WvStreams
|
00001 /* -*- Mode: C++ -*- 00002 * Worldvisions Weaver Software: 00003 * Copyright (C) 1997-2002 Net Integration Technologies, Inc. 00004 * 00005 * A set of classes that provide co-operative multitasking support. By 00006 * default there's no scheduler -- you have to provide it yourself. As it 00007 * stands, this is just a convenient way to switch from one context to 00008 * another when you know exactly what you want to do. 00009 * 00010 * This is mainly intended for use by WvStream, but that's probably not the 00011 * only possible use... see also WvCont. 00012 */ 00013 #ifndef __WVTASK_H 00014 #define __WVTASK_H 00015 00016 #ifdef _WIN32 00017 00018 #include "wvwin32task.h" 00019 00020 #else 00021 00022 #include "wvstring.h" 00023 #include "wvlinklist.h" 00024 #include "wvstreamsdebugger.h" 00025 #include "wvstringlist.h" 00026 #include "setjmp.h" 00027 #include <ucontext.h> 00028 00029 #define WVTASK_MAGIC 0x123678 00030 00031 class WvTaskMan; 00032 00034 class WvTask 00035 { 00036 friend class WvTaskMan; 00037 00038 // you might think it would be useful to have this return an int, since 00039 // yield() and run() both return int. But that ends up being more 00040 // confusing than you think, because if you call task1->run(), and he 00041 // calls task2->run(), and task2 calls yield(), then task1->run() returns 00042 // the value *task2* passed to yield! So we avoid the confusion by not 00043 // using return values here, which discourages people from thinking of 00044 // them as return values. 00045 typedef void TaskFunc(void *userdata); 00046 00047 static int taskcount, numtasks, numrunning; 00048 int magic_number, *stack_magic; 00049 WvString name; 00050 int tid; 00051 00052 size_t stacksize; 00053 void *stack; 00054 bool running, recycled; 00055 00056 WvTaskMan &man; 00057 ucontext_t mystate; // used for resuming the task 00058 ucontext_t func_call, func_return; 00059 00060 TaskFunc *func; 00061 void *userdata; 00062 00063 WvTask(WvTaskMan &_man, size_t _stacksize = 64*1024); 00064 00065 public: 00066 virtual ~WvTask(); 00067 00068 void start(WvStringParm _name, TaskFunc *_func, void *_userdata); 00069 bool isrunning() const 00070 { return running; } 00071 void recycle(); 00072 int get_tid() const { return tid; } 00073 WvString get_name() const { return name; } 00074 }; 00075 00076 00077 DeclareWvList(WvTask); 00078 00080 class WvTaskMan 00081 { 00082 friend class WvTask; 00083 00084 static WvTaskMan *singleton; 00085 static int links; 00086 00087 static int magic_number; 00088 static WvTaskList all_tasks, free_tasks; 00089 00090 static void get_stack(WvTask &task, size_t size); 00091 static void stackmaster(); 00092 static void _stackmaster(); 00093 static void do_task(); 00094 static void call_func(WvTask *task); 00095 00096 static char *stacktop; 00097 static ucontext_t stackmaster_task; 00098 00099 static WvTask *stack_target; 00100 static ucontext_t get_stack_return; 00101 00102 static WvTask *current_task; 00103 static ucontext_t toplevel; 00104 00105 WvTaskMan(); 00106 virtual ~WvTaskMan(); 00107 00108 #ifdef ENABLE_DELETE_DETECTOR 00109 friend void operator &&<WvTaskMan>(CheckIObject, const WvTaskMan *); 00110 #endif 00111 00112 public: 00114 static WvTaskMan *get(); 00115 static void unlink(); 00116 00117 WvTask *start(WvStringParm name, 00118 WvTask::TaskFunc *func, void *userdata, 00119 size_t stacksize = 64*1024); 00120 00121 // run() and yield() return the 'val' passed to run() when this task 00122 // was started. 00123 static int run(WvTask &task, int val = 1); 00124 static int yield(int val = 1); 00125 00126 static WvTask *whoami() 00127 { return current_task; } 00128 00129 static const void *current_top_of_stack(); 00130 static size_t current_stacksize_limit(); 00131 00132 private: 00133 static WvString debugger_tasks_run_cb(WvStringParm, WvStringList &, 00134 WvStreamsDebugger::ResultCallback, void *); 00135 }; 00136 00137 00138 #endif // ifdef _WIN32 00139 #endif // __WVTASK_H