1c08f5a1aa15fefb02d47824e2ee27316d77d32f
[wvstreams.git] / include / wvcont.h
blob1c08f5a1aa15fefb02d47824e2ee27316d77d32f
1 /* -*- Mode: C++ -*-
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()
9 * somehow).
12 #ifndef __WVCONT_H
13 #define __WVCONT_H
15 #include "wvlinklist.h"
16 #include "wvstreamsdebugger.h"
17 #include "wvtr1.h"
19 typedef wv::function<void*(void*)> WvContCallback;
21 /**
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
27 * from yield()).
29 class WvCont
31 struct Data;
32 friend struct Data;
33 typedef WvList<Data> DataList;
35 private:
36 /**
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.
41 Data *data;
42 static DataList *data_list;
44 static Data *curdata;
45 static int taskdepth;
47 static void bouncer(void *userdata);
49 /**
50 * Actually call the callback inside its task, and enforce a call stack.
51 * Doesn't do anything with arguments. Returns the return value.
53 void *call()
54 { return _call(data); }
56 /**
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);
62 /**
63 * Construct a WvCont given a pre-existing Data structure. This is
64 * basically equivalent to using the copy constructor.
66 WvCont(Data *data);
68 public:
69 /**
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
72 * the same data type.
74 WvCont(const WvContCallback &cb, unsigned long stacksize = 64*1024);
76 /** Copy constructor. */
77 WvCont(const WvCont &cb);
79 /** Destructor. */
80 ~WvCont();
82 /**
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.
92 //
93 // Unfortunately this prevents us from assert()ing that you're in the
94 // context you think you are.
96 /**
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
105 * yield().
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.
114 static bool isok();
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.
124 * Example:
125 * typedef bool MyFunc(Obj *obj, void *userdata);
126 * WvCont cont;
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.
145 * Example:
146 * typedef bool MyFunc(void *userdata);
147 * WvCont cont;
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;
155 return (R)cont(0);
158 private:
159 static WvString debugger_conts_run_cb(WvStringParm cmd, WvStringList &args,
160 WvStreamsDebugger::ResultCallback result_cb, void *);
163 #endif // __WVCONT_H