Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

wvcont.h

Go to the documentation of this file.
00001 /* -*- Mode: C++ -*- 00002 * Worldvisions Weaver Software: 00003 * Copyright (C) 1997-2002 Net Integration Technologies, Inc. 00004 * 00005 * WvCont provides "continuations", which are apparently also known as 00006 * semi-coroutines. You can wrap any WvCallback<void*,void*> in a WvCont 00007 * and make it a "continuable" callback - that is, you can yield() from it 00008 * and return a value. Next time someone calls your callback, it will be 00009 * as if yield() has returned (and the parameter to your function is returned 00010 * from yield()). 00011 * 00012 * FIXME: I was too lazy to templatize this properly, so we only support 00013 * WvCallback<void*,void*>. It should be possible to work with any kind 00014 * of return value and parameter, although it makes sense to limit things 00015 * to just one parameter (since it currently has to be returned by yield() 00016 * somehow). 00017 */ 00018 #ifndef __WVCONT_H 00019 #define __WVCONT_H 00020 00021 #include "wvcallback.h" 00022 00023 class WvCont 00024 { 00025 public: 00026 /** 00027 * These are hardcoded because I'm too lazy to templatize this. 00028 * Most people will ignore the return and parameter values anyhow. 00029 */ 00030 typedef void *R; 00031 typedef void *P1; 00032 00033 typedef WvCallback<R, P1> Callback; 00034 00035 private: 00036 /** 00037 * When we copy a WvCont, we increase the reference count of the 'data' 00038 * member rather than copying it. That makes it so every copy of a given 00039 * callback object still refers to the same WvTask. 00040 */ 00041 struct Data; 00042 Data *data; 00043 00044 static Data *curdata; 00045 static int taskdepth; 00046 00047 static void bouncer(void *userdata); 00048 00049 /** 00050 * Actually call the callback inside its task, and enforce a call stack. 00051 * Doesn't do anything with arguments or return values. 00052 */ 00053 void call(); 00054 00055 WvCont(Data *data); 00056 00057 public: 00058 /** 00059 * Construct a WvCont using an existing WvCallback. The WvCont object 00060 * can be used in place of that callback, and stored in a callback of 00061 * the same data type. 00062 */ 00063 WvCont(const Callback &cb, unsigned long stacksize = 64*1024); 00064 00065 /** Copy constructor. */ 00066 WvCont(const WvCont &cb); 00067 00068 /** Destructor. */ 00069 ~WvCont(); 00070 00071 /** 00072 * call the callback, making p1 the return value of yield() or the 00073 * parameter to the function, and returning Ret, the argument of yield() 00074 * or the return value of the function. 00075 */ 00076 R operator() (P1 p1 = 0); 00077 00078 // the following are static because a function doesn't really know 00079 // which WvCont it belongs to, and only one WvCont can be the "current" 00080 // one globally in an application anyway. 00081 // 00082 // Unfortunately this prevents us from assert()ing that you're in the 00083 // context you think you are. 00084 00085 /** 00086 * Get a copy of the current WvCont. 00087 */ 00088 static WvCont current(); 00089 00090 /** 00091 * "return" from the current callback, giving value 'ret' to the person 00092 * who called us. Next time this callback is called, it's as if yield() 00093 * had returned, and the parameter to the callback is the value of 00094 * yield(). 00095 */ 00096 static P1 yield(R ret = 0); 00097 00098 /** 00099 * Tell us if the current context is "okay", that is, not trying to 00100 * die. If !isok(), you shouldn't yield(), because the caller is just 00101 * going to keep calling you until you die. Return as soon as you can. 00102 */ 00103 static bool isok(); 00104 }; 00105 00106 #endif // __WVCONT_H 00107

Generated on Tue Oct 5 01:09:20 2004 for WvStreams by doxygen 1.3.7