configure: Drop archaic and incompletely used test
[charm.git] / src / util / RTH.h
1 /* 
2 RTH runtime: Return-based "Threads" package,
3 for multiple flows-of-control *without* any 
4 crazy threading work.
5
6 I'll probably regret this, but if I make this a 
7 C++-based API I can make local variable access much easier.
8
9 Orion Sky Lawlor, olawlor@acm.org, 2003/07/23
10 */
11 #ifndef __CHARM_RTH_H
12 #define __CHARM_RTH_H
13
14 #include "pup.h"
15 #include <new> /* for in-place operator new */
16
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 
20    an actual destructor. 
21 */
22 class RTH_Locals {
23 public:
24         virtual ~RTH_Locals();
25         virtual void pup(PUP::er &p);
26 };
27
28
29 /** An opaque handle to the RTH runtime data,
30   which includes the call stack and local variables.
31  */
32 class RTH_Runtime;
33
34 /** An RTH user subroutine, declared using the
35 RTH_Routine_* macros.
36 */
37 typedef void (*RTH_Routine)(RTH_Runtime *runtime,
38         void *object,RTH_Locals *locals,int pc);
39
40
41 /************************************************
42 RTH library interface: used for writing libraries
43 that call RTH routines and/or are called by RTH routines.
44 */
45
46 /** Create a new RTH runtime that will run this function
47     on its first "resume" call.
48 */
49 RTH_Runtime *RTH_Runtime_create(RTH_Routine fn,int localsSize,void *obj);
50
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.
55 */
56 RTH_Runtime *RTH_Runtime_pup(RTH_Runtime *runtime,PUP::er &p,void *obj);
57
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.
64 */
65 void RTH_Runtime_suspend(RTH_Runtime *runtime,int nextPC);
66
67 /** Resume the blocked RTH thread immediately.
68    This call will not return until the thread blocks again.  
69 */
70 void RTH_Runtime_resume(RTH_Runtime *runtime);
71
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);
75
76 /** Called at the end of an RTH routine.
77     Allows the next routine to be started.
78  */
79 void RTH_Runtime_done(RTH_Runtime *runtime);
80
81 /** Dispose of the RTH runtime. Does not free the user object. */
82 void RTH_Runtime_destroy(RTH_Runtime *runtime);
83
84
85 /************************************************
86 RTH "translator":
87   Instruments user's source code with calls to
88   the RTH runtime.
89 */
90
91 /** Begins the definition of an RTH user routine.
92 You define a routine foo for a class bar using 
93 these macros like:
94    RTH_Routine_locals(foo,bar)
95      int i, j;
96      double z;
97    RTH_Routine_code(foo,bar)
98      z=0.0; 
99      for (i=0;i<3;i++) z+=1.0;
100    RTH_Routine_end(foo,bar)
101
102 IMPLEMENTATION: Creates a small wrapper object to hold
103   the routine and the routine's local variables.
104 */
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 */
110
111 /** After listing any local variables (and a pup routine),
112     use this macro to start defining the body code of your
113     subroutine. 
114 IMPLEMENTATION: Opens the actual routine, and adds a 
115  "switch(pc)" statement.
116 */
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 */
123
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.
127 */
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); \
131       return;  \
132     default: \
133       printf("Bad pc %d\n",RTH_impl_pc); exit(1);/* unrecognized program counter: */ \
134     }; /* Switch end */ \
135   } /* User routine end */ \
136 \
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) \
140   {\
141     ((locals_t *)locals)->name(runtime,(object *)c,pc);\
142   }\
143 \
144 }; /* locals_t class end */ 
145
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
151   will be executed.
152  */
153 #define RTH_Suspend() do {\
154         RTH_Runtime_suspend(RTH_impl_runtime,__LINE__);\
155         return;\
156 case __LINE__: ; \
157 } while(0)
158
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 
163   on pup (somehow).
164 */
165 #define RTH_Call(object,name) do{ \
166      if (!RTH_Runtime_call(RTH_impl_runtime,RTH_Routine_lookup(object,name),__LINE__)) \
167         return;\
168 case __LINE__: ; \
169 } while(0)
170
171 /** Given a routine name, convert to a call-function and locals size.
172   Can be called from inside or outside an RTH_Routine.
173 */
174 #define RTH_Routine_lookup(object,name) \
175    RTH_Routine_##object##_##name::RTH_Call_routine, sizeof(RTH_Routine_##object##_##name)
176
177 #endif
178