/usr/include/wvstreams/wvcont.h is in libwvstreams-dev 4.6.1-11.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 | /* -*- Mode: C++ -*-
* Worldvisions Weaver Software:
* Copyright (C) 1997-2002 Net Integration Technologies, Inc.
*
* FIXME: I was too lazy to templatize this properly, so we only support
* WvCallback<void*,void*>. It should be possible to work with any kind
* of return value and parameter, although it makes sense to limit things
* to just one parameter (since it currently has to be returned by yield()
* somehow).
*/
#ifndef __WVCONT_H
#define __WVCONT_H
#include "wvlinklist.h"
#include "wvstreamsdebugger.h"
#include "wvtr1.h"
typedef wv::function<void*(void*)> WvContCallback;
/**
* WvCont provides "continuations", which are apparently also known as
* semi-coroutines. You can wrap any WvCallback<void*,void*> in a WvCont
* and make it a "continuable" callback - that is, you can yield() from it
* and return a value. Next time someone calls your callback, it will be
* as if yield() has returned (and the parameter to your function is returned
* from yield()).
*/
class WvCont
{
struct Data;
friend struct Data;
typedef WvList<Data> DataList;
private:
/**
* When we copy a WvCont, we increase the reference count of the 'data'
* member rather than copying it. That makes it so every copy of a given
* callback object still refers to the same WvTask.
*/
Data *data;
static DataList *data_list;
static Data *curdata;
static int taskdepth;
static void bouncer(void *userdata);
/**
* Actually call the callback inside its task, and enforce a call stack.
* Doesn't do anything with arguments. Returns the return value.
*/
void *call()
{ return _call(data); }
/**
* Call the callback inside its task, but don't assume this WvCont will
* still be around when we come back.
*/
static void *_call(Data *data);
/**
* Construct a WvCont given a pre-existing Data structure. This is
* basically equivalent to using the copy constructor.
*/
WvCont(Data *data);
public:
/**
* Construct a WvCont using an existing WvCallback. The WvCont object
* can be used in place of that callback, and stored in a callback of
* the same data type.
*/
WvCont(const WvContCallback &cb, unsigned long stacksize = 64*1024);
/** Copy constructor. */
WvCont(const WvCont &cb);
/** Destructor. */
~WvCont();
/**
* call the callback, making p1 the return value of yield() or the
* parameter to the function, and returning Ret, the argument of yield()
* or the return value of the function.
*/
void *operator() (void *p1 = 0);
// the following are static because a function doesn't really know
// which WvCont it belongs to, and only one WvCont can be the "current"
// one globally in an application anyway.
//
// Unfortunately this prevents us from assert()ing that you're in the
// context you think you are.
/**
* Get a copy of the current WvCont.
*/
static WvCont current();
/**
* "return" from the current callback, giving value 'ret' to the person
* who called us. Next time this callback is called, it's as if yield()
* had returned, and the parameter to the callback is the value of
* yield().
*/
static void *yield(void *ret = 0);
/**
* Tell us if the current context is "okay", that is, not trying to
* die. If !isok(), you shouldn't yield(), because the caller is just
* going to keep calling you until you die. Return as soon as you can.
*/
static bool isok();
/**
* A templated function that allows you to pass a WvCont wherever a
* C-style function pointer of the form
* R func(T, void *userdata)
* is taken. It's your job to make sure the 'userdata' provided is
* a pointer to the right WvCont.
*
* Example:
* typedef bool MyFunc(Obj *obj, void *userdata);
* WvCont cont;
* MyFunc *func = &WvCont::c_bouncer<bool,Obj *>;
* bool b = func(new Obj, &cont);
*/
template <typename R, typename T>
static R c_bouncer(T t, void *_cont)
{
WvCont &cont = *(WvCont *)_cont;
return (R)cont((T)t);
}
/**
* A templated function that allows you to pass a WvCont wherever a
* C-style function pointer of the form
* R func(void *userdata)
* is taken. It's your job to make sure the 'userdata' provided is
* a pointer to the right WvCont.
*
* Example:
* typedef bool MyFunc(void *userdata);
* WvCont cont;
* MyFunc *func = &WvCont::c_bouncer<bool>;
* bool b = func(&cont);
*/
template <typename R>
static R c_bouncer(void *_cont)
{
WvCont &cont = *(WvCont *)_cont;
return (R)cont(0);
}
private:
static WvString debugger_conts_run_cb(WvStringParm cmd, WvStringList &args,
WvStreamsDebugger::ResultCallback result_cb, void *);
};
#endif // __WVCONT_H
|