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
|
/* -*- Mode: C++ -*-
* Worldvisions Weaver Software:
* Copyright (C) 1997-2002 Net Integration Technologies, Inc.
*
* A set of classes that provide co-operative multitasking support. By
* default there's no scheduler -- you have to provide it yourself. As it
* stands, this is just a convenient way to switch from one context to
* another when you know exactly what you want to do.
*
* This is mainly intended for use by WvStream, but that's probably not the
* only possible use... see also WvCont.
*/
#ifndef __WVTASK_H
#define __WVTASK_H
#ifdef _WIN32
#include "wvwin32task.h"
#else
#include "wvstring.h"
#include "wvlinklist.h"
#include "setjmp.h"
#define WVTASK_MAGIC 0x123678
class WvTaskMan;
/** Represents a single thread of control. */
class WvTask
{
friend class WvTaskMan;
// you might think it would be useful to have this return an int, since
// yield() and run() both return int. But that ends up being more
// confusing than you think, because if you call task1->run(), and he
// calls task2->run(), and task2 calls yield(), then task1->run() returns
// the value *task2* passed to yield! So we avoid the confusion by not
// using return values here, which discourages people from thinking of
// them as return values.
typedef void TaskFunc(void *userdata);
static int taskcount, numtasks, numrunning;
int magic_number, *stack_magic;
WvString name;
int tid;
size_t stacksize;
bool running, recycled;
WvTaskMan &man;
jmp_buf mystate; // used for resuming the task
TaskFunc *func;
void *userdata;
WvTask(WvTaskMan &_man, size_t _stacksize = 64*1024);
public:
virtual ~WvTask();
void start(WvStringParm _name, TaskFunc *_func, void *_userdata);
bool isrunning() const
{ return running; }
void recycle();
};
DeclareWvList(WvTask);
/** Provides co-operative multitasking support among WvTask instances. */
class WvTaskMan
{
friend class WvTask;
static WvTaskMan *singleton;
static int links;
static int magic_number;
static WvTaskList free_tasks;
static void get_stack(WvTask &task, size_t size);
static void stackmaster();
static void _stackmaster();
static void do_task();
static char *stacktop;
static jmp_buf stackmaster_task;
static WvTask *stack_target;
static jmp_buf get_stack_return;
static WvTask *current_task;
static jmp_buf toplevel;
WvTaskMan();
virtual ~WvTaskMan();
#ifdef ENABLE_DELETE_DETECTOR
friend void operator &&<WvTaskMan>(CheckIObject, const WvTaskMan *);
#endif
public:
/// get/dereference the singleton global WvTaskMan
static WvTaskMan *get();
static void unlink();
WvTask *start(WvStringParm name,
WvTask::TaskFunc *func, void *userdata,
size_t stacksize = 64*1024);
// run() and yield() return the 'val' passed to run() when this task
// was started.
static int run(WvTask &task, int val = 1);
static int yield(int val = 1);
static WvTask *whoami()
{ return current_task; }
};
#endif // ifdef _WIN32
#endif // __WVTASK_H
|