4.1. Procedure Continuation Abstraction

The heart of the driver/library interface is the continuation class. Note the message pointer is an abstract address and must be cast to the right type by client drivers.
Start cpp section to rtl/flx_rtl.hpp[1 /1 ]
     1: #line 790 "./lpsrc/flx_rtl.pak"
     2: #ifndef FLX_RTL
     3: #define FLX_RTL
     4: #include "flx_rtl_config.hpp"
     5: #include "flx_meta.hpp"
     6: #ifndef FLX_GC
     7: #include "flx_gc.hpp"
     8: #endif
     9: #include <string>
    10: #include <functional>
    11: 
    12: #if defined(FLX_PTF_STATIC_STRUCT)
    13: #define PTF ptf.
    14: #elif defined(FLX_PTF_STATIC_POINTER)
    15: #define PTF ptf->
    16: #else
    17: #define PTF ptf->
    18: #endif
    19: 
    20: // for declarations in header file
    21: #if defined(FLX_PTF_STATIC_STRUCT)
    22: #define FLX_FMEM_DECL
    23: #define FLX_FPAR_DECL_ONLY
    24: #define FLX_FPAR_DECL
    25: #define FLX_APAR_DECL_ONLY
    26: #define FLX_APAR_DECL
    27: #define FLX_DCL_THREAD_FRAME extern thread_frame_t ptf;
    28: #elif defined(FLX_PTF_STATIC_POINTER)
    29: #define FLX_FMEM_DECL
    30: #define FLX_FPAR_DECL_ONLY
    31: #define FLX_FPAR_DECL
    32: #define FLX_APAR_DECL_ONLY
    33: #define FLX_APAR_DECL
    34: #define FLX_DCL_THREAD_FRAME extern thread_frame_t *ptf;
    35: #else
    36: #define FLX_FMEM_DECL thread_frame_t *ptf;
    37: #define FLX_FPAR_DECL_ONLY thread_frame_t *_ptf
    38: #define FLX_FPAR_DECL thread_frame_t *_ptf,
    39: #define FLX_APAR_DECL_ONLY thread_frame_t *ptf
    40: #define FLX_APAR_DECL thread_frame_t *ptf,
    41: #define FLX_DCL_THREAD_FRAME
    42: #endif
    43: 
    44: namespace flx { namespace rtl {
    45: 
    46: // ********************************************************
    47: // Felix system classes
    48: // ********************************************************
    49: 
    50: struct RTL_EXTERN con_t;     // continuation
    51: struct RTL_EXTERN thread_t; // f-thread
    52: struct RTL_EXTERN _ref_;     // pointer/reference
    53: struct RTL_EXTERN _uctor_;   // union constructor
    54: struct RTL_EXTERN schannel_t;   // synchronous channel type
    55: struct RTL_EXTERN slist_t;   // singly linked list of void*
    56: struct RTL_EXTERN _root_ptr_t;   // singly linked list of void*
    57: 
    58: struct RTL_EXTERN unit {};   // unit
    59:   // INLINE DEFINITION, PROBLEMATIC!!
    60: 
    61: // ********************************************************
    62: // Shape (RTTI) objects for system classes
    63: // con_t is only an abstract base, so has no fixed shape
    64: // shapes for instance types generated by Felix compiler
    65: // we provide a shape for C 'int' type as well
    66: // ********************************************************
    67: 
    68: RTL_EXTERN extern flx::gc::generic::gc_shape_t _fthread_ptr_map;
    69: RTL_EXTERN extern flx::gc::generic::gc_shape_t schannel_ptr_map;
    70: RTL_EXTERN extern flx::gc::generic::gc_shape_t _ref_ptr_map;
    71: RTL_EXTERN extern flx::gc::generic::gc_shape_t _uctor_ptr_map;
    72: RTL_EXTERN extern flx::gc::generic::gc_shape_t _int_ptr_map;
    73: RTL_EXTERN extern flx::gc::generic::gc_shape_t unit_ptr_map;
    74: RTL_EXTERN extern flx::gc::generic::gc_shape_t slist_ptr_map;
    75: RTL_EXTERN extern flx::gc::generic::gc_shape_t _root_ptr_ptr_map;
    76: 
    77: // ********************************************************
    78: // Standard C++ Exceptions
    79: // ********************************************************
    80: 
    81: struct RTL_EXTERN flx_exception_t;
    82: struct RTL_EXTERN flx_exec_failure_t;
    83: struct RTL_EXTERN flx_range_srcref_t;
    84: struct RTL_EXTERN flx_match_failure_t;
    85: struct RTL_EXTERN flx_assert_failure_t;
    86: struct RTL_EXTERN flx_assert2_failure_t;
    87: struct RTL_EXTERN flx_switch_failure_t;
    88: // ********************************************************
    89: /// CONTINUATION.
    90: // ********************************************************
    91: 
    92: struct RTL_EXTERN con_t ///< abstract base for mutable continuations
    93: {
    94: #ifdef FLX_CGOTO
    95:   void *pc;                 ///< interior program counter
    96: #else
    97:    int pc;
    98: #endif
    99: 
   100:   _uctor_ *p_svc;           ///< pointer to service request
   101: 
   102:   con_t();                  ///< initialise pc, p_svc to 0
   103:   virtual con_t *resume()=0;///< method to perform a computational step
   104:   virtual ~con_t();
   105:   con_t * _caller;          ///< callers continuation (return address)
   106: };
   107: 
   108: // ********************************************************
   109: /// SLIST. singly linked lists: SHARABLE and COPYABLE
   110: /// SLIST manages pointers to memory managed by the collector
   111: // ********************************************************
   112: 
   113: struct RTL_EXTERN slist_t {
   114:   gc::generic::collector_t *gc;
   115:   struct slist_node_t *head;
   116: 
   117:   slist_t (gc::generic::collector_t *); ///< create empty list
   118:   slist_t (slist_t const &);            ///< shallow copy
   119: 
   120:   void push(void *data);                ///< push a gc pointer
   121:   void *pop();                          ///< pop a gc pointer
   122:   bool isempty()const;
   123: };
   124: 
   125: // ********************************************************
   126: /// FTHREAD. Felix threads
   127: // ********************************************************
   128: 
   129: struct RTL_EXTERN fthread_t // fthread abstraction
   130: {
   131:   con_t *cc;                    ///< current continuation
   132: 
   133:   fthread_t();                  ///< dead thread, suitable for assignment
   134:   fthread_t(con_t*);            ///< make thread from a continuation
   135:   _uctor_ *run();               ///< run until dead or driver service request
   136:   void kill();                  ///< kill by detaching the continuation
   137:   _uctor_ *get_svc()const;      ///< get current service request of waiting thread
   138: private: // uncopyable
   139:   fthread_t(fthread_t const&);
   140:   void operator=(fthread_t const&);
   141: };
   142: 
   143: // ********************************************************
   144: /// SCHANNEL. Synchronous channels
   145: // ********************************************************
   146: 
   147: struct RTL_EXTERN schannel_t
   148: {
   149:   slist_t *waiting_to_read;             ///< fthreads waiting for a writer
   150:   slist_t *waiting_to_write;            ///< fthreads waiting for a reader
   151:   schannel_t(gc::generic::collector_t*);
   152:   void push_reader(fthread_t *);        ///< add a reader
   153:   fthread_t *pop_reader();              ///< pop a reader, NULL if none
   154:   void push_writer(fthread_t *);        ///< add a writer
   155:   fthread_t *pop_writer();              ///< pop a writer, NULL if none
   156: private: // uncopyable
   157:   schannel_t(schannel_t const&);
   158:   void operator= (schannel_t const&);
   159: };
   160: 
   161: // ********************************************************
   162: /// REFERENCE. Felix pointer type
   163: /// note: non-polymorphic, so ctor can be inline
   164: /// This type is used to represent pointers to variables.
   165: /// It has two components: a frame pointer and offset.
   166: /// A whole frame is refered to by setting the offset to 0.
   167: /// A non-collectable pointer is refered to by setting the frame to 0
   168: /// References are first class values: they can copied, assigned,
   169: /// and default constructed. Holding a reference in a location
   170: /// known to the gc ensures the target variable is not collected:
   171: /// Such references cannot dangle.
   172: /// The frame/offset representation was chosen since it fits
   173: /// well with a copying collector: the price is that finding
   174: /// the interior pointer requires adding the offset to the frame
   175: /// pointer. Note that 'frame' points to the CLIENTDATA address
   176: /// of a frame where user data starts: this is not the lowest
   177: /// machine address of the frame's allocated memory or FRAME
   178: /// address, despite the name.
   179: // ********************************************************
   180: 
   181: struct RTL_EXTERN _ref_
   182: {
   183:   void *frame;      ///< Heap frame pointer
   184:   std::ptrdiff_t offset;   ///< Client Data offset
   185: 
   186:   _ref_() : frame(0),offset(0) {} ///< NULL reference
   187:   _ref_(void *f, void *d):
   188:     frame(f), offset((unsigned char*)d-(unsigned char*)f) {}
   189:       ///< init from interior pointer d of a collectable frame f
   190: 
   191:   _ref_(void *f, std::ptrdiff_t d):
   192:     frame(f), offset(d) {} ///< init from collectable frame f and offset d
   193: 
   194:   _ref_(_ref_ const& r) : frame(r.frame), offset(r.offset) {}
   195:     ///< copy constructor
   196: 
   197:   void operator = (_ref_ const& r); ///< assignment operator
   198: 
   199:   void *get_data()const { return (unsigned char*)frame + offset; }
   200:     ///< get interior pointer
   201: 
   202:   void set_data(void *p)
   203:     { offset = (unsigned char*)p - (unsigned char*)frame; }
   204:     ///< set interior pointer into same frame
   205: 
   206:   void set(void *f, void *p)
   207:   { frame = f; offset = (unsigned char*)p - (unsigned char*)f; } ///< set from frame f and interior pointer
   208: };
   209: 
   210: 
   211: // ********************************************************
   212: /// VARIANTS. Felix union type
   213: /// note: non-polymorphic, so ctor can be inline
   214: // ********************************************************
   215: 
   216: struct RTL_EXTERN _uctor_
   217: {
   218:   int variant;  ///< Variant code
   219:   void *data;   ///< Heap variant constructor data
   220:   _uctor_() : variant(-1), data(0) {}
   221:   _uctor_(int i, void *d) : variant(i), data(d) {}
   222:   _uctor_(int *a, _uctor_ x) : variant(a[x.variant]), data(x.data) {}
   223: };
   224: 
   225: // ********************************************************
   226: /// ROOT POINTER.
   227: /// Use to chain pseudo roots together. Generally scannable
   228: /// but not collectable.
   229: // ********************************************************
   230: 
   231: struct RTL_EXTERN _root_ptr_t
   232: {
   233:   _root_ptr_t();
   234:   _root_ptr_t(void *x);
   235:   _root_ptr_t(_root_ptr_t const&);
   236:   void operator=(_root_ptr_t const&);
   237:   ~_root_ptr_t();
   238: 
   239:   _root_ptr_t *next;
   240:   _root_ptr_t *prev;
   241:   void *data;
   242: 
   243: private:
   244:   void insert_after (_root_ptr_t*);
   245:   void erase();
   246: };
   247: 
   248: // INLINE! All casts
   249: template<class T>
   250: struct root_ptr_t : _root_ptr_t {
   251:   root_ptr_t(){}
   252:   root_ptr_t(root_ptr_t<T> const&){}
   253:   root_ptr_t<T>& operator=(root_ptr_t<T> const &a){
   254:     return reinterpret_cast<root_ptr_t<T>&>(_root_ptr_t::operator=(a));
   255:   }
   256:  ~root_ptr_t(){}
   257: 
   258:   root_ptr_t(T const *a) : _root_ptr_t (const_cast<T*>(a)) {}
   259: 
   260:   T *operator->() { return (T*)data; }
   261:   T const *operator->() const { return (T const*)data; }
   262:   T &operator*() { return *(T*)data; }
   263:   T const &operator*() const { return *(T const*)data; }
   264: };
   265: 
   266: template<class T>
   267: bool operator == (root_ptr_t<T> a, root_ptr_t<T> b)
   268: {
   269:   return a-> data == b->data;
   270: }
   271: 
   272: template<class T>
   273: bool operator != (root_ptr_t<T> a, root_ptr_t<T> b)
   274: {
   275:   return a-> data != b->data;
   276: }
   277: 
   278: template<class T>
   279: bool operator < (root_ptr_t<T> const &a, root_ptr_t<T> const &b)
   280: {
   281:   // we use this because it enforces a total order
   282:   return std::less<void const*>()(a-> data, b->data);
   283: }
   284: 
   285: template<class T>
   286: bool operator <= (root_ptr_t<T> const &a, root_ptr_t<T> const &b)
   287: {
   288:   // we use this because it enforces a total order
   289:   return std::less_equal<void const*>()(a-> data, b->data);
   290: }
   291: 
   292: template<class T>
   293: bool operator > (root_ptr_t<T> const &a, root_ptr_t<T> const &b)
   294: {
   295:   // we use this because it enforces a total order
   296:   return std::greater<void const*>()(a-> data, b->data);
   297: }
   298: 
   299: template<class T>
   300: bool operator >= (root_ptr_t<T> const &a, root_ptr_t<T> const &b)
   301: {
   302:   // we use this because it enforces a total order
   303:   return std::greater_equal<void const*>()(a-> data, b->data);
   304: }
   305: 
   306: 
   307: // ********************************************************
   308: /// EXCEPTION: Felix exception base abstraction.
   309: /// Mainly used to convert catches into subroutine
   310: /// calls which then dispatch on RTTI manually.
   311: // ********************************************************
   312: 
   313: struct RTL_EXTERN flx_exception_t {
   314:   virtual ~flx_exception_t()=0;
   315: };
   316: 
   317: // ********************************************************
   318: /// EXCEPTION: EXEC protocol failure.
   319: /// Thrown when trying to run a dead procedure
   320: // ********************************************************
   321: 
   322: struct RTL_EXTERN flx_exec_failure_t : flx_exception_t {
   323:   std::string filename;  ///< dll filename
   324:   std::string operation; ///< faulty operation
   325:   std::string what;      ///< error description
   326:   flx_exec_failure_t(std::string f, std::string o, std::string w);
   327:   virtual ~flx_exec_failure_t();
   328: };
   329: 
   330: // ********************************************************
   331: /// SOURCE REFERENCE: to track places in user source code.
   332: // ********************************************************
   333: 
   334: struct RTL_EXTERN flx_range_srcref_t {
   335:   char *filename;  ///< source file name
   336:   int startline;   ///< first line (1 origin)
   337:   int startcol;    ///< first column (1 origin)
   338:   int endline;     ///< last line
   339:   int endcol;      ///< last column
   340:   flx_range_srcref_t(char *f,int sl, int sc, int el, int ec);
   341:   flx_range_srcref_t();
   342: };
   343: 
   344: // ********************************************************
   345: /// EXCEPTION: MATCH failure.
   346: /// Thrown when no match cases match the argument of a match,
   347: /// regmatch, or reglex
   348: // ********************************************************
   349: 
   350: struct RTL_EXTERN flx_match_failure_t : flx_exception_t {
   351:   flx_range_srcref_t flx_loc; ///< location in Felix file
   352:   char *cxx_srcfile;          ///< C++ file name
   353:   int cxx_srcline;            ///< C++ line number
   354:   flx_match_failure_t(flx_range_srcref_t ff, char *cf, int cl);
   355:   virtual ~flx_match_failure_t();
   356: };
   357: 
   358: // ********************************************************
   359: /// EXCEPTION: ASSERT failure.
   360: /// Thrown when user assertion fails
   361: // ********************************************************
   362: 
   363: struct RTL_EXTERN flx_assert_failure_t : flx_exception_t {
   364:   flx_range_srcref_t flx_loc; ///< location in Felix file
   365:   char *cxx_srcfile;          ///< C++ file
   366:   int cxx_srcline;            ///< __LINE__ macro
   367:   flx_assert_failure_t(flx_range_srcref_t ff, char *cf, int cl);
   368:   virtual ~flx_assert_failure_t();
   369: };
   370: 
   371: struct RTL_EXTERN flx_assert2_failure_t : flx_exception_t {
   372:   flx_range_srcref_t flx_loc; ///< location in Felix file
   373:   flx_range_srcref_t flx_loc2; ///< second location in Felix file
   374:   char *cxx_srcfile;          ///< C++ file
   375:   int cxx_srcline;            ///< __LINE__ macro
   376:   flx_assert2_failure_t(flx_range_srcref_t ff, flx_range_srcref_t ff2, char *cf, int cl);
   377:   virtual ~flx_assert2_failure_t();
   378: };
   379: 
   380: // ********************************************************
   381: /// EXCEPTION: RANGE failure.
   382: /// Thrown when a range check fails
   383: // ********************************************************
   384: 
   385: struct RTL_EXTERN flx_range_failure_t : flx_exception_t {
   386:   flx_range_srcref_t flx_loc; ///< location in Felix file
   387:   char *cxx_srcfile;          ///< C++ file
   388:   int cxx_srcline;            ///< __LINE__ macro
   389:   flx_range_failure_t(flx_range_srcref_t ff, char *cf, int cl);
   390:   virtual ~flx_range_failure_t();
   391: };
   392: 
   393: RTL_EXTERN long range_check (long l, long x, long h, flx_range_srcref_t sref, char *cf, int cl);
   394: 
   395: 
   396: // ********************************************************
   397: /// EXCEPTION: SWITCH failure. this is a system failure!
   398: // ********************************************************
   399: 
   400: struct RTL_EXTERN flx_switch_failure_t : flx_exception_t {
   401:   virtual ~flx_switch_failure_t();
   402: };
   403: 
   404: 
   405: // ********************************************************
   406: // SERVICE REQUEST CODE
   407: // THESE VALUES MUST SYNCH WITH THE STANDARD LIBRARY
   408: // ********************************************************
   409: 
   410: enum svc_t               // what the dispatch should do
   411: {                        // when the resume callback returns
   412:   svc_yield = 0,
   413:   svc_get_fthread=1,
   414:   svc_read=2,
   415:   svc_general=3,         // temporary hack by RF
   416:   svc_reserved=4,
   417:   svc_spawn_pthread=5,
   418:   svc_spawn_detached=6,
   419:   svc_sread=7,           // synchronous read
   420:   svc_swrite=8,          // synchronous write
   421:   svc_kill=9,           // kill fthread
   422:   svc_compact=10,        // run compactor
   423:   svc_collect=11,        // run collector
   424:   svc_collect_and_compact=12,        // run collector and compactor
   425:   svc_end
   426: };
   427: 
   428: struct readreq_t {
   429:   schannel_t *chan;
   430:   _ref_ variable;
   431: };
   432: 
   433: }} // namespaces
   434: 
   435: #define FLX_MATCH_FAILURE(f,sl,sc,el,ec) \
   436:   throw flx::rtl::flx_match_failure_t (flx_range_srcref_t(f,sl,sc,el,ec),__FILE__,__LINE__)
   437: 
   438: #define FLX_ASSERT_FAILURE(f,sl,sc,el,ec) \
   439:   throw flx::rtl::flx_assert_failure_t (flx_range_srcref_t(f,sl,sc,el,ec),__FILE__,__LINE__)
   440: 
   441: #define FLX_ASSERT2_FAILURE(f,sl,sc,el,ec,f2,sl2,sc2,el2,ec2) \
   442:   throw flx::rtl::flx_assert2_failure_t (\
   443:     flx_range_srcref_t(f,sl,sc,el,ec),\
   444:     flx_range_srcref_t(f2,sl2,sc2,el2,sc2),\
   445:     __FILE__,__LINE__)
   446: 
   447: #define FLX_RANGE_FAILURE(f,sl,sc,el,ec) \
   448:   throw flx::rtl::flx_range_failure_t (flx_range_srcref_t(f,sl,sc,el,ec),__FILE__,__LINE__)
   449: 
   450: // for generated code in body file
   451: #define INIT_PC pc=0;
   452: 
   453: #ifdef FLX_CGOTO
   454:   #define FLX_START_SWITCH if(pc)goto *pc;
   455:   #define FLX_SET_PC(x) pc=&&case_##x;
   456:   #define FLX_CASE_LABEL(x) case_##x:;
   457:   #define FLX_DECLARE_LABEL(n,i,x) \
   458:     extern void f##i##_##n##_##x(void) __asm__("l"#i"_"#n"_"#x);
   459:   #define FLX_LABEL(n,i,x) x:\
   460:     __asm__(".global l"#i"_"#n"_"#x);\
   461:     __asm__("l"#i"_"#n"_"#x":");\
   462:     __asm__(""::"g"(&&x));
   463:   #define FLX_FARTARGET(n,i,x) (void*)&f##i##_##n##_##x
   464:   #define FLX_END_SWITCH
   465: #else
   466:   #define FLX_START_SWITCH switch(pc){case 0:;
   467:   #define FLX_SET_PC(x) pc=x;
   468:   #define FLX_CASE_LABEL(x) case x:;
   469:   #define FLX_DECLARE_LABEL(n,i,x)
   470:   #define FLX_LABEL(n,i,x) case n: x:;
   471:   #define FLX_FARTARGET(n,i,x) n
   472:   #define FLX_END_SWITCH default: throw flx_switch_failure_t(); }
   473: #endif
   474: 
   475: #define FLX_RETURN \
   476: { \
   477:   con_t *tmp = _caller; \
   478:   _caller = 0; \
   479:   return tmp; \
   480: }
   481: 
   482: #define FLX_NEWP(x) new(*PTF gc,x##_ptr_map)x
   483: 
   484: #define FLX_FINALISER(x) \
   485: static void x##_finaliser(collector_t *, void *p){\
   486:   ((x*)p)->~x();\
   487: }
   488: 
   489: #if defined(FLX_USE_REGPARM3) && defined(HAVE_GNU_X86)
   490: #define FLX_REGPARM __attribute__((regparm(3)))
   491: #else
   492: #define FLX_REGPARM
   493: #endif
   494: 
   495: #if defined(FLX_PTF_STATIC_STRUCT)
   496: #define FLX_FMEM_INIT_ONLY
   497: #define FLX_FMEM_INIT :
   498: #define FLX_FPAR_PASS_ONLY
   499: #define FLX_FPAR_PASS
   500: #define FLX_APAR_PASS_ONLY
   501: #define FLX_APAR_PASS
   502: #define _PTF _ptf.
   503: #define _PTFV
   504: #define FLX_PASS_PTF 0
   505: #define FLX_EAT_PTF(x)
   506: #define FLX_DEF_THREAD_FRAME thread_frame_t ptf;
   507: #elif defined(FLX_PTF_STATIC_POINTER)
   508: #define FLX_FMEM_INIT_ONLY
   509: #define FLX_FMEM_INIT :
   510: #define FLX_FPAR_PASS_ONLY
   511: #define FLX_FPAR_PASS
   512: #define FLX_APAR_PASS_ONLY
   513: #define FLX_APAR_PASS
   514: #define _PTF _ptf->
   515: #define _PTFV
   516: #define FLX_PASS_PTF 0
   517: #define FLX_EAT
   518: #define FLX_DEF_THREAD_FRAME thread_frame_t *ptf=0;
   519: #else
   520: #define FLX_FMEM_INIT_ONLY : ptf(_ptf)
   521: #define FLX_FMEM_INIT : ptf(_ptf),
   522: #define FLX_FPAR_PASS_ONLY ptf
   523: #define FLX_FPAR_PASS ptf,
   524: #define FLX_APAR_PASS_ONLY _ptf
   525: #define FLX_APAR_PASS _ptf,
   526: #define _PTF _ptf->
   527: #define _PTFV _ptf
   528: #define FLX_PASS_PTF 1
   529: #define FLX_EAT_PTF(x) x
   530: #define FLX_DEF_THREAD_FRAME
   531: #endif
   532: 
   533: #if defined(FLX_PTF_STATIC_STRUCT)
   534: #define FLX_FRAME_WRAPPERS(mname) \
   535: extern "C" thread_frame_t *create_thread_frame(\
   536:   collector_t *gc\
   537: ) {\
   538:   ptf.gc = gc;\
   539:   return &ptf;\
   540: }
   541: #elif defined(FLX_PTF_STATIC_POINTER)
   542: #define FLX_FRAME_WRAPPERS(mname) \
   543: extern "C" thread_frame_t *create_thread_frame(\
   544:   collector_t *gc\
   545: ) {\
   546:   mname::thread_frame_t *p = new(*gc,mname::thread_frame_t_ptr_map) mname::thread_frame_t(gc);\
   547:   ptf = p;\
   548:   return p;\
   549: }
   550: #else
   551: #define FLX_FRAME_WRAPPERS(mname) \
   552: extern "C" FLX_EXPORT mname::thread_frame_t *create_thread_frame(\
   553:   collector_t *gc\
   554: ) {\
   555:   mname::thread_frame_t *p = new(*gc,mname::thread_frame_t_ptr_map) mname::thread_frame_t(gc);\
   556:   return p;\
   557: }
   558: #endif
   559: 
   560: #if defined(FLX_PTF_STATIC_STRUCT)
   561: #define FLX_START_WRAPPER(mname,x)\
   562: extern "C" con_t *flx_start(\
   563:   mname::thread_frame_t *ptf,\
   564:   int argc,\
   565:   char **argv,\
   566:   FILE *stdin_,\
   567:   FILE *stdout_,\
   568:   FILE *stderr_\
   569: ) {\
   570:   ptf->argc = argc;\
   571:   ptf->argv = argv;\
   572:   ptf->flx_stdin = stdin_;\
   573:   ptf->flx_stdout = stdout_;\
   574:   ptf->flx_stderr = stderr_;\
   575:   return (new(*ptf->gc,mname::x##_ptr_map) \
   576:     mname::x()) ->call(0);\
   577: }
   578: #elif defined(FLX_PTF_STATIC_POINTER)
   579: #define FLX_START_WRAPPER(mname,x)\
   580: extern "C" con_t *flx_start(\
   581:   mname::thread_frame_t *ptf,\
   582:   int argc,\
   583:   char **argv,\
   584:   FILE *stdin_,\
   585:   FILE *stdout_,\
   586:   FILE *stderr_\
   587: ) {\
   588:   ptf->argc = argc;\
   589:   ptf->argv = argv;\
   590:   ptf->flx_stdin = stdin_;\
   591:   ptf->flx_stdout = stdout_;\
   592:   ptf->flx_stderr = stderr_;\
   593:   return (new(*ptf->gc,mname::x##_ptr_map) \
   594:     mname::x()) ->call(0);\
   595: }
   596: #else
   597: #define FLX_START_WRAPPER(mname,x)\
   598: extern "C" FLX_EXPORT con_t *flx_start(\
   599:   mname::thread_frame_t *ptf,\
   600:   int argc,\
   601:   char **argv,\
   602:   FILE *stdin_,\
   603:   FILE *stdout_,\
   604:   FILE *stderr_\
   605: ) {\
   606:   ptf->argc = argc;\
   607:   ptf->argv = argv;\
   608:   ptf->flx_stdin = stdin_;\
   609:   ptf->flx_stdout = stdout_;\
   610:   ptf->flx_stderr = stderr_;\
   611:   return (new(*ptf->gc,mname::x##_ptr_map) \
   612:     mname::x(ptf)) ->call(0);\
   613: }
   614: #endif
   615: 
   616: #if defined(FLX_PTF_STATIC_STRUCT)
   617: #define FLX_STACK_START_WRAPPER(mname,x)\
   618: extern "C" con_t *flx_start(\
   619:   mname::thread_frame_t *ptf,\
   620:   int argc,\
   621:   char **argv,\
   622:   FILE *stdin_,\
   623:   FILE *stdout_,\
   624:   FILE *stderr_\
   625: ) {\
   626:   ptf->argc = argc;\
   627:   ptf->argv = argv;\
   628:   ptf->flx_stdin = stdin_;\
   629:   ptf->flx_stdout = stdout_;\
   630:   ptf->flx_stderr = stderr_;\
   631:   mname::x().stack_call();\
   632:   return 0;\
   633: }
   634: #elif defined(FLX_PTF_STATIC_POINTER)
   635: #define FLX_STACK_START_WRAPPER(mname,x)\
   636: extern "C" con_t *flx_start(\
   637:   mname::thread_frame_t *ptf,\
   638:   int argc,\
   639:   char **argv,\
   640:   FILE *stdin_,\
   641:   FILE *stdout_,\
   642:   FILE *stderr_\
   643: ) {\
   644:   ptf->argc = argc;\
   645:   ptf->argv = argv;\
   646:   ptf->flx_stdin = stdin_;\
   647:   ptf->flx_stdout = stdout_;\
   648:   ptf->flx_stderr = stderr_;\
   649:   mname::x().stack_call();\
   650:   return 0;\
   651: }
   652: #else
   653: #define FLX_STACK_START_WRAPPER(mname,x)\
   654: extern "C" FLX_EXPORT con_t *flx_start(\
   655:   mname::thread_frame_t *ptf,\
   656:   int argc,\
   657:   char **argv,\
   658:   FILE *stdin_,\
   659:   FILE *stdout_,\
   660:   FILE *stderr_\
   661: ) {\
   662:   ptf->argc = argc;\
   663:   ptf->argv = argv;\
   664:   ptf->flx_stdin = stdin_;\
   665:   ptf->flx_stdout = stdout_;\
   666:   ptf->flx_stderr = stderr_;\
   667:   mname::x(ptf).stack_call();\
   668:   return 0;\
   669: }
   670: #endif
   671: 
   672: #if defined(FLX_PTF_STATIC_STRUCT)
   673: #define FLX_C_START_WRAPPER(mname,x)\
   674: extern "C" con_t *flx_start(\
   675:   mname::thread_frame_t *ptf,\
   676:   int argc,\
   677:   char **argv,\
   678:   FILE *stdin_,\
   679:   FILE *stdout_,\
   680:   FILE *stderr_\
   681: ) {\
   682:   ptf->argc = argc;\
   683:   ptf->argv = argv;\
   684:   ptf->flx_stdin = stdin_;\
   685:   ptf->flx_stdout = stdout_;\
   686:   ptf->flx_stderr = stderr_;\
   687:   mname::x();\
   688:   return 0;\
   689: }
   690: #elif defined(FLX_PTF_STATIC_POINTER)
   691: #define FLX_C_START_WRAPPER(mname,x)\
   692: extern "C" con_t *flx_start(\
   693:   mname::thread_frame_t *ptf,\
   694:   int argc,\
   695:   char **argv,\
   696:   FILE *stdin_,\
   697:   FILE *stdout_,\
   698:   FILE *stderr_\
   699: ) {\
   700:   ptf->argc = argc;\
   701:   ptf->argv = argv;\
   702:   ptf->flx_stdin = stdin_;\
   703:   ptf->flx_stdout = stdout_;\
   704:   ptf->flx_stderr = stderr_;\
   705:   mname::x();\
   706:   return 0;\
   707: }
   708: #else
   709: #define FLX_C_START_WRAPPER(mname,x)\
   710: extern "C" FLX_EXPORT con_t *flx_start(\
   711:   mname::thread_frame_t *ptf,\
   712:   int argc,\
   713:   char **argv,\
   714:   FILE *stdin_,\
   715:   FILE *stdout_,\
   716:   FILE *stderr_\
   717: ) {\
   718:   ptf->argc = argc;\
   719:   ptf->argv = argv;\
   720:   ptf->flx_stdin = stdin_;\
   721:   ptf->flx_stdout = stdout_;\
   722:   ptf->flx_stderr = stderr_;\
   723:   mname::x(ptf);\
   724:   return 0;\
   725: }
   726: #endif
   727: 
   728: #endif
   729: 
End cpp section to rtl/flx_rtl.hpp[1]
Start cpp section to rtl/flx_rtl.cpp[1 /1 ]
     1: #line 1520 "./lpsrc/flx_rtl.pak"
     2: #include "flx_rtl.hpp"
     3: #include <cstdio>
     4: #include <cassert>
     5: 
     6: namespace flx { namespace rtl {
     7: 
     8: // ********************************************************
     9: // con_t implementation
    10: // ********************************************************
    11: 
    12: con_t::con_t() : pc(0), p_svc(0), _caller(0) {
    13: #ifdef FLX_DEBUG_CONT
    14:  fprintf(stderr,"Constructing %p\n",this);
    15: #endif
    16: }
    17: con_t::~con_t(){
    18: #ifdef FLX_DEBUG_CONT
    19:   fprintf(stderr,"Destroying %p\n",this);
    20: #endif
    21: }
    22: 
    23: // ********************************************************
    24: // slist implementation
    25: // ********************************************************
    26: 
    27: // PRIVATE to the slist_t class!
    28: struct slist_node_t {
    29:   slist_node_t *next;
    30:   void *data;
    31:   slist_node_t(slist_node_t *n, void *d) : next(n), data(d) {}
    32: };
    33: 
    34: //OFFSETS for slist_node_t
    35: static std::size_t slist_node_offsets[2]={
    36:     offsetof(slist_node_t,next),
    37:     offsetof(slist_node_t,data)
    38: };
    39: 
    40: flx::gc::generic::gc_shape_t slist_node_ptr_map(
    41:   NULL,
    42:   "slist_node_t",
    43:   1,sizeof(slist_node_t),
    44:   0, // no finaliser,
    45:   2,
    46:   slist_node_offsets
    47: );
    48: 
    49: 
    50: slist_t::slist_t(gc::generic::collector_t *_gc) : gc (_gc), head(0) {}
    51: slist_t::slist_t(slist_t const &r) : gc (r.gc), head(r.head) {}
    52: 
    53: bool slist_t::isempty()const { return head == 0; }
    54: 
    55: void slist_t::push(void *data)
    56: {
    57:   head = new(*gc,slist_node_ptr_map) slist_node_t(head,data);
    58: }
    59: 
    60: // note: never fails, return NULL pointer if the list is empty
    61: void *slist_t::pop()
    62: {
    63:   if(head) {
    64:     void *data = head->data;
    65:     head=head->next;
    66:     return data;
    67:   }
    68:   else return 0;
    69: }
    70: 
    71: //OFFSETS for slist_t
    72: static std::size_t slist_offsets[1]={
    73:     offsetof(slist_t,head)
    74: };
    75: 
    76: flx::gc::generic::gc_shape_t slist_ptr_map(
    77:   &slist_node_ptr_map,
    78:   "slist_t",
    79:   1,sizeof(slist_t),
    80:   0, // no finaliser
    81:   1,
    82:   slist_offsets
    83: );
    84: 
    85: // ********************************************************
    86: // _root_ptr_t implementation
    87: // ********************************************************
    88: 
    89: _root_ptr_t::_root_ptr_t() : next(0), prev(0), data(0) {}
    90: _root_ptr_t::_root_ptr_t(void *x) : next(0), prev(0), data(x) {}
    91: _root_ptr_t::~_root_ptr_t() { erase(); }
    92: 
    93: void _root_ptr_t::insert_after(_root_ptr_t *a) {
    94:   prev = a;
    95:   next = prev->next;
    96:   prev->next = this;
    97:   if(next)next->prev = this;
    98:   data = next->data;
    99: }
   100: 
   101: _root_ptr_t::_root_ptr_t(_root_ptr_t const &a) {
   102:   insert_after(const_cast<_root_ptr_t*>(&a));
   103: }
   104: 
   105: void _root_ptr_t::operator=(_root_ptr_t const &a) {
   106:   if (&a != this)
   107:   {
   108:     erase();
   109:     insert_after(const_cast<_root_ptr_t*>(&a));
   110:   }
   111: }
   112: 
   113: //OFFSETS for root_ptr_t
   114: static std::size_t _root_ptr_offsets[3]={
   115:     offsetof(_root_ptr_t,next),
   116:     offsetof(_root_ptr_t,prev),
   117:     offsetof(_root_ptr_t,data)
   118: };
   119: 
   120: flx::gc::generic::gc_shape_t _root_ptr_ptr_map(
   121:   &slist_ptr_map,
   122:   "_root_ptr_t",
   123:   1,sizeof(_root_ptr_t),
   124:   0, // no finaliser
   125:   1,
   126:   _root_ptr_offsets
   127: );
   128: 
   129: void _root_ptr_t::erase() {
   130:   next->prev = prev;
   131:   prev->next = next;
   132:   next = 0; prev = 0;
   133:   data = 0;
   134: }
   135: 
   136: // ********************************************************
   137: // fthread_t implementation
   138: // ********************************************************
   139: 
   140: fthread_t::fthread_t() : cc(0) {}
   141: fthread_t::fthread_t(con_t *a) : cc(a) {}
   142: 
   143: // uncopyable object but implementation needed for linker
   144: fthread_t::fthread_t(fthread_t const&){ assert(false); }
   145: void fthread_t::operator=(fthread_t const&){ assert(false); }
   146: 
   147: void fthread_t::kill() { cc = 0; }
   148: 
   149: _uctor_ *fthread_t::get_svc()const { return cc?cc->p_svc:0; }
   150: 
   151: _uctor_ *fthread_t::run() {
   152:   if(!cc) return 0; // dead
   153: restep:
   154:   cc->p_svc = 0;
   155: step:
   156:   //fprintf(stderr,"cc=%p->",cc);
   157:   try { cc = cc->resume(); }
   158:   catch (con_t *x) { cc = x; }
   159: 
   160:   //fprintf(stderr,"->%p\n",cc);
   161:   if(!cc) return 0; // died
   162: 
   163:   if(cc->p_svc)
   164:   {
   165:     switch(cc->p_svc->variant)
   166:     {
   167:       case svc_get_fthread:
   168:         **(fthread_t***)(cc->p_svc->data) = this;
   169:         goto restep;      // handled
   170: 
   171:       //case svc_yield:
   172:       //  goto restep;
   173: 
   174:       // we don't know what to do with the request,
   175:       // so pass the buck to the driver
   176:       default:
   177:         return cc->p_svc;
   178:     }
   179:   }
   180:   goto step;
   181: }
   182: 
   183: 
   184: //OFFSETS for fthread_t
   185: static std::size_t _fthread_offsets[1]={
   186:     offsetof(fthread_t,cc)
   187: };
   188: 
   189: flx::gc::generic::gc_shape_t _fthread_ptr_map(
   190:   &_root_ptr_ptr_map,
   191:   "fthread_t",
   192:   1,sizeof(fthread_t),
   193:   0,
   194:   1,
   195:   _fthread_offsets,
   196:   gc::generic::gc_flags_immobile
   197: );
   198: 
   199: // ********************************************************
   200: // schannel_t implementation
   201: // ********************************************************
   202: 
   203: schannel_t::schannel_t (gc::generic::collector_t *gc) :
   204:   waiting_to_read(0), waiting_to_write(0)
   205: {
   206:   waiting_to_read = new (*gc, slist_ptr_map) slist_t(gc);
   207:   waiting_to_write = new (*gc, slist_ptr_map) slist_t(gc);
   208: }
   209: 
   210: // uncopyable object but implementation needed for linker
   211: schannel_t::schannel_t(schannel_t const&) { assert(false); }
   212: void schannel_t::operator=(schannel_t const&) { assert(false); }
   213: 
   214: void schannel_t::push_reader(fthread_t *r)
   215: {
   216:   waiting_to_read->push(r);
   217: }
   218: 
   219: void schannel_t::push_writer(fthread_t *w)
   220: {
   221:   waiting_to_write->push(w);
   222: }
   223: 
   224: fthread_t *schannel_t::pop_reader()
   225: {
   226:   return (fthread_t*)waiting_to_read->pop();
   227: }
   228: 
   229: fthread_t *schannel_t::pop_writer()
   230: {
   231:   return (fthread_t*)waiting_to_write->pop();
   232: }
   233: 
   234: //OFFSETS for schannel_t
   235: static std::size_t schannel_offsets[2]={
   236:     offsetof(schannel_t,waiting_to_read),
   237:     offsetof(schannel_t,waiting_to_write)
   238: };
   239: 
   240: flx::gc::generic::gc_shape_t schannel_ptr_map(
   241:   &_fthread_ptr_map,
   242:   "schannel_t",
   243:   1,sizeof(schannel_t),
   244:   0, // no finaliser
   245:   2,
   246:   schannel_offsets
   247: );
   248: 
   249: // ********************************************************
   250: // _ref_ implementation
   251: // ********************************************************
   252: 
   253: void _ref_::operator = (_ref_ const& r)
   254: {
   255:   if (frame != r.frame || offset != r.offset)
   256:   {
   257:     frame = r.frame;
   258:     offset = r.offset;
   259:   }
   260: }
   261: 
   262: //OFFSETS for _ref_
   263: static std::size_t _ref_offsets[1]={
   264:     offsetof(_ref_,frame)
   265: };
   266: 
   267: flx::gc::generic::gc_shape_t _ref_ptr_map(
   268:   &schannel_ptr_map,
   269:   "_ref_",
   270:   1,sizeof(_ref_),
   271:   0, // no finaliser
   272:   1,
   273:   _ref_offsets
   274: );
   275: 
   276: // ********************************************************
   277: // _uctor_ implementation
   278: // ********************************************************
   279: 
   280: //OFFSETS for _uctor_
   281: static std::size_t _uctor_offsets[1]= {
   282:   offsetof(_uctor_,data)
   283: };
   284: 
   285: flx::gc::generic::gc_shape_t _uctor_ptr_map (
   286:   &_ref_ptr_map,
   287:   "_uctor_",
   288:   1,
   289:   sizeof(_uctor_),
   290:   0,
   291:   1,
   292:   _uctor_offsets
   293: );
   294: 
   295: // ********************************************************
   296: // int implementation
   297: // ********************************************************
   298: 
   299: flx::gc::generic::gc_shape_t _int_ptr_map (
   300:   &_uctor_ptr_map,
   301:   "int",
   302:   1,
   303:   sizeof(int),
   304:   0,
   305:   0,
   306:   0
   307: );
   308: 
   309: // ********************************************************
   310: // unit implementation
   311: // ********************************************************
   312: 
   313: flx::gc::generic::gc_shape_t unit_ptr_map (
   314:   &_int_ptr_map,
   315:   "unit",
   316:   1,
   317:   sizeof(unit),
   318:   0,
   319:   0,
   320:   0
   321: );
   322: 
   323: // ********************************************************
   324: // standard exceptions -- implementation
   325: // ********************************************************
   326: flx_exception_t::~flx_exception_t(){}
   327: 
   328: flx_exec_failure_t::flx_exec_failure_t(std::string f, std::string o, std::string w) :
   329:   filename(f),
   330:   operation(o),
   331:   what(w)
   332: {}
   333: 
   334: flx_exec_failure_t::~flx_exec_failure_t(){}
   335: 
   336: flx_range_srcref_t::flx_range_srcref_t() :
   337:     filename(""),startline(0),startcol(0),endline(0),endcol(0){}
   338: flx_range_srcref_t::flx_range_srcref_t(char *f,int sl, int sc, int el, int ec) :
   339:     filename(f),startline(sl),startcol(sc),endline(el),endcol(ec){}
   340: 
   341: flx_match_failure_t::flx_match_failure_t(flx_range_srcref_t ff, char *cf, int cl) :
   342:    flx_loc(ff), cxx_srcfile(cf), cxx_srcline(cl) {}
   343: flx_match_failure_t::~flx_match_failure_t(){}
   344: 
   345: flx_assert_failure_t::flx_assert_failure_t(flx_range_srcref_t ff, char *cf, int cl) :
   346:    flx_loc(ff), cxx_srcfile(cf), cxx_srcline(cl) {}
   347: flx_assert_failure_t::~flx_assert_failure_t(){}
   348: 
   349: flx_assert2_failure_t::flx_assert2_failure_t(flx_range_srcref_t ff, flx_range_srcref_t ff2, char *cf, int cl) :
   350:    flx_loc(ff), flx_loc2(ff2), cxx_srcfile(cf), cxx_srcline(cl) {}
   351: flx_assert2_failure_t::~flx_assert2_failure_t(){}
   352: 
   353: flx_range_failure_t::flx_range_failure_t(flx_range_srcref_t ff, char *cf, int cl) :
   354:    flx_loc(ff), cxx_srcfile(cf), cxx_srcline(cl) {}
   355: flx_range_failure_t::~flx_range_failure_t(){}
   356: 
   357: flx_switch_failure_t::~flx_switch_failure_t(){}
   358: 
   359: long range_check (long l, long x, long h, flx_range_srcref_t sref, char *cf, int cl)
   360: {
   361:   if (x>=l && x<h) return x;
   362:   throw flx::rtl::flx_range_failure_t (sref,cf,cl);
   363: }
   364: 
   365: 
   366: }}
   367: 
End cpp section to rtl/flx_rtl.cpp[1]