a new build option --enable-tracing-commthread
[charm.git] / src / util / RTH.h
blob0c973dbaaac84c882162d682ce7ddc6e5be9171f
1 /*
2 RTH runtime: Return-based "Threads" package,
3 for multiple flows-of-control *without* any
4 crazy threading work.
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
11 #ifndef __CHARM_RTH_H
12 #define __CHARM_RTH_H
14 #include "pup.h"
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
20 an actual destructor.
22 class RTH_Locals {
23 public:
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.
32 class RTH_Runtime;
34 /** An RTH user subroutine, declared using the
35 RTH_Routine_* macros.
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 /************************************************
86 RTH "translator":
87 Instruments user's source code with calls to
88 the RTH runtime.
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)
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
113 subroutine.
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); \
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 */ \
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
151 will be executed.
153 #define RTH_Suspend() do {\
154 RTH_Runtime_suspend(RTH_impl_runtime,__LINE__);\
155 return;\
156 case __LINE__: ; \
157 } while(0)
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).
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)
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)
177 #endif