src/sysc/kernel/sc_runnable_int.h

Go to the documentation of this file.
00001 /*****************************************************************************
00002 
00003   The following code is derived, directly or indirectly, from the SystemC
00004   source code Copyright (c) 1996-2005 by all Contributors.
00005   All Rights reserved.
00006 
00007   The contents of this file are subject to the restrictions and limitations
00008   set forth in the SystemC Open Source License Version 2.4 (the "License");
00009   You may not use this file except in compliance with such restrictions and
00010   limitations. You may obtain instructions on how to receive a copy of the
00011   License at http://www.systemc.org/. Software distributed by Contributors
00012   under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
00013   ANY KIND, either express or implied. See the License for the specific
00014   language governing rights and limitations under the License.
00015 
00016  *****************************************************************************/
00017 
00018 /*****************************************************************************
00019 
00020   sc_runnable_int.h -- For inline definitions of some utility functions.
00021                        DO NOT EXPORT THIS INCLUDE FILE. Include this file
00022                        after "sc_process_int.h" so that we can get the base
00023                        class right.
00024 
00025   Original Author: Bishnupriya Bhattacharya , Cadence Design, 28th July, 2003
00026 
00027  *****************************************************************************/
00028 
00029 /*****************************************************************************
00030 
00031   MODIFICATION LOG - modifiers, enter your name, affiliation, date and
00032   changes you are making here.
00033       Andy Goodrich, Forte Design Systems, 2 September 2003
00034       Changed queue heads to instances to eliminate the checks for null heads.
00035 
00036  *****************************************************************************/
00037 
00038 #ifndef SC_RUNNABLE_INT_H
00039 #define SC_RUNNABLE_INT_H
00040 
00041 
00042 #include "sysc/kernel/sc_runnable.h"
00043 
00044 namespace sc_core {
00045 
00046 // The values below are used to indicate when a queue is empty. A non-zero     
00047 // non-legal pointer value is used for this so that a zero value in the
00048 // m_execute_p field of an sc_process_b instance can be used to indicate      
00049 // that is has not been queued for run. (If we did not use a non-zero
00050 // queue empty indicator then a sc_process_b instance that was queued
00051 // twice in a row might end up on the queue twice if it were the first
00052 // one that was queued!)
00053 
00054 #define SC_NO_METHODS ((sc_method_handle)0xdb)
00055 #define SC_NO_THREADS ((sc_thread_handle)0xdb)
00056 
00057 
00058 //------------------------------------------------------------------------------
00059 //"sc_runnable::init"
00060 //
00061 // This method initializes this object instance. Note we allocate the queue
00062 // heads if necessary. This is done here rather than in the constructor for
00063 // this class to eliminate CTOR processing errors with gcc.
00064 //------------------------------------------------------------------------------
00065 inline void sc_runnable::init()
00066 {
00067     m_methods_pop = SC_NO_METHODS;
00068     if ( !m_methods_push_head )
00069     {
00070         m_methods_push_head = 
00071             new sc_method_process(0, 0, 0);
00072         m_methods_push_head->do_initialize(false);
00073     }
00074     m_methods_push_tail = m_methods_push_head;
00075         m_methods_push_head->set_next_runnable(SC_NO_METHODS);
00076 
00077     m_threads_pop = SC_NO_THREADS;
00078     if ( !m_threads_push_head )
00079     {
00080         m_threads_push_head = 
00081             new sc_thread_process(0, 0, 0);
00082         m_threads_push_head->do_initialize(false);
00083     }
00084         m_threads_push_head->set_next_runnable(SC_NO_THREADS);
00085     m_threads_push_tail = m_threads_push_head;
00086 }
00087 
00088 
00089 //------------------------------------------------------------------------------
00090 //"sc_runnable::is_empty"
00091 //
00092 // This method returns true if the push queue is empty, or false if not.
00093 //------------------------------------------------------------------------------
00094 inline bool sc_runnable::is_empty() const
00095 {
00096     return m_methods_push_head->next_runnable() == SC_NO_METHODS && 
00097                 m_threads_push_head->next_runnable() == SC_NO_THREADS;
00098 }
00099 
00100 
00101 //------------------------------------------------------------------------------
00102 //"sc_runnable::push_back_method"
00103 //
00104 // This method pushes the supplied method process onto the back of the queue of 
00105 // runnable method processes.
00106 //     method_h -> method process to add to the queue.
00107 //------------------------------------------------------------------------------
00108 inline void sc_runnable::push_back_method( sc_method_handle method_h )
00109 {
00110     // assert( method_h->next_runnable() == 0 ); // Can't queue twice.
00111     method_h->set_next_runnable(SC_NO_METHODS);
00112     m_methods_push_tail->set_next_runnable(method_h);
00113     m_methods_push_tail = method_h;
00114 }
00115 
00116 
00117 //------------------------------------------------------------------------------
00118 //"sc_runnable::push_back_thread"
00119 //
00120 // This method pushes the supplied thread process onto the back of the queue of 
00121 // runnable thread processes.
00122 //     thread_h -> thread process to add to the queue.
00123 //------------------------------------------------------------------------------
00124 inline void sc_runnable::push_back_thread( sc_thread_handle thread_h )
00125 {
00126     // assert( thread_h->next_runnable() == 0 ); // Can't queue twice.
00127     thread_h->set_next_runnable(SC_NO_THREADS);
00128     m_threads_push_tail->set_next_runnable(thread_h);
00129     m_threads_push_tail = thread_h;
00130 }
00131 
00132 
00133 //------------------------------------------------------------------------------
00134 //"sc_runnable::push_front_method"
00135 //
00136 // This method pushes the supplied method process onto the front of the queue of
00137 // runnable method processes. If the queue is empty the process is the tail 
00138 // also.
00139 //     method_h -> method process to add to the queue.
00140 //------------------------------------------------------------------------------
00141 inline void sc_runnable::push_front_method( sc_method_handle method_h )
00142 {
00143     // assert( method_h->next_runnable() == 0 ); // Can't queue twice.
00144     method_h->set_next_runnable(m_methods_push_head->next_runnable());
00145     if ( m_methods_push_tail == m_methods_push_head ) // Empty queue.
00146     {
00147         m_methods_push_tail->set_next_runnable(method_h);
00148         m_methods_push_tail = method_h;
00149     }
00150     else                                               // Non-empty queue.
00151     {
00152         m_methods_push_head->set_next_runnable(method_h);
00153     }
00154 }
00155 
00156 
00157 //------------------------------------------------------------------------------
00158 //"sc_runnable::push_front_thread"
00159 //
00160 // This method pushes the supplied thread process onto the front of the queue of
00161 // runnable thread processes. If the queue is empty the process is the tail 
00162 // also.
00163 //     thread_h -> thread process to add to the queue.
00164 //------------------------------------------------------------------------------
00165 inline void sc_runnable::push_front_thread( sc_thread_handle thread_h )
00166 {
00167     // assert( thread_h->next_runnable() == 0 ); // Can't queue twice.
00168     thread_h->set_next_runnable(m_threads_push_head->next_runnable());
00169     if ( m_threads_push_tail == m_threads_push_head ) // Empty queue.
00170     {
00171         m_threads_push_tail->set_next_runnable(thread_h);
00172         m_threads_push_tail = thread_h;
00173     }
00174     else                                               // Non-empty queue.
00175     {
00176         m_threads_push_head->set_next_runnable(thread_h);
00177     }
00178 }
00179 
00180 
00181 //------------------------------------------------------------------------------
00182 //"sc_runnable::pop_method"
00183 //
00184 // This method pops the next method process to be executed, or returns a null 
00185 // if no method processes are available for execution.
00186 //------------------------------------------------------------------------------
00187 inline sc_method_handle sc_runnable::pop_method()
00188 {
00189     sc_method_handle result_p;
00190 
00191     result_p = m_methods_pop;
00192     if ( result_p != SC_NO_METHODS ) 
00193     {
00194         m_methods_pop = result_p->next_runnable();
00195         result_p->set_next_runnable(0);
00196     }
00197         else
00198         {
00199                 result_p = 0;
00200         }
00201     return result_p;
00202 
00203 }
00204 
00205 //------------------------------------------------------------------------------
00206 //"sc_runnable::pop_thread"
00207 //
00208 // This method pops the next thread process to be executed, or returns a null 
00209 // if no thread processes are available for execution.
00210 //------------------------------------------------------------------------------
00211 inline sc_thread_handle sc_runnable::pop_thread()
00212 {
00213     sc_thread_handle result_p;
00214 
00215     result_p = m_threads_pop;
00216     if ( result_p != SC_NO_THREADS ) 
00217     {
00218         m_threads_pop = result_p->next_runnable();
00219         result_p->set_next_runnable(0);
00220     }
00221         else
00222         {
00223                 result_p = 0;
00224         }
00225     return result_p;
00226 }
00227 
00228 
00229 //------------------------------------------------------------------------------
00230 //"sc_runnable::remove_method"
00231 //
00232 // This method removes the supplied method process from the push queue if it is
00233 // present. Note we clear the method's next pointer so that it may be queued 
00234 // again.
00235 //     remove_p -> method process to remove from the run queue.
00236 //------------------------------------------------------------------------------
00237 inline void sc_runnable::remove_method( sc_method_handle remove_p )
00238 {
00239     sc_method_handle now_p;     // Method now checking.
00240     sc_method_handle prior_p;   // Method prior to now_p.
00241 
00242     prior_p = m_methods_push_head;
00243     for ( now_p = m_methods_push_head; now_p; now_p = now_p->next_runnable() )
00244     {
00245         if ( remove_p == now_p )
00246         {
00247             prior_p->set_next_runnable( now_p->next_runnable() );
00248             if (now_p == m_methods_push_tail) {
00249                 m_methods_push_tail = prior_p;
00250             }
00251             now_p->set_next_runnable(0);
00252             break;
00253         }
00254         prior_p = now_p;
00255     }
00256 }
00257 
00258 
00259 //------------------------------------------------------------------------------
00260 //"sc_runnable::remove_thread"
00261 //
00262 // This method removes the supplied thread process from the push queue if it is
00263 // present. Note we clear the thread's next pointer so that it may be queued 
00264 // again.
00265 //     remove_p -> thread process to remove from the run queue.
00266 //------------------------------------------------------------------------------
00267 inline void sc_runnable::remove_thread( sc_thread_handle remove_p )
00268 {
00269     sc_thread_handle now_p;     // Thread now checking.
00270     sc_thread_handle prior_p;   // Thread prior to now_p.
00271 
00272     prior_p = m_threads_push_head;
00273     for ( now_p = m_threads_push_head; now_p; now_p = now_p->next_runnable() )
00274     {
00275         if ( remove_p == now_p )
00276         {
00277             prior_p->set_next_runnable( now_p->next_runnable() );
00278             if (now_p == m_threads_push_tail) {
00279                 m_threads_push_tail = prior_p;
00280             }
00281             now_p->set_next_runnable(0);
00282             break;
00283         }
00284         prior_p = now_p;
00285     }
00286 }
00287 
00288 //------------------------------------------------------------------------------
00289 //"sc_runnable::sc_runnable"
00290 //
00291 // This is the object instance constructor for this class.
00292 //------------------------------------------------------------------------------
00293 inline sc_runnable::sc_runnable() 
00294 {
00295     m_methods_pop = 0;
00296     m_methods_push_head = 0;
00297     m_methods_push_tail = 0;
00298     m_threads_pop = 0;
00299     m_threads_push_head = 0;
00300     m_threads_push_tail = 0;
00301 }
00302 
00303 
00304 //------------------------------------------------------------------------------
00305 //"sc_runnable::~sc_runnable"
00306 //
00307 // This is the object instance destructor for this class.
00308 //------------------------------------------------------------------------------
00309 inline sc_runnable::~sc_runnable()
00310 {
00311     delete m_methods_push_head;
00312     delete m_threads_push_head;
00313 }
00314 
00315 
00316 //------------------------------------------------------------------------------
00317 //"sc_runnable::toggle"
00318 //
00319 // This method moves the push queue to the pop queue and zeros the push
00320 // queue.
00321 //------------------------------------------------------------------------------
00322 inline void sc_runnable::toggle()
00323 {
00324     m_methods_pop = m_methods_push_head->next_runnable();
00325     m_methods_push_head->set_next_runnable(SC_NO_METHODS);
00326     m_methods_push_tail = m_methods_push_head;
00327     m_threads_pop = m_threads_push_head->next_runnable();
00328     m_threads_push_head->set_next_runnable(SC_NO_THREADS);
00329     m_threads_push_tail = m_threads_push_head;
00330 }
00331 
00332 #undef SC_NO_METHODS
00333 #undef SC_NO_THREADS
00334 
00335 } // namespace sc_core
00336 
00337 #endif // SC_RUNNABLE_INT_H
00338 
00339 // Taf!

Generated on Wed Apr 25 13:53:27 2007 for SystemC by  doxygen 1.5.1