Main Page | Class Hierarchy | Class List | File List | Class Members

mtasker.cc

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); // 'A' will return here when 'key' has arrived, hands over control to kernel first
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); // give control to the 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;         // set tid 
00189   
00190   d_waiters.erase(key);             // removes the waitpoint 
00191   swapcontext(&d_kernel,userspace); // swaps back to the above point 'A'
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; // come back to kernel after dying
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++); // will run at next schedule invocation
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); // swaps back to the above point 'A'
00253         delete i->second.context;              
00254         d_waiters.erase(i->first);                  // removes the waitpoint 
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   // we now jump to &kernel, automatically
00302 }
00303 
00305 
00308 template<class Key, class Val>int MTasker<Key,Val>::getTid()
00309 {
00310   return d_tid;
00311 }

Generated on Sun Feb 8 12:07:52 2004 for MTasker by doxygen 1.3.5