1.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 473 "./lpsrc/flx_rtl.pak"
     2: #ifndef __FLX_RTL_H__
     3: #define __FLX_RTL_H__
     4: #include "flx_rtl_config.hpp"
     5: #include "flx_meta.hpp"
     6: #include "flx_gc.hpp"
     7: #include <string>
     8: #include <functional>
     9: 
    10: #if FLX_PTF_STATIC_STRUCT
    11: #define PTF ptf.
    12: #elif FLX_PTF_STATIC_POINTER
    13: #define PTF ptf->
    14: #else
    15: #define PTF ptf->
    16: #endif
    17: 
    18: // for declarations in header file
    19: #if FLX_PTF_STATIC_STRUCT
    20: #define FLX_FMEM_DECL
    21: #define FLX_FPAR_DECL_ONLY
    22: #define FLX_FPAR_DECL
    23: #define FLX_APAR_DECL_ONLY
    24: #define FLX_APAR_DECL
    25: #define FLX_DCL_THREAD_FRAME extern thread_frame_t ptf;
    26: #elif FLX_PTF_STATIC_POINTER
    27: #define FLX_FMEM_DECL
    28: #define FLX_FPAR_DECL_ONLY
    29: #define FLX_FPAR_DECL
    30: #define FLX_APAR_DECL_ONLY
    31: #define FLX_APAR_DECL
    32: #define FLX_DCL_THREAD_FRAME extern thread_frame_t *ptf;
    33: #else
    34: #define FLX_FMEM_DECL thread_frame_t *ptf;
    35: #define FLX_FPAR_DECL_ONLY thread_frame_t *_ptf
    36: #define FLX_FPAR_DECL thread_frame_t *_ptf,
    37: #define FLX_APAR_DECL_ONLY thread_frame_t *ptf
    38: #define FLX_APAR_DECL thread_frame_t *ptf,
    39: #define FLX_DCL_THREAD_FRAME
    40: #endif
    41: 
    42: #if FLX_CGOTO
    43:   #define FLX_PC_DECL void *pc;
    44: #else
    45:   #define FLX_PC_DECL int pc;
    46: #endif
    47: 
    48: 
    49: namespace flx { namespace rtl {
    50: 
    51: // ********************************************************
    52: // Felix system classes
    53: // ********************************************************
    54: 
    55: struct RTL_EXTERN con_t;     // continuation
    56: struct RTL_EXTERN thread_t; // f-thread
    57: struct RTL_EXTERN _ref_;     // pointer/reference
    58: struct RTL_EXTERN _uctor_;   // union constructor
    59: struct RTL_EXTERN schannel_t;   // synchronous channel type
    60: struct RTL_EXTERN slist_t;   // singly linked list of void*
    61: struct RTL_EXTERN _root_ptr_t;   // singly linked list of void*
    62: 
    63: struct RTL_EXTERN unit {};   // unit
    64:   // INLINE DEFINITION, PROBLEMATIC!!
    65: 
    66: // ********************************************************
    67: // Shape (RTTI) objects for system classes
    68: // con_t is only an abstract base, so has no fixed shape
    69: // shapes for instance types generated by Felix compiler
    70: // we provide a shape for C 'int' type as well
    71: // ********************************************************
    72: 
    73: RTL_EXTERN extern flx::gc::generic::gc_shape_t _fthread_ptr_map;
    74: RTL_EXTERN extern flx::gc::generic::gc_shape_t schannel_ptr_map;
    75: RTL_EXTERN extern flx::gc::generic::gc_shape_t _ref_ptr_map;
    76: RTL_EXTERN extern flx::gc::generic::gc_shape_t _uctor_ptr_map;
    77: RTL_EXTERN extern flx::gc::generic::gc_shape_t _int_ptr_map;
    78: RTL_EXTERN extern flx::gc::generic::gc_shape_t unit_ptr_map;
    79: RTL_EXTERN extern flx::gc::generic::gc_shape_t slist_ptr_map;
    80: RTL_EXTERN extern flx::gc::generic::gc_shape_t _root_ptr_ptr_map;
    81: 
    82: // ********************************************************
    83: // Standard C++ Exceptions
    84: // ********************************************************
    85: 
    86: struct RTL_EXTERN flx_exception_t;
    87: struct RTL_EXTERN flx_exec_failure_t;
    88: struct RTL_EXTERN flx_range_srcref_t;
    89: struct RTL_EXTERN flx_match_failure_t;
    90: struct RTL_EXTERN flx_assert_failure_t;
    91: struct RTL_EXTERN flx_assert2_failure_t;
    92: struct RTL_EXTERN flx_switch_failure_t;
    93: // ********************************************************
    94: /// CONTINUATION.
    95: // ********************************************************
    96: 
    97: struct RTL_EXTERN con_t ///< abstract base for mutable continuations
    98: {
    99:   FLX_PC_DECL               ///< interior program counter
   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:   bool operator==(_ref_ x) const  ///< compare equal
   210:   { return frame==x.frame && offset==x.offset; }
   211: 
   212:   bool operator!=(_ref_ x) const  ///< compare inequal
   213:   { return frame!=x.frame || offset!=x.offset; }
   214: };
   215: 
   216: 
   217: // ********************************************************
   218: /// VARIANTS. Felix union type
   219: /// note: non-polymorphic, so ctor can be inline
   220: // ********************************************************
   221: 
   222: struct RTL_EXTERN _uctor_
   223: {
   224:   int variant;  ///< Variant code
   225:   void *data;   ///< Heap variant constructor data
   226:   _uctor_() : variant(-1), data(0) {}
   227:   _uctor_(int i, void *d) : variant(i), data(d) {}
   228:   _uctor_(int *a, _uctor_ x) : variant(a[x.variant]), data(x.data) {}
   229: };
   230: 
   231: // ********************************************************
   232: /// ROOT POINTER.
   233: /// Use to chain pseudo roots together. Generally scannable
   234: /// but not collectable.
   235: // ********************************************************
   236: 
   237: struct RTL_EXTERN _root_ptr_t
   238: {
   239:   _root_ptr_t();
   240:   _root_ptr_t(void *x);
   241:   _root_ptr_t(_root_ptr_t const&);
   242:   void operator=(_root_ptr_t const&);
   243:   ~_root_ptr_t();
   244: 
   245:   _root_ptr_t *next;
   246:   _root_ptr_t *prev;
   247:   void *data;
   248: 
   249: private:
   250:   void insert_after (_root_ptr_t*);
   251:   void erase();
   252: };
   253: 
   254: // INLINE! All casts
   255: template<class T>
   256: struct root_ptr_t : _root_ptr_t {
   257:   root_ptr_t(){}
   258:   root_ptr_t(root_ptr_t<T> const&){}
   259:   root_ptr_t<T>& operator=(root_ptr_t<T> const &a){
   260:     return reinterpret_cast<root_ptr_t<T>&>(_root_ptr_t::operator=(a));
   261:   }
   262:  ~root_ptr_t(){}
   263: 
   264:   root_ptr_t(T const *a) : _root_ptr_t (const_cast<T*>(a)) {}
   265: 
   266:   T *operator->() { return (T*)data; }
   267:   T const *operator->() const { return (T const*)data; }
   268:   T &operator*() { return *(T*)data; }
   269:   T const &operator*() const { return *(T const*)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> a, root_ptr_t<T> b)
   280: {
   281:   return a-> data != b->data;
   282: }
   283: 
   284: template<class T>
   285: bool operator < (root_ptr_t<T> const &a, root_ptr_t<T> const &b)
   286: {
   287:   // we use this because it enforces a total order
   288:   return std::less<void const*>()(a-> data, b->data);
   289: }
   290: 
   291: template<class T>
   292: bool operator <= (root_ptr_t<T> const &a, root_ptr_t<T> const &b)
   293: {
   294:   // we use this because it enforces a total order
   295:   return std::less_equal<void const*>()(a-> data, b->data);
   296: }
   297: 
   298: template<class T>
   299: bool operator > (root_ptr_t<T> const &a, root_ptr_t<T> const &b)
   300: {
   301:   // we use this because it enforces a total order
   302:   return std::greater<void const*>()(a-> data, b->data);
   303: }
   304: 
   305: template<class T>
   306: bool operator >= (root_ptr_t<T> const &a, root_ptr_t<T> const &b)
   307: {
   308:   // we use this because it enforces a total order
   309:   return std::greater_equal<void const*>()(a-> data, b->data);
   310: }
   311: 
   312: 
   313: // ********************************************************
   314: /// EXCEPTION: Felix exception base abstraction.
   315: /// Mainly used to convert catches into subroutine
   316: /// calls which then dispatch on RTTI manually.
   317: // ********************************************************
   318: 
   319: struct RTL_EXTERN flx_exception_t {
   320:   virtual ~flx_exception_t()=0;
   321: };
   322: 
   323: // ********************************************************
   324: /// EXCEPTION: EXEC protocol failure.
   325: /// Thrown when trying to run a dead procedure
   326: // ********************************************************
   327: 
   328: struct RTL_EXTERN flx_exec_failure_t : flx_exception_t {
   329:   std::string filename;  ///< dll filename
   330:   std::string operation; ///< faulty operation
   331:   std::string what;      ///< error description
   332:   flx_exec_failure_t(std::string f, std::string o, std::string w);
   333:   virtual ~flx_exec_failure_t();
   334: };
   335: 
   336: // ********************************************************
   337: /// SOURCE REFERENCE: to track places in user source code.
   338: // ********************************************************
   339: 
   340: struct RTL_EXTERN flx_range_srcref_t {
   341:   char *filename;  ///< source file name
   342:   int startline;   ///< first line (1 origin)
   343:   int startcol;    ///< first column (1 origin)
   344:   int endline;     ///< last line
   345:   int endcol;      ///< last column
   346:   flx_range_srcref_t(char *f,int sl, int sc, int el, int ec);
   347:   flx_range_srcref_t();
   348: };
   349: 
   350: // ********************************************************
   351: /// EXCEPTION: HALT.
   352: /// Thrown by halt command
   353: // ********************************************************
   354: 
   355: struct RTL_EXTERN flx_halt_t : flx_exception_t {
   356:   std::string reason;         ///< halt argument
   357:   flx_range_srcref_t flx_loc; ///< location in Felix file
   358:   char *cxx_srcfile;          ///< C++ file name
   359:   int cxx_srcline;            ///< C++ line number
   360:   flx_halt_t(flx_range_srcref_t ff, char *cf, int cl, std::string reason);
   361:   virtual ~flx_halt_t();
   362: };
   363: 
   364: // ********************************************************
   365: /// EXCEPTION: MATCH failure.
   366: /// Thrown when no match cases match the argument of a match,
   367: /// regmatch, or reglex
   368: // ********************************************************
   369: 
   370: struct RTL_EXTERN flx_match_failure_t : flx_exception_t {
   371:   flx_range_srcref_t flx_loc; ///< location in Felix file
   372:   char *cxx_srcfile;          ///< C++ file name
   373:   int cxx_srcline;            ///< C++ line number
   374:   flx_match_failure_t(flx_range_srcref_t ff, char *cf, int cl);
   375:   virtual ~flx_match_failure_t();
   376: };
   377: 
   378: // ********************************************************
   379: /// EXCEPTION: ASSERT failure.
   380: /// Thrown when user assertion fails
   381: // ********************************************************
   382: 
   383: struct RTL_EXTERN flx_assert_failure_t : flx_exception_t {
   384:   flx_range_srcref_t flx_loc; ///< location in Felix file
   385:   char *cxx_srcfile;          ///< C++ file
   386:   int cxx_srcline;            ///< __LINE__ macro
   387:   flx_assert_failure_t(flx_range_srcref_t ff, char *cf, int cl);
   388:   virtual ~flx_assert_failure_t();
   389: };
   390: 
   391: struct RTL_EXTERN flx_assert2_failure_t : flx_exception_t {
   392:   flx_range_srcref_t flx_loc; ///< location in Felix file
   393:   flx_range_srcref_t flx_loc2; ///< second location in Felix file
   394:   char *cxx_srcfile;          ///< C++ file
   395:   int cxx_srcline;            ///< __LINE__ macro
   396:   flx_assert2_failure_t(flx_range_srcref_t ff, flx_range_srcref_t ff2, char *cf, int cl);
   397:   virtual ~flx_assert2_failure_t();
   398: };
   399: 
   400: // ********************************************************
   401: /// EXCEPTION: RANGE failure.
   402: /// Thrown when a range check fails
   403: // ********************************************************
   404: 
   405: struct RTL_EXTERN flx_range_failure_t : flx_exception_t {
   406:   flx_range_srcref_t flx_loc; ///< location in Felix file
   407:   char *cxx_srcfile;          ///< C++ file
   408:   int cxx_srcline;            ///< __LINE__ macro
   409:   flx_range_failure_t(flx_range_srcref_t ff, char *cf, int cl);
   410:   virtual ~flx_range_failure_t();
   411: };
   412: 
   413: RTL_EXTERN long range_check (long l, long x, long h, flx_range_srcref_t sref, char *cf, int cl);
   414: 
   415: 
   416: // ********************************************************
   417: /// EXCEPTION: SWITCH failure. this is a system failure!
   418: // ********************************************************
   419: 
   420: struct RTL_EXTERN flx_switch_failure_t : flx_exception_t {
   421:   virtual ~flx_switch_failure_t();
   422: };
   423: 
   424: 
   425: // ********************************************************
   426: // SERVICE REQUEST CODE
   427: // THESE VALUES MUST SYNCH WITH THE STANDARD LIBRARY
   428: // ********************************************************
   429: 
   430: enum svc_t               // what the dispatch should do
   431: {                        // when the resume callback returns
   432:   svc_yield = 0,
   433:   svc_get_fthread=1,
   434:   svc_read=2,
   435:   svc_general=3,         // temporary hack by RF
   436:   svc_reserved=4,
   437:   svc_spawn_pthread=5,
   438:   svc_spawn_detached=6,
   439:   svc_sread=7,           // synchronous read
   440:   svc_swrite=8,          // synchronous write
   441:   svc_kill=9,           // kill fthread
   442:   svc_compact=10,        // run compactor
   443:   svc_collect=11,        // run collector
   444:   svc_collect_and_compact=12,        // run collector and compactor
   445:   svc_end
   446: };
   447: 
   448: struct readreq_t {
   449:   schannel_t *chan;
   450:   _ref_ variable;
   451: };
   452: 
   453: }} // namespaces
   454: 
   455: #define FLX_EXEC_FAILURE(f,op,what) \
   456:   throw flx::rtl::flx_exec_failure_t (f,op,what)
   457: 
   458: #define FLX_HALT(f,sl,sc,el,ec,s) \
   459:   throw flx::rtl::flx_halt_t (flx_range_srcref_t(f,sl,sc,el,ec),__FILE__,__LINE__,s)
   460: 
   461: #define FLX_MATCH_FAILURE(f,sl,sc,el,ec) \
   462:   throw flx::rtl::flx_match_failure_t (flx_range_srcref_t(f,sl,sc,el,ec),__FILE__,__LINE__)
   463: 
   464: #define FLX_ASSERT_FAILURE(f,sl,sc,el,ec) \
   465:   throw flx::rtl::flx_assert_failure_t (flx_range_srcref_t(f,sl,sc,el,ec),__FILE__,__LINE__)
   466: 
   467: #define FLX_ASSERT2_FAILURE(f,sl,sc,el,ec,f2,sl2,sc2,el2,ec2) \
   468:   throw flx::rtl::flx_assert2_failure_t (\
   469:     flx_range_srcref_t(f,sl,sc,el,ec),\
   470:     flx_range_srcref_t(f2,sl2,sc2,el2,sc2),\
   471:     __FILE__,__LINE__)
   472: 
   473: #define FLX_RANGE_FAILURE(f,sl,sc,el,ec) \
   474:   throw flx::rtl::flx_range_failure_t (flx_range_srcref_t(f,sl,sc,el,ec),__FILE__,__LINE__)
   475: 
   476: // for generated code in body file
   477: #define INIT_PC pc=0;
   478:     ///< interior program counter
   479: 
   480: #if FLX_CGOTO
   481:   #define FLX_START_SWITCH if(pc)goto *pc;
   482:   #define FLX_SET_PC(x) pc=&&case_##x;
   483:   #define FLX_CASE_LABEL(x) case_##x:;
   484:   #define FLX_DECLARE_LABEL(n,i,x) \
   485:     extern void f##i##_##n##_##x(void) __asm__("l"#i"_"#n"_"#x);
   486:   #define FLX_LABEL(n,i,x) x:\
   487:     __asm__(".global l"#i"_"#n"_"#x);\
   488:     __asm__("l"#i"_"#n"_"#x":");\
   489:     __asm__(""::"g"(&&x));
   490:   #define FLX_FARTARGET(n,i,x) (void*)&f##i##_##n##_##x
   491:   #define FLX_END_SWITCH
   492: #else
   493:   #define FLX_START_SWITCH switch(pc){case 0:;
   494:   #define FLX_SET_PC(x) pc=x;
   495:   #define FLX_CASE_LABEL(x) case x:;
   496:   #define FLX_DECLARE_LABEL(n,i,x)
   497:   #define FLX_LABEL(n,i,x) case n: x:;
   498:   #define FLX_FARTARGET(n,i,x) n
   499:   #define FLX_END_SWITCH default: throw flx_switch_failure_t(); }
   500: #endif
   501: 
   502: #define FLX_RETURN \
   503: { \
   504:   con_t *tmp = _caller; \
   505:   _caller = 0; \
   506:   return tmp; \
   507: }
   508: 
   509: #define FLX_NEWP(x) new(*PTF gc,x##_ptr_map)x
   510: 
   511: #define FLX_FINALISER(x) \
   512: static void x##_finaliser(collector_t *, void *p){\
   513:   ((x*)p)->~x();\
   514: }
   515: 
   516: #if FLX_USE_REGPARM3 && FLX_HAVE_GNU_X86
   517: #define FLX_REGPARM __attribute__((regparm(3)))
   518: #else
   519: #define FLX_REGPARM
   520: #endif
   521: 
   522: #if FLX_PTF_STATIC_STRUCT
   523: #define FLX_FMEM_INIT_ONLY
   524: #define FLX_FMEM_INIT :
   525: #define FLX_FPAR_PASS_ONLY
   526: #define FLX_FPAR_PASS
   527: #define FLX_APAR_PASS_ONLY
   528: #define FLX_APAR_PASS
   529: #define _PTF _ptf.
   530: #define _PTFV
   531: #define FLX_PASS_PTF 0
   532: #define FLX_EAT_PTF(x)
   533: #define FLX_DEF_THREAD_FRAME thread_frame_t ptf;
   534: #elif FLX_PTF_STATIC_POINTER
   535: #define FLX_FMEM_INIT_ONLY
   536: #define FLX_FMEM_INIT :
   537: #define FLX_FPAR_PASS_ONLY
   538: #define FLX_FPAR_PASS
   539: #define FLX_APAR_PASS_ONLY
   540: #define FLX_APAR_PASS
   541: #define _PTF _ptf->
   542: #define _PTFV
   543: #define FLX_PASS_PTF 0
   544: #define FLX_EAT
   545: #define FLX_DEF_THREAD_FRAME thread_frame_t *ptf=0;
   546: #else
   547: #define FLX_FMEM_INIT_ONLY : ptf(_ptf)
   548: #define FLX_FMEM_INIT : ptf(_ptf),
   549: #define FLX_FPAR_PASS_ONLY ptf
   550: #define FLX_FPAR_PASS ptf,
   551: #define FLX_APAR_PASS_ONLY _ptf
   552: #define FLX_APAR_PASS _ptf,
   553: #define _PTF _ptf->
   554: #define _PTFV _ptf
   555: #define FLX_PASS_PTF 1
   556: #define FLX_EAT_PTF(x) x
   557: #define FLX_DEF_THREAD_FRAME
   558: #endif
   559: 
   560: #if FLX_PTF_STATIC_STRUCT
   561: #define FLX_FRAME_WRAPPERS(mname) \
   562: extern "C" thread_frame_t *create_thread_frame(\
   563:   collector_t *gc\
   564: ) {\
   565:   ptf.gc = gc;\
   566:   return &ptf;\
   567: }
   568: #elif FLX_PTF_STATIC_POINTER
   569: #define FLX_FRAME_WRAPPERS(mname) \
   570: extern "C" thread_frame_t *create_thread_frame(\
   571:   collector_t *gc\
   572: ) {\
   573:   mname::thread_frame_t *p = new(*gc,mname::thread_frame_t_ptr_map) mname::thread_frame_t(gc);\
   574:   ptf = p;\
   575:   return p;\
   576: }
   577: #else
   578: #define FLX_FRAME_WRAPPERS(mname) \
   579: extern "C" FLX_EXPORT mname::thread_frame_t *create_thread_frame(\
   580:   collector_t *gc\
   581: ) {\
   582:   mname::thread_frame_t *p = new(*gc,mname::thread_frame_t_ptr_map) mname::thread_frame_t(gc);\
   583:   return p;\
   584: }
   585: #endif
   586: 
   587: #if FLX_PTF_STATIC_STRUCT
   588: #define FLX_START_WRAPPER(mname,x)\
   589: extern "C" con_t *flx_start(\
   590:   mname::thread_frame_t *ptf,\
   591:   int argc,\
   592:   char **argv,\
   593:   FILE *stdin_,\
   594:   FILE *stdout_,\
   595:   FILE *stderr_\
   596: ) {\
   597:   ptf->argc = argc;\
   598:   ptf->argv = argv;\
   599:   ptf->flx_stdin = stdin_;\
   600:   ptf->flx_stdout = stdout_;\
   601:   ptf->flx_stderr = stderr_;\
   602:   return (new(*ptf->gc,mname::x##_ptr_map) \
   603:     mname::x()) ->call(0);\
   604: }
   605: #elif FLX_PTF_STATIC_POINTER
   606: #define FLX_START_WRAPPER(mname,x)\
   607: extern "C" con_t *flx_start(\
   608:   mname::thread_frame_t *ptf,\
   609:   int argc,\
   610:   char **argv,\
   611:   FILE *stdin_,\
   612:   FILE *stdout_,\
   613:   FILE *stderr_\
   614: ) {\
   615:   ptf->argc = argc;\
   616:   ptf->argv = argv;\
   617:   ptf->flx_stdin = stdin_;\
   618:   ptf->flx_stdout = stdout_;\
   619:   ptf->flx_stderr = stderr_;\
   620:   return (new(*ptf->gc,mname::x##_ptr_map) \
   621:     mname::x()) ->call(0);\
   622: }
   623: #else
   624: #define FLX_START_WRAPPER(mname,x)\
   625: extern "C" FLX_EXPORT con_t *flx_start(\
   626:   mname::thread_frame_t *ptf,\
   627:   int argc,\
   628:   char **argv,\
   629:   FILE *stdin_,\
   630:   FILE *stdout_,\
   631:   FILE *stderr_\
   632: ) {\
   633:   ptf->argc = argc;\
   634:   ptf->argv = argv;\
   635:   ptf->flx_stdin = stdin_;\
   636:   ptf->flx_stdout = stdout_;\
   637:   ptf->flx_stderr = stderr_;\
   638:   return (new(*ptf->gc,mname::x##_ptr_map) \
   639:     mname::x(ptf)) ->call(0);\
   640: }
   641: #endif
   642: 
   643: #if FLX_PTF_STATIC_STRUCT
   644: #define FLX_STACK_START_WRAPPER(mname,x)\
   645: extern "C" con_t *flx_start(\
   646:   mname::thread_frame_t *ptf,\
   647:   int argc,\
   648:   char **argv,\
   649:   FILE *stdin_,\
   650:   FILE *stdout_,\
   651:   FILE *stderr_\
   652: ) {\
   653:   ptf->argc = argc;\
   654:   ptf->argv = argv;\
   655:   ptf->flx_stdin = stdin_;\
   656:   ptf->flx_stdout = stdout_;\
   657:   ptf->flx_stderr = stderr_;\
   658:   mname::x().stack_call();\
   659:   return 0;\
   660: }
   661: #elif FLX_PTF_STATIC_POINTER
   662: #define FLX_STACK_START_WRAPPER(mname,x)\
   663: extern "C" con_t *flx_start(\
   664:   mname::thread_frame_t *ptf,\
   665:   int argc,\
   666:   char **argv,\
   667:   FILE *stdin_,\
   668:   FILE *stdout_,\
   669:   FILE *stderr_\
   670: ) {\
   671:   ptf->argc = argc;\
   672:   ptf->argv = argv;\
   673:   ptf->flx_stdin = stdin_;\
   674:   ptf->flx_stdout = stdout_;\
   675:   ptf->flx_stderr = stderr_;\
   676:   mname::x().stack_call();\
   677:   return 0;\
   678: }
   679: #else
   680: #define FLX_STACK_START_WRAPPER(mname,x)\
   681: extern "C" FLX_EXPORT con_t *flx_start(\
   682:   mname::thread_frame_t *ptf,\
   683:   int argc,\
   684:   char **argv,\
   685:   FILE *stdin_,\
   686:   FILE *stdout_,\
   687:   FILE *stderr_\
   688: ) {\
   689:   ptf->argc = argc;\
   690:   ptf->argv = argv;\
   691:   ptf->flx_stdin = stdin_;\
   692:   ptf->flx_stdout = stdout_;\
   693:   ptf->flx_stderr = stderr_;\
   694:   mname::x(ptf).stack_call();\
   695:   return 0;\
   696: }
   697: #endif
   698: 
   699: #if FLX_PTF_STATIC_STRUCT
   700: #define FLX_C_START_WRAPPER(mname,x)\
   701: extern "C" con_t *flx_start(\
   702:   mname::thread_frame_t *ptf,\
   703:   int argc,\
   704:   char **argv,\
   705:   FILE *stdin_,\
   706:   FILE *stdout_,\
   707:   FILE *stderr_\
   708: ) {\
   709:   ptf->argc = argc;\
   710:   ptf->argv = argv;\
   711:   ptf->flx_stdin = stdin_;\
   712:   ptf->flx_stdout = stdout_;\
   713:   ptf->flx_stderr = stderr_;\
   714:   mname::x();\
   715:   return 0;\
   716: }
   717: #elif FLX_PTF_STATIC_POINTER
   718: #define FLX_C_START_WRAPPER(mname,x)\
   719: extern "C" con_t *flx_start(\
   720:   mname::thread_frame_t *ptf,\
   721:   int argc,\
   722:   char **argv,\
   723:   FILE *stdin_,\
   724:   FILE *stdout_,\
   725:   FILE *stderr_\
   726: ) {\
   727:   ptf->argc = argc;\
   728:   ptf->argv = argv;\
   729:   ptf->flx_stdin = stdin_;\
   730:   ptf->flx_stdout = stdout_;\
   731:   ptf->flx_stderr = stderr_;\
   732:   mname::x();\
   733:   return 0;\
   734: }
   735: #else
   736: #define FLX_C_START_WRAPPER(mname,x)\
   737: extern "C" FLX_EXPORT con_t *flx_start(\
   738:   mname::thread_frame_t *ptf,\
   739:   int argc,\
   740:   char **argv,\
   741:   FILE *stdin_,\
   742:   FILE *stdout_,\
   743:   FILE *stderr_\
   744: ) {\
   745:   ptf->argc = argc;\
   746:   ptf->argv = argv;\
   747:   ptf->flx_stdin = stdin_;\
   748:   ptf->flx_stdout = stdout_;\
   749:   ptf->flx_stderr = stderr_;\
   750:   mname::x(ptf);\
   751:   return 0;\
   752: }
   753: #endif
   754: 
   755: #endif
End cpp section to rtl/flx_rtl.hpp[1]
Start cpp section to rtl/flx_rtl.cpp[1 /1 ]
     1: #line 1230 "./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: #if FLX_DEBUG_CONT
    14:  fprintf(stderr,"Constructing %p\n",this);
    15: #endif
    16: }
    17: con_t::~con_t(){
    18: #if 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_halt_t::flx_halt_t(flx_range_srcref_t ff, char *cf, int cl, std::string r) :
   342:    reason(r), flx_loc(ff), cxx_srcfile(cf), cxx_srcline(cl) {}
   343: flx_halt_t::~flx_halt_t(){}
   344: 
   345: flx_match_failure_t::flx_match_failure_t(flx_range_srcref_t ff, char *cf, int cl) :
   346:    flx_loc(ff), cxx_srcfile(cf), cxx_srcline(cl) {}
   347: flx_match_failure_t::~flx_match_failure_t(){}
   348: 
   349: flx_assert_failure_t::flx_assert_failure_t(flx_range_srcref_t ff, char *cf, int cl) :
   350:    flx_loc(ff), cxx_srcfile(cf), cxx_srcline(cl) {}
   351: flx_assert_failure_t::~flx_assert_failure_t(){}
   352: 
   353: flx_assert2_failure_t::flx_assert2_failure_t(flx_range_srcref_t ff, flx_range_srcref_t ff2, char *cf, int cl) :
   354:    flx_loc(ff), flx_loc2(ff2), cxx_srcfile(cf), cxx_srcline(cl) {}
   355: flx_assert2_failure_t::~flx_assert2_failure_t(){}
   356: 
   357: flx_range_failure_t::flx_range_failure_t(flx_range_srcref_t ff, char *cf, int cl) :
   358:    flx_loc(ff), cxx_srcfile(cf), cxx_srcline(cl) {}
   359: flx_range_failure_t::~flx_range_failure_t(){}
   360: 
   361: flx_switch_failure_t::~flx_switch_failure_t(){}
   362: 
   363: long range_check (long l, long x, long h, flx_range_srcref_t sref, char *cf, int cl)
   364: {
   365:   if (x>=l && x<h) return x;
   366:   throw flx::rtl::flx_range_failure_t (sref,cf,cl);
   367: }
   368: 
   369: 
   370: }}
End cpp section to rtl/flx_rtl.cpp[1]