00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include "thread.h"
00018
00019
00020
00021 ThreadKernel *ThreadKernel::kernel=NULL;
00022
00023
00024 int ThreadKernel::_NRunningThreads()
00025 {
00026 mutex.lock();
00027 int n=nrunning;
00028 mutex.unlock();
00029
00030 return(n);
00031 }
00032
00033
00034 void *ThreadKernel::_ThreadFuncWrapper(void *ptr)
00035 {
00036
00037
00038
00039 ExecutionThread *ethread=(ExecutionThread*)ptr;
00040
00041
00042 TNode *tn=new TNode();
00043 tn->thread=g_thread_self();
00044 tn->execthread=ethread;
00045
00046 mutex.lock();
00047 threadlist.append(tn);
00048 ++nrunning;
00049 mutex.unlock();
00050
00051
00052 g_private_set(phook,tn);
00053
00054
00055 bool rv=g_atomic_pointer_compare_and_exchange(
00056 (gpointer*)ðread->handle,NULL,tn);
00057 CritAssert(rv);
00058
00059
00060 ethread->run();
00061
00062
00063 return(NULL);
00064 }
00065
00066 void *ThreadKernel::ThreadFuncWrapper(void *ptr)
00067 {
00068
00069 return(ThreadKernel::kernel->_ThreadFuncWrapper(ptr));
00070 }
00071
00072
00073 void ThreadKernel::_PhookNotifier(gpointer ptr)
00074 {
00075
00076
00077
00078
00079
00080 if(ptr==this)
00081 {
00082
00083 CritAssert(0);
00084 return;
00085 }
00086
00087 TNode *tn=(TNode*)ptr;
00088 CritAssert(tn->thread==g_thread_self());
00089
00090 mutex.lock();
00091
00092
00093
00094 if(tn->execthread)
00095 {
00096 bool rv=g_atomic_pointer_compare_and_exchange(
00097 (gpointer*)&tn->execthread->handle,tn,NULL);
00098
00099
00100 CritAssert(rv);
00101
00102
00103 }
00104
00105
00106
00107 tn->thread=NULL;
00108
00109
00110 threadlist.dequeue(tn);
00111 --nrunning;
00112
00113 mutex.unlock();
00114
00115
00116 delete tn;
00117 }
00118
00119 void ThreadKernel::PhookNotifier(gpointer ptr)
00120 {
00121
00122 ThreadKernel::kernel->_PhookNotifier(ptr);
00123 }
00124
00125
00126 void ThreadKernel::_unregister(ExecutionThread *et)
00127 {
00128
00129
00130 if(!g_atomic_pointer_get((gpointer*)&kernel)) return;
00131
00132
00133 mutex.lock();
00134
00135 if(this && et->handle)
00136 {
00137
00138 TNode *tn=et->handle;
00139 et->handle=NULL;
00140
00141
00142 tn->execthread=NULL;
00143 }
00144
00145 mutex.unlock();
00146 }
00147
00148
00149 void ThreadKernel::init()
00150 {
00151
00152 new ThreadKernel();
00153 }
00154
00155 void ThreadKernel::cleanup()
00156 {
00157 if(ThreadKernel::kernel)
00158 { delete ThreadKernel::kernel; }
00159 }
00160
00161
00162 ThreadKernel::ThreadKernel() :
00163 mutex(),
00164 threadlist(),
00165 nrunning(0)
00166 {
00167
00168 g_thread_init(NULL);
00169 CritAssert(g_thread_supported());
00170
00171
00172 mutex.lock();
00173
00174
00175
00176
00177 phook=g_private_new(&PhookNotifier);
00178 CritAssert(phook);
00179
00180 g_private_set(phook,this);
00181
00182 Assert(!ThreadKernel::kernel);
00183 ThreadKernel::kernel=this;
00184
00185 mutex.unlock();
00186 }
00187
00188 ThreadKernel::~ThreadKernel()
00189 {
00190 mutex.lock();
00191
00192
00193
00194
00195 CritAssert(threadlist.IsEmpty());
00196 while(!threadlist.IsEmpty())
00197 {
00198 delete threadlist.PopFirst();
00199 --nrunning;
00200 }
00201
00202
00203 g_private_set(phook,NULL);
00204 phook=NULL;
00205
00206 Assert(ThreadKernel::kernel==this);
00207 ThreadKernel::kernel=NULL;
00208
00209 mutex.unlock();
00210 }
00211
00212
00213
00214
00215 int ExecutionThread::start()
00216 {
00217 if(g_atomic_pointer_get(&handle)) return(-2);
00218
00219
00220
00221
00222
00223 GThread *thread=g_thread_create(
00224 &ThreadKernel::ThreadFuncWrapper,this,
00225 0,NULL);
00226 if(!thread)
00227 {
00229
00230 return(-3);
00231 }
00232
00237 for(;;)
00238 {
00239 if(g_atomic_pointer_get(&handle)) break;
00240 g_thread_yield();
00241 }
00242
00243 return(0);
00244 }
00245
00246
00247 void ExecutionThread::exit()
00248 {
00249 g_thread_exit(NULL);
00250 }
00251
00252
00253 void ExecutionThread::yield()
00254 {
00255 g_thread_yield();
00256 }
00257
00258
00259 void ExecutionThread::run()
00260 {
00261
00262
00263 return;
00264 }
00265
00266
00267
00268 ExecutionThread::ExecutionThread()
00269 {
00270 handle=NULL;
00271 }
00272
00273 ExecutionThread::~ExecutionThread()
00274 {
00275
00276 ThreadKernel::unregister(this);
00277 }
00278
00279
00280 #if 0
00281 #include <stdio.h>
00282 #include <sched.h>
00283
00284
00285
00286
00287 class MyThreadA : public ExecutionThread
00288 {
00289 void run()
00290 {
00291 for(int i=0; i<100; i++)
00292 {
00293 fprintf(stderr,"runA\t");
00294 yield();
00295 }
00296 }
00297 };
00298
00299 class MyThreadB : public ExecutionThread
00300 {
00301 void run()
00302 {
00303 for(int i=0; i<100; i++)
00304 {
00305 fprintf(stderr,"runB\t");
00306 yield();
00307 if(i==40) exit();
00308 }
00309 }
00310 };
00311
00312
00313 int main()
00314 {
00315 ThreadKernel::init();
00316
00317 MyThreadA A;
00318 MyThreadB B;
00319 fprintf(stderr,"A=%p, B=%p\n",&A,&B);
00320
00321 A.start();
00322 B.start();
00323
00324 for(int i=0; i<50; i++)
00325 {
00326 sched_yield();
00327 A.start();
00328 if(!B.running())
00329 {
00330 fprintf(stderr,"B-OUT!");
00331 B.start();
00332 }
00333 }
00334
00335 fprintf(stderr,"Press any key..."); getchar();
00336
00337 ThreadKernel::cleanup();
00338
00339 fprintf(stderr,"Exiting\n");
00340 return(0);
00341 }
00342
00343 #endif