Thread.cpp

Go to the documentation of this file.
00001 /** @file Thread.cpp
00002 * @author Gabor Madl
00003 * @date Created 02/2005
00004 * @brief Thread implementation.
00005 *
00006 *
00007 * =================================================================
00008 * DREAM License v2.0
00009 * 
00010 * DREAM - Distributed Real-time Embedded Analysis Method
00011 * http://dre.sourceforge.net.
00012 * Copyright (c) 2005-2007 Gabor Madl, All Rights Reserved.
00013 * 
00014 * This file is part of DREAM.
00015 * 
00016 * DREAM is free software; you can redistribute it and/or modify it
00017 * under the terms of the GNU General Public License version 2 as
00018 * published by the Free Software Foundation. No future versions of
00019 * the GPL license may be automatically applied to DREAM. It is in
00020 * the sole discretion of the copyright holder to determine whether
00021 * DREAM may be released under a different license or terms. There
00022 * are no restrictions on the use of DREAM for any purpose.
00023 * 
00024 * DREAM is distributed in the hope that it will be useful,
00025 * but WITHOUT ANY WARRANTY; without even the implied warranty of
00026 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00027 * GNU General Public License for more details.
00028 * 
00029 * You should have received a copy of the GNU General Public License
00030 * along with this program; if not, write to the Free Software
00031 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
00032 * MA 02110-1301, USA.
00033 * 
00034 * By submitting comments, suggestions, code, code snippets,
00035 * techniques (including that of usage), and algorithms, submitters
00036 * acknowledge that they have the right to do so, that any such
00037 * submissions are given freely and unreservedly, and that they
00038 * waive any claims to copyright or ownership. In addition,
00039 * submitters acknowledge that any such submission might become
00040 * part of the copyright maintained on the overall body of code,
00041 * which comprises DREAM. By making a submission, submitter agrees
00042 * to these terms. Furthermore, submitters acknowledge that the
00043 * incorporation or modification of such submissions is entirely
00044 * at the discretion of the moderators of the DREAM project.
00045 * 
00046 * DREAM links to the Libxml2 third party library. Please see 
00047 * COPYING-libxml for the copyright information of Libxml2.
00048 * =================================================================
00049 */
00050 
00051 #include "Thread.h"
00052 
00053 namespace DREAM
00054 {
00055 
00056 /////////////////////////////////////////////////////////////////////////////
00057 //
00058 // NodeList
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         // Nodes might dequeue themselves from the exec_map therefore a simple
00133         // for_each won't do the job...
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 // Thread
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 

Generated on Fri Jul 27 18:30:03 2007 for DREAM by  doxygen 1.5.1