00001 #include "mtasker.hh"
00002 #include <stdio.h>
00003 #include <iostream>
00004
00131
00132
00146 template<class EventKey, class EventVal>int MTasker<EventKey,EventVal>::waitEvent(const EventKey &key, EventVal *val, unsigned int timeout)
00147 {
00148 Waiter w;
00149 w.context=new ucontext_t;
00150 w.ttd= timeout ? time(0)+timeout : 0;
00151 w.tid=d_tid;
00152
00153 d_waiters[key]=w;
00154
00155 swapcontext(d_waiters[key].context,&d_kernel);
00156 if(val && d_waitstatus==Answer)
00157 *val=d_waitval;
00158 d_tid=w.tid;
00159 return d_waitstatus;
00160 }
00161
00163
00165 template<class Key, class Val>void MTasker<Key,Val>::yield()
00166 {
00167 d_runQueue.push(d_tid);
00168 swapcontext(d_threads[d_tid],&d_kernel);
00169 }
00170
00172
00177 template<class EventKey, class EventVal>int MTasker<EventKey,EventVal>::sendEvent(const EventKey& key, const EventVal* val)
00178 {
00179 if(!d_waiters.count(key)) {
00180 return 0;
00181 }
00182
00183 d_waitstatus=Answer;
00184 if(val)
00185 d_waitval=*val;
00186
00187 ucontext_t *userspace=d_waiters[key].context;
00188 d_tid=d_waiters[key].tid;
00189
00190 d_waiters.erase(key);
00191 swapcontext(&d_kernel,userspace);
00192
00193 delete userspace;
00194 return 1;
00195 }
00196
00198
00202 template<class Key, class Val>void MTasker<Key,Val>::makeThread(tfunc_t *start, void* val)
00203 {
00204 ucontext_t *uc=new ucontext_t;
00205 getcontext(uc);
00206
00207 uc->uc_link = &d_kernel;
00208 uc->uc_stack.ss_sp = new char[d_stacksize];
00209
00210 uc->uc_stack.ss_size = d_stacksize;
00211 #ifdef SOLARIS
00212 makecontext (uc, (void (*)(...))threadWrapper, 4, this, start, d_maxtid, val);
00213 #else
00214 makecontext (uc, (void (*)(void))threadWrapper, 4, this, start, d_maxtid, val);
00215 #endif
00216 d_threads[d_maxtid]=uc;
00217 d_runQueue.push(d_maxtid++);
00218 }
00219
00220
00222
00231 template<class Key, class Val>bool MTasker<Key,Val>::schedule()
00232 {
00233
00234 if(!d_runQueue.empty()) {
00235 d_tid=d_runQueue.front();
00236 swapcontext(&d_kernel, d_threads[d_tid]);
00237 d_runQueue.pop();
00238 return true;
00239 }
00240 if(!d_zombiesQueue.empty()) {
00241 delete[] (char *)d_threads[d_zombiesQueue.front()]->uc_stack.ss_sp;
00242 delete d_threads[d_zombiesQueue.front()];
00243 d_threads.erase(d_zombiesQueue.front());
00244 d_zombiesQueue.pop();
00245 return true;
00246 }
00247 if(!d_waiters.empty()) {
00248 time_t now=time(0);
00249 for(typename waiters_t::const_iterator i=d_waiters.begin();i!=d_waiters.end();++i) {
00250 if(i->second.ttd && i->second.ttd<now) {
00251 d_waitstatus=TimeOut;
00252 swapcontext(&d_kernel,i->second.context);
00253 delete i->second.context;
00254 d_waiters.erase(i->first);
00255 }
00256 }
00257 }
00258 return false;
00259 }
00260
00262
00265 template<class Key, class Val>bool MTasker<Key,Val>::noProcesses()
00266 {
00267 return d_threads.empty();
00268 }
00269
00271
00274 template<class Key, class Val>unsigned int MTasker<Key,Val>::numProcesses()
00275 {
00276 return d_threads.size();
00277 }
00278
00279
00281
00287 template<class Key, class Val>void MTasker<Key,Val>::getEvents(std::vector<Key>& events)
00288 {
00289 events.clear();
00290 for(typename waiters_t::const_iterator i=d_waiters.begin();i!=d_waiters.end();++i) {
00291 events.push_back(i->first);
00292 }
00293 }
00294
00295
00296 template<class Key, class Val>void MTasker<Key,Val>::threadWrapper(MTasker *self, tfunc_t *tf, int tid, void* val)
00297 {
00298 (*tf)(val);
00299 self->d_zombiesQueue.push(tid);
00300
00301
00302 }
00303
00305
00308 template<class Key, class Val>int MTasker<Key,Val>::getTid()
00309 {
00310 return d_tid;
00311 }