00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051 #include "Thread.h"
00052
00053 namespace DREAM
00054 {
00055
00056
00057
00058
00059
00060
00061
00062 NodeList::NodeList ()
00063 {
00064 }
00065
00066 NodeList::~NodeList ()
00067 {
00068 }
00069
00070 inline void NodeList::add (DREAM::Node* node_ptr)
00071 {
00072 node_map_.insert (DREAM::NODE_PAIR (node_ptr->id (), node_ptr));
00073 }
00074
00075 inline void NodeList::clear ()
00076 {
00077 node_map_.clear ();
00078 }
00079
00080 inline DREAM::Node* NodeList::find (const std::string& id) const
00081 {
00082 DREAM::NODE_MAP::const_iterator node_iter = node_map_.find (id);
00083 return node_iter != node_map_.end () ? node_iter->second : NULL;
00084 }
00085
00086 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
00087 DREAM::NODE_MAP* NodeList::get_map ()
00088 throw (DREAM::Exception)
00089 #else
00090 inline DREAM::NODE_MAP* NodeList::get_map ()
00091 #endif
00092 {
00093 return &node_map_;
00094 }
00095
00096 inline void NodeList::publish () const
00097 {
00098 std::for_each (node_map_.begin (), node_map_.end (), consume_pair ());
00099 }
00100
00101 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
00102 void NodeList::erase (const std::string& id)
00103 throw (DREAM::Exception)
00104 #else
00105 inline void NodeList::erase (const std::string& id)
00106 #endif
00107 {
00108 DREAM::NODE_MAP::iterator node_iter = node_map_.find (id);
00109
00110 if (node_iter != node_map_.end ())
00111 node_map_.erase (id);
00112 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
00113 else
00114 throw DREAM::Exception ("NodeList::erase () called with invalid Node id.");
00115 #endif
00116 }
00117
00118 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
00119 void NodeList::take_transitions ()
00120 throw (DREAM::Exception)
00121 #else
00122 inline void NodeList::take_transitions ()
00123 #endif
00124 {
00125 #ifndef DREAM_UNUSED_THREADS
00126 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
00127 if (node_map_.empty ())
00128 throw DREAM::Exception ("Thread::take_transitions () called for empty node_map_ list. No nodes are assigned to the Thread.");
00129 #endif
00130 #endif
00131
00132
00133
00134 NODE_MAP::iterator node_iter_next, node_iter = node_map_.begin ();
00135
00136 while (node_iter != node_map_.end ())
00137 {
00138 node_iter_next = node_iter;
00139 node_iter->second->take_transitions ();
00140 node_iter = ++node_iter_next;
00141 }
00142 }
00143
00144
00145
00146
00147
00148
00149
00150 Thread::Thread (DREAM::Scheduler* scheduler_ptr, uint priority, uint threads)
00151 : scheduler_ptr_ (scheduler_ptr),
00152 priority_ (priority),
00153 threads_ (threads),
00154 availablethreads_ (threads)
00155 {
00156 if (scheduler_ptr)
00157 scheduler_ptr->add_thread (this);
00158 }
00159
00160 Thread::~Thread ()
00161 {
00162 std::for_each (node_map_.begin (), node_map_.end (), delete_pair ());
00163 }
00164
00165 inline void Thread::add_error (DREAM::Task* task_ptr)
00166 {
00167 scheduler_ptr_->add_error (task_ptr);
00168 }
00169
00170 inline uint Thread::availablethreads () const
00171 {
00172 return availablethreads_;
00173 }
00174
00175 void Thread::deploy (DREAM::Scheduler* scheduler_ptr)
00176 throw (DREAM::Exception)
00177 {
00178 if (scheduler_ptr_)
00179 throw DREAM::Exception ("Thread::deploy (): Thread already assigned to a CPU.");
00180
00181 scheduler_ptr_ = scheduler_ptr;
00182 scheduler_ptr->add_thread (this);
00183 }
00184
00185 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
00186 void Thread::dequeue (DREAM::Node* node_ptr)
00187 throw (DREAM::Exception)
00188 #else
00189 inline void Thread::dequeue (DREAM::Node* node_ptr)
00190 #endif
00191 {
00192 DREAM::NODE_MAP::iterator exec_iter = exec_map_.find (node_ptr->id ());
00193
00194 if (exec_iter != exec_map_.end ())
00195 exec_map_.erase (node_ptr->id ());
00196 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
00197 else
00198 {
00199 std::string message;
00200 message << "Thread::dequeue () called with invalid Node id: " << node_ptr->id ();
00201 throw DREAM::Exception (message);
00202 }
00203 #endif
00204
00205 #ifdef DREAM_VERBOSE2
00206 if (Option::verbose1_ && Option::verbose2_)
00207 {
00208 std::string message;
00209 trace (message << node_ptr->id () << " is taken out of the execution queue");
00210 }
00211 #endif
00212 }
00213
00214 #ifdef DREAM_RACE_CONDITION
00215 inline void Thread::enqueue (DREAM::Channel* channel_ptr)
00216 {
00217 exec_map_.insert (DREAM::NODE_PAIR (channel_ptr->id (), channel_ptr));
00218
00219 #ifdef DREAM_VERBOSE2
00220 if (Option::verbose1_ && Option::verbose2_)
00221 {
00222 std::string message;
00223 trace (message << channel_ptr->id () << " enabled");
00224 }
00225 #endif
00226 }
00227
00228 inline void Thread::enqueue (DREAM::Task* task_ptr)
00229 {
00230 exec_map_.insert (DREAM::NODE_PAIR (task_ptr->id (), task_ptr));
00231 recent_avltree_.insert (task_ptr->id (), task_ptr);
00232
00233 #ifdef DREAM_VERBOSE2
00234 if (Option::verbose1_ && Option::verbose2_)
00235 {
00236 std::string message;
00237 trace (message << task_ptr->id () << " enabled");
00238 }
00239 #endif
00240 }
00241 #else
00242 inline void Thread::enqueue (DREAM::Node* node_ptr)
00243 {
00244 exec_map_.insert (DREAM::NODE_PAIR (node_ptr->id (), node_ptr));
00245
00246 #ifdef DREAM_VERBOSE2
00247 if (Option::verbose1_ && Option::verbose2_)
00248 {
00249 std::string message;
00250 trace (message << node_ptr->id () << " enabled");
00251 }
00252 #endif
00253 }
00254 #endif
00255
00256 void Thread::freethread ()
00257 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
00258 throw (DREAM::Exception)
00259 #endif
00260 {
00261 if (availablethreads_ < threads_)
00262 {
00263 ++availablethreads_;
00264 scheduler_ptr_->freeCPU ();
00265 }
00266 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
00267 else
00268 {
00269 std::string message;
00270 message << "Lane with priority \"" << priority_ << "\" deployed on Scheduler \"" << scheduler_ptr_->id () << "\" cannot free unused threads...";
00271 throw DREAM::Exception (message);
00272 }
00273 #endif
00274 }
00275
00276 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
00277 DREAM::NODE_MAP* Thread::get_exec_map ()
00278 throw (DREAM::Exception)
00279 #else
00280 inline DREAM::NODE_MAP* Thread::get_exec_map ()
00281 #endif
00282 {
00283 return &exec_map_;
00284 }
00285
00286 #ifdef DREAM_RACE_CONDITION
00287 inline const DREAM::TASK_AVLTREE* Thread::get_recent_avltree () const
00288 {
00289 return &recent_avltree_;
00290 }
00291 #endif
00292
00293 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
00294 double Thread::next_event () const
00295 throw (DREAM::Exception)
00296 #else
00297 inline double Thread::next_event () const
00298 #endif
00299 {
00300 #ifndef DREAM_UNUSED_THREADS
00301 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
00302 if (node_map_.empty ())
00303 throw DREAM::Exception ("Thread::next_event () called for empty node_map_ list. No nodes are assigned to the Thread.");
00304 #endif
00305 #endif
00306
00307 double time_step = 0.0;
00308
00309 for (DREAM::NODE_MAP::const_iterator node_iter = node_map_.begin (); node_iter != node_map_.end (); node_iter++)
00310 {
00311 double temp = node_iter->second->next_event ();
00312
00313 if (0.0 < temp && temp < time_step)
00314 time_step = temp;
00315 else if (time_step == 0.0)
00316 time_step = temp;
00317 }
00318
00319 return time_step;
00320 }
00321
00322
00323 inline uint Thread::priority () const
00324 {
00325 return priority_;
00326 }
00327
00328 #ifdef DREAM_RACE_CONDITION
00329 bool Thread::recent (DREAM::Task* task_ptr) const
00330 {
00331 if (recent_avltree_.size () < 2)
00332 return false;
00333
00334 TASK_AVLTREE::const_iterator iter;
00335
00336 for (iter = recent_avltree_.begin (); iter != recent_avltree_.end (); iter++)
00337 {
00338 if (iter->second == task_ptr)
00339 return true;
00340 }
00341
00342 return false;
00343 }
00344 #endif
00345
00346 void Thread::reset ()
00347 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
00348 throw (DREAM::Exception)
00349 #endif
00350 {
00351 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
00352 if (node_map_.empty ())
00353 throw DREAM::Exception ("Thread::reset () called for empty node_map_ list.");
00354 #endif
00355
00356 exec_map_.clear ();
00357
00358 availablethreads_ = threads ();
00359
00360 std::for_each (node_map_.begin (), node_map_.end (), reset_pair ());
00361 }
00362
00363 inline bool Thread::schedulable () const
00364 {
00365 return ((0 < availablethreads_) && (! exec_map_.empty ())) ? true : false;
00366 }
00367
00368 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
00369 const DREAM::Scheduler* Thread::scheduler () const
00370 throw (DREAM::Exception)
00371 #else
00372 inline const DREAM::Scheduler* Thread::scheduler () const
00373 #endif
00374 {
00375 return scheduler_ptr_;
00376 }
00377
00378 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
00379 DREAM::Scheduler* Thread::scheduler ()
00380 throw (DREAM::Exception)
00381 #else
00382 inline DREAM::Scheduler* Thread::scheduler ()
00383 #endif
00384 {
00385 return scheduler_ptr_;
00386 }
00387
00388 inline uint Thread::threads () const
00389 {
00390 return threads_;
00391 }
00392
00393 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
00394 void Thread::time_step (double time_step)
00395 throw (DREAM::Exception)
00396 #else
00397 inline void Thread::time_step (double time_step)
00398 #endif
00399 {
00400 #ifndef DREAM_UNUSED_THREADS
00401 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
00402 if (node_map_.empty ())
00403 throw DREAM::Exception ("Thread::time_step () called for empty node_map_ list. No nodes are assigned to the Thread.");
00404 #endif
00405 #endif
00406
00407 #ifdef DREAM_RACE_CONDITION
00408 recent_avltree_.clear ();
00409 #endif
00410
00411 for (DREAM::NODE_MAP::const_iterator node_iter = node_map_.begin (); node_iter != node_map_.end (); node_iter++)
00412 node_iter->second->clock_step (time_step);
00413 }
00414
00415
00416 inline void Thread::trace (const std::string& output) const
00417 {
00418 scheduler_ptr_->trace (output);
00419 }
00420
00421 void Thread::usethread ()
00422 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
00423 throw (DREAM::Exception)
00424 #endif
00425 {
00426 if (availablethreads_ > 0)
00427 --availablethreads_;
00428 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
00429 else
00430 {
00431 std::string message;
00432 message << "Lane with priority \"" << priority_ << "\" deployed on Scheduler \"" << scheduler_ptr_->id () << "\" has no more available threads...";
00433 throw DREAM::Exception (message);
00434 }
00435 #endif
00436 }
00437
00438 void Thread::visitor_if (DREAM::NODE_MAP* task_map, DREAM::NODE_MAP* channel_map, DREAM::NODE_MAP* timer_map, std::ofstream& f_stream)
00439 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
00440 throw (DREAM::Exception)
00441 #endif
00442 {
00443 DREAM::NODE_MAP::iterator node_iter;
00444
00445 for (node_iter = node_map_.begin (); node_iter != node_map_.end (); node_iter++)
00446 {
00447 node_iter->second->visitor_if (task_map, channel_map, timer_map, f_stream);
00448 }
00449 }
00450
00451 void Thread::visitor_map (DREAM::NODE_MAP* task_map, DREAM::NODE_MAP* channel_map, DREAM::NODE_MAP* timer_map)
00452 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
00453 throw (DREAM::Exception)
00454 #endif
00455 {
00456 DREAM::NODE_MAP::iterator node_iter;
00457
00458 for (node_iter = node_map_.begin (); node_iter != node_map_.end (); node_iter++)
00459 {
00460 node_iter->second->visitor_map (task_map, channel_map, timer_map);
00461 }
00462 }
00463
00464 void Thread::visitor_task_avltree (DREAM::TASK_AVLTREE* task_avltree)
00465 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
00466 throw (DREAM::Exception)
00467 #endif
00468 {
00469 DREAM::NODE_MAP::iterator node_iter;
00470
00471 for (node_iter = node_map_.begin (); node_iter != node_map_.end (); node_iter++)
00472 {
00473 std::string check = node_iter->first;
00474 node_iter->second->visitor_task_avltree (task_avltree);
00475 }
00476 }
00477
00478 void Thread::visitor_update_task_avltree (DREAM::TASK_AVLTREE* task_avltree)
00479 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
00480 throw (DREAM::Exception)
00481 #endif
00482 {
00483 DREAM::NODE_MAP::iterator node_iter;
00484
00485 for (node_iter = node_map_.begin (); node_iter != node_map_.end (); node_iter++)
00486 {
00487 std::string check = node_iter->first;
00488 node_iter->second->visitor_update_task_avltree (task_avltree);
00489 }
00490 }
00491
00492 void Thread::visitor_uppaal (DREAM::NODE_MAP* task_map, DREAM::NODE_MAP* channel_map, DREAM::NODE_MAP* timer_map, std::ofstream& f_stream)
00493 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
00494 throw (DREAM::Exception)
00495 #endif
00496 {
00497 DREAM::NODE_MAP::iterator node_iter;
00498
00499 for (node_iter = node_map_.begin (); node_iter != node_map_.end (); node_iter++)
00500 {
00501 node_iter->second->visitor_uppaal (task_map, channel_map, timer_map, f_stream);
00502 }
00503 }
00504
00505 }
00506