2 RTH runtime: Return-based "Threads" package,
3 for multiple flows-of-control *without* any
6 I'll probably regret this, but if I make this a
7 C++-based API I can make local variable access much easier.
9 Orion Sky Lawlor, olawlor@acm.org, 2003/07/23
15 #include <new> /* for in-place operator new */
17 /** All the local variables for RTH routines
18 are stored in subclasses of this type. Keeping
19 the types allows us to have a PUP routine and
24 virtual ~RTH_Locals();
25 virtual void pup(PUP::er
&p
);
29 /** An opaque handle to the RTH runtime data,
30 which includes the call stack and local variables.
34 /** An RTH user subroutine, declared using the
37 typedef void (*RTH_Routine
)(RTH_Runtime
*runtime
,
38 void *object
,RTH_Locals
*locals
,int pc
);
41 /************************************************
42 RTH library interface: used for writing libraries
43 that call RTH routines and/or are called by RTH routines.
46 /** Create a new RTH runtime that will run this function
47 on its first "resume" call.
49 RTH_Runtime
*RTH_Runtime_create(RTH_Routine fn
,int localsSize
,void *obj
);
51 /** Pup this RTH_Runtime. This routine can be called on
52 an uninitialized RTH_Runtime if the PUP::er is unpacking.
53 This does *not* free the RTH_Runtime, so call RTH_Runtime_free
54 in your destructor as usual.
56 RTH_Runtime
*RTH_Runtime_pup(RTH_Runtime
*runtime
,PUP::er
&p
,void *obj
);
58 /** "Block" this RTH thread. Saves the currently
59 running function and nextPC for later "resume" call.
60 Unlike a real thread, this routine returns, and you're
61 expected to exit the RTH_fn immediately.
62 Also see the RTH_Suspend macro, which can be used
63 directly from inside a user RTH_Routine.
65 void RTH_Runtime_suspend(RTH_Runtime
*runtime
,int nextPC
);
67 /** Resume the blocked RTH thread immediately.
68 This call will not return until the thread blocks again.
70 void RTH_Runtime_resume(RTH_Runtime
*runtime
);
72 /** Call this RTH subroutine inline. Returns 0 if the
73 current thread should block. (i.e., the call "failed") */
74 int RTH_Runtime_call(RTH_Runtime
*runtime
,RTH_Routine fn
,int localsSize
,int nextPC
);
76 /** Called at the end of an RTH routine.
77 Allows the next routine to be started.
79 void RTH_Runtime_done(RTH_Runtime
*runtime
);
81 /** Dispose of the RTH runtime. Does not free the user object. */
82 void RTH_Runtime_destroy(RTH_Runtime
*runtime
);
85 /************************************************
87 Instruments user's source code with calls to
91 /** Begins the definition of an RTH user routine.
92 You define a routine foo for a class bar using
94 RTH_Routine_locals(foo,bar)
97 RTH_Routine_code(foo,bar)
99 for (i=0;i<3;i++) z+=1.0;
100 RTH_Routine_end(foo,bar)
102 IMPLEMENTATION: Creates a small wrapper object to hold
103 the routine and the routine's local variables.
105 #define RTH_Routine_locals(object,name) \
106 class RTH_Routine_##object##_##name : public RTH_Locals { \
107 typedef RTH_Locals super; \
108 typedef RTH_Routine_##object##_##name locals_t; \
109 public: /* user's local variables go here */
111 /** After listing any local variables (and a pup routine),
112 use this macro to start defining the body code of your
114 IMPLEMENTATION: Opens the actual routine, and adds a
115 "switch(pc)" statement.
117 #define RTH_Routine_code(object,name) \
118 inline void name(RTH_Runtime *RTH_impl_runtime,\
119 object *c,int RTH_impl_pc) { \
120 switch(RTH_impl_pc) { \
121 case 0: /* Program counter at routine start (PC_START): */ \
122 new ((void *)this) locals_t; /* Call our locals' constructor in-place */
124 /** Ends the definition of an RTH routine.
125 IMPLEMENTATION: Ends the switch statement started by
126 RTH_Routine_code, and adds the callfn static function.
128 #define RTH_Routine_end(object,name) \
129 /* end-of-routine: check if we need to resume our calling routine */ \
130 RTH_Runtime_done(RTH_impl_runtime); \
133 printf("Bad pc %d\n",RTH_impl_pc); exit(1);/* unrecognized program counter: */ \
134 }; /* Switch end */ \
135 } /* User routine end */ \
137 /* C-style call-function for user routine-- applies appropriate typecasts. */ \
138 static void RTH_Call_routine(RTH_Runtime *runtime,\
139 void *c,RTH_Locals *locals,int pc) \
141 ((locals_t *)locals)->name(runtime,(object *)c,pc);\
144 }; /* locals_t class end */
146 /** Block the currently running RTH thread. Can only
147 be called from inside an RTH_Routine.
148 IMPLEMENTATION: Uses the bizarre method of stashing the
149 program counter for the next statement and returning.
150 On the next resume, the statements following the suspend
153 #define RTH_Suspend() do {\
154 RTH_Runtime_suspend(RTH_impl_runtime,__LINE__);\
159 /** Call this RTH subroutine (blocking). Can only be called
160 from inside an RTH_Routine.
161 Store any arguments for the routine inside your object.
162 FIXME: add real argument-passing and return types, based
165 #define RTH_Call(object,name) do{ \
166 if (!RTH_Runtime_call(RTH_impl_runtime,RTH_Routine_lookup(object,name),__LINE__)) \
171 /** Given a routine name, convert to a call-function and locals size.
172 Can be called from inside or outside an RTH_Routine.
174 #define RTH_Routine_lookup(object,name) \
175 RTH_Routine_##object##_##name::RTH_Call_routine, sizeof(RTH_Routine_##object##_##name)