2 * Worldvisions Weaver Software:
3 * Copyright (C) 1997-2002 Net Integration Technologies, Inc.
5 * FIXME: I was too lazy to templatize this properly, so we only support
6 * WvCallback<void*,void*>. It should be possible to work with any kind
7 * of return value and parameter, although it makes sense to limit things
8 * to just one parameter (since it currently has to be returned by yield()
15 #include "wvlinklist.h"
16 #include "wvstreamsdebugger.h"
19 typedef wv::function
<void*(void*)> WvContCallback
;
22 * WvCont provides "continuations", which are apparently also known as
23 * semi-coroutines. You can wrap any WvCallback<void*,void*> in a WvCont
24 * and make it a "continuable" callback - that is, you can yield() from it
25 * and return a value. Next time someone calls your callback, it will be
26 * as if yield() has returned (and the parameter to your function is returned
33 typedef WvList
<Data
> DataList
;
37 * When we copy a WvCont, we increase the reference count of the 'data'
38 * member rather than copying it. That makes it so every copy of a given
39 * callback object still refers to the same WvTask.
42 static DataList
*data_list
;
47 static void bouncer(void *userdata
);
50 * Actually call the callback inside its task, and enforce a call stack.
51 * Doesn't do anything with arguments. Returns the return value.
54 { return _call(data
); }
57 * Call the callback inside its task, but don't assume this WvCont will
58 * still be around when we come back.
60 static void *_call(Data
*data
);
63 * Construct a WvCont given a pre-existing Data structure. This is
64 * basically equivalent to using the copy constructor.
70 * Construct a WvCont using an existing WvCallback. The WvCont object
71 * can be used in place of that callback, and stored in a callback of
74 WvCont(const WvContCallback
&cb
, unsigned long stacksize
= 64*1024);
76 /** Copy constructor. */
77 WvCont(const WvCont
&cb
);
83 * call the callback, making p1 the return value of yield() or the
84 * parameter to the function, and returning Ret, the argument of yield()
85 * or the return value of the function.
87 void *operator() (void *p1
= 0);
89 // the following are static because a function doesn't really know
90 // which WvCont it belongs to, and only one WvCont can be the "current"
91 // one globally in an application anyway.
93 // Unfortunately this prevents us from assert()ing that you're in the
94 // context you think you are.
97 * Get a copy of the current WvCont.
99 static WvCont
current();
102 * "return" from the current callback, giving value 'ret' to the person
103 * who called us. Next time this callback is called, it's as if yield()
104 * had returned, and the parameter to the callback is the value of
107 static void *yield(void *ret
= 0);
110 * Tell us if the current context is "okay", that is, not trying to
111 * die. If !isok(), you shouldn't yield(), because the caller is just
112 * going to keep calling you until you die. Return as soon as you can.
118 * A templated function that allows you to pass a WvCont wherever a
119 * C-style function pointer of the form
120 * R func(T, void *userdata)
121 * is taken. It's your job to make sure the 'userdata' provided is
122 * a pointer to the right WvCont.
125 * typedef bool MyFunc(Obj *obj, void *userdata);
127 * MyFunc *func = &WvCont::c_bouncer<bool,Obj *>;
128 * bool b = func(new Obj, &cont);
130 template <typename R
, typename T
>
131 static R
c_bouncer(T t
, void *_cont
)
133 WvCont
&cont
= *(WvCont
*)_cont
;
134 return (R
)cont((T
)t
);
139 * A templated function that allows you to pass a WvCont wherever a
140 * C-style function pointer of the form
141 * R func(void *userdata)
142 * is taken. It's your job to make sure the 'userdata' provided is
143 * a pointer to the right WvCont.
146 * typedef bool MyFunc(void *userdata);
148 * MyFunc *func = &WvCont::c_bouncer<bool>;
149 * bool b = func(&cont);
151 template <typename R
>
152 static R
c_bouncer(void *_cont
)
154 WvCont
&cont
= *(WvCont
*)_cont
;
159 static WvString
debugger_conts_run_cb(WvStringParm cmd
, WvStringList
&args
,
160 WvStreamsDebugger::ResultCallback result_cb
, void *);