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-2006 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 // $Log: sc_runnable_int.h,v $
00039 // Revision 1.1.1.1  2006/12/15 20:31:37  acg
00040 // SystemC 2.2
00041 //
00042 // Revision 1.4  2006/04/20 17:08:17  acg
00043 //  Andy Goodrich: Changed loop end checks to use non-zero unique values
00044 //                 rather than erroneous check for zero values.
00045 //
00046 // Revision 1.3  2006/01/13 18:44:30  acg
00047 // Added $Log to record CVS changes into the source.
00048 //
00049 
00050 #ifndef SC_RUNNABLE_INT_H
00051 #define SC_RUNNABLE_INT_H
00052 
00053 
00054 #include "sysc/kernel/sc_runnable.h"
00055 #include "sysc/kernel/sc_method_process.h"
00056 #include "sysc/kernel/sc_thread_process.h"
00057 
00058 namespace sc_core {
00059 
00060 // The values below are used to indicate when a queue is empty. A non-zero     
00061 // non-legal pointer value is used for this so that a zero value in the
00062 // m_execute_p field of an sc_process_b instance can be used to indicate      
00063 // that is has not been queued for run. (If we did not use a non-zero
00064 // queue empty indicator then a sc_process_b instance that was queued
00065 // twice in a row might end up on the queue twice if it were the first
00066 // one that was queued!)
00067 
00068 #define SC_NO_METHODS ((sc_method_handle)0xdb)
00069 #define SC_NO_THREADS ((sc_thread_handle)0xdb)
00070 
00071 
00072 //------------------------------------------------------------------------------
00073 //"sc_runnable::init"
00074 //
00075 // This method initializes this object instance. Note we allocate the queue
00076 // heads if necessary. This is done here rather than in the constructor for
00077 // this class to eliminate CTOR processing errors with gcc.
00078 //------------------------------------------------------------------------------
00079 inline void sc_runnable::init()
00080 {
00081     m_methods_pop = SC_NO_METHODS;
00082     if ( !m_methods_push_head )
00083     {
00084         m_methods_push_head = 
00085             new sc_method_process((const char*)0, true, (SC_ENTRY_FUNC)0, 0, 0);
00086         m_methods_push_head->dont_initialize(true);
00087     }
00088     m_methods_push_tail = m_methods_push_head;
00089     m_methods_push_head->set_next_runnable(SC_NO_METHODS);
00090 
00091     m_threads_pop = SC_NO_THREADS;
00092     if ( !m_threads_push_head )
00093     {
00094         m_threads_push_head = 
00095             new sc_thread_process((const char*)0, true, (SC_ENTRY_FUNC)0, 0, 0);
00096         m_threads_push_head->dont_initialize(true);
00097     }
00098     m_threads_push_head->set_next_runnable(SC_NO_THREADS);
00099     m_threads_push_tail = m_threads_push_head;
00100 }
00101 
00102 
00103 //------------------------------------------------------------------------------
00104 //"sc_runnable::is_empty"
00105 //
00106 // This method returns true if the push queue is empty, or false if not.
00107 //------------------------------------------------------------------------------
00108 inline bool sc_runnable::is_empty() const
00109 {
00110     return m_methods_push_head->next_runnable() == SC_NO_METHODS && 
00111         m_threads_push_head->next_runnable() == SC_NO_THREADS;
00112 }
00113 
00114 
00115 //------------------------------------------------------------------------------
00116 //"sc_runnable::push_back_method"
00117 //
00118 // This method pushes the supplied method process onto the back of the queue of 
00119 // runnable method processes.
00120 //     method_h -> method process to add to the queue.
00121 //------------------------------------------------------------------------------
00122 inline void sc_runnable::push_back_method( sc_method_handle method_h )
00123 {
00124     // assert( method_h->next_runnable() == 0 ); // Can't queue twice.
00125     method_h->set_next_runnable(SC_NO_METHODS);
00126     m_methods_push_tail->set_next_runnable(method_h);
00127     m_methods_push_tail = method_h;
00128 }
00129 
00130 
00131 //------------------------------------------------------------------------------
00132 //"sc_runnable::push_back_thread"
00133 //
00134 // This method pushes the supplied thread process onto the back of the queue of 
00135 // runnable thread processes.
00136 //     thread_h -> thread process to add to the queue.
00137 //------------------------------------------------------------------------------
00138 inline void sc_runnable::push_back_thread( sc_thread_handle thread_h )
00139 {
00140     // assert( thread_h->next_runnable() == 0 ); // Can't queue twice.
00141     thread_h->set_next_runnable(SC_NO_THREADS);
00142     m_threads_push_tail->set_next_runnable(thread_h);
00143     m_threads_push_tail = thread_h;
00144 }
00145 
00146 
00147 //------------------------------------------------------------------------------
00148 //"sc_runnable::push_front_method"
00149 //
00150 // This method pushes the supplied method process onto the front of the queue of
00151 // runnable method processes. If the queue is empty the process is the tail 
00152 // also.
00153 //     method_h -> method process to add to the queue.
00154 //------------------------------------------------------------------------------
00155 inline void sc_runnable::push_front_method( sc_method_handle method_h )
00156 {
00157     // assert( method_h->next_runnable() == 0 ); // Can't queue twice.
00158     method_h->set_next_runnable(m_methods_push_head->next_runnable());
00159     if ( m_methods_push_tail == m_methods_push_head ) // Empty queue.
00160     {
00161         m_methods_push_tail->set_next_runnable(method_h);
00162     m_methods_push_tail = method_h;
00163     }
00164     else                                               // Non-empty queue.
00165     {
00166     m_methods_push_head->set_next_runnable(method_h);
00167     }
00168 }
00169 
00170 
00171 //------------------------------------------------------------------------------
00172 //"sc_runnable::push_front_thread"
00173 //
00174 // This method pushes the supplied thread process onto the front of the queue of
00175 // runnable thread processes. If the queue is empty the process is the tail 
00176 // also.
00177 //     thread_h -> thread process to add to the queue.
00178 //------------------------------------------------------------------------------
00179 inline void sc_runnable::push_front_thread( sc_thread_handle thread_h )
00180 {
00181     // assert( thread_h->next_runnable() == 0 ); // Can't queue twice.
00182     thread_h->set_next_runnable(m_threads_push_head->next_runnable());
00183     if ( m_threads_push_tail == m_threads_push_head ) // Empty queue.
00184     {
00185         m_threads_push_tail->set_next_runnable(thread_h);
00186     m_threads_push_tail = thread_h;
00187     }
00188     else                                               // Non-empty queue.
00189     {
00190     m_threads_push_head->set_next_runnable(thread_h);
00191     }
00192 }
00193 
00194 
00195 //------------------------------------------------------------------------------
00196 //"sc_runnable::pop_method"
00197 //
00198 // This method pops the next method process to be executed, or returns a null 
00199 // if no method processes are available for execution.
00200 //------------------------------------------------------------------------------
00201 inline sc_method_handle sc_runnable::pop_method()
00202 {
00203     sc_method_handle result_p;
00204 
00205     result_p = m_methods_pop;
00206     if ( result_p != SC_NO_METHODS ) 
00207     {
00208         m_methods_pop = result_p->next_runnable();
00209         result_p->set_next_runnable(0);
00210     }
00211     else
00212     {
00213         result_p = 0;
00214     }
00215     return result_p;
00216 
00217 }
00218 
00219 //------------------------------------------------------------------------------
00220 //"sc_runnable::pop_thread"
00221 //
00222 // This method pops the next thread process to be executed, or returns a null 
00223 // if no thread processes are available for execution.
00224 //------------------------------------------------------------------------------
00225 inline sc_thread_handle sc_runnable::pop_thread()
00226 {
00227     sc_thread_handle result_p;
00228 
00229     result_p = m_threads_pop;
00230     if ( result_p != SC_NO_THREADS ) 
00231     {
00232         m_threads_pop = result_p->next_runnable();
00233         result_p->set_next_runnable(0);
00234     }
00235     else
00236     {
00237         result_p = 0;
00238     }
00239     return result_p;
00240 }
00241 
00242 
00243 //------------------------------------------------------------------------------
00244 //"sc_runnable::remove_method"
00245 //
00246 // This method removes the supplied method process from the push queue if it is
00247 // present. Note we clear the method's next pointer so that it may be queued 
00248 // again.
00249 //     remove_p -> method process to remove from the run queue.
00250 //------------------------------------------------------------------------------
00251 inline void sc_runnable::remove_method( sc_method_handle remove_p )
00252 {
00253     sc_method_handle now_p;     // Method now checking.
00254     sc_method_handle prior_p;   // Method prior to now_p.
00255 
00256     prior_p = m_methods_push_head;
00257     for ( now_p = m_methods_push_head; now_p!= SC_NO_METHODS; 
00258         now_p = now_p->next_runnable() )
00259     {
00260         if ( remove_p == now_p )
00261         {
00262             prior_p->set_next_runnable( now_p->next_runnable() );
00263             if (now_p == m_methods_push_tail) {
00264                 m_methods_push_tail = prior_p;
00265             }
00266             now_p->set_next_runnable(0);
00267             break;
00268         }
00269         prior_p = now_p;
00270     }
00271 }
00272 
00273 
00274 //------------------------------------------------------------------------------
00275 //"sc_runnable::remove_thread"
00276 //
00277 // This method removes the supplied thread process from the push queue if it is
00278 // present. Note we clear the thread's next pointer so that it may be queued 
00279 // again.
00280 //     remove_p -> thread process to remove from the run queue.
00281 //------------------------------------------------------------------------------
00282 inline void sc_runnable::remove_thread( sc_thread_handle remove_p )
00283 {
00284     sc_thread_handle now_p;     // Thread now checking.
00285     sc_thread_handle prior_p;   // Thread prior to now_p.
00286 
00287     prior_p = m_threads_push_head;
00288     for ( now_p = m_threads_push_head; now_p != SC_NO_THREADS; 
00289         now_p = now_p->next_runnable() )
00290     {
00291         if ( remove_p == now_p )
00292         {
00293             prior_p->set_next_runnable( now_p->next_runnable() );
00294             if (now_p == m_threads_push_tail) {
00295                 m_threads_push_tail = prior_p;
00296             }
00297             now_p->set_next_runnable(0);
00298             break;
00299         }
00300         prior_p = now_p;
00301     }
00302 }
00303 
00304 //------------------------------------------------------------------------------
00305 //"sc_runnable::sc_runnable"
00306 //
00307 // This is the object instance constructor for this class.
00308 //------------------------------------------------------------------------------
00309 inline sc_runnable::sc_runnable() 
00310 {
00311     m_methods_pop = 0;
00312     m_methods_push_head = 0;
00313     m_methods_push_tail = 0;
00314     m_threads_pop = 0;
00315     m_threads_push_head = 0;
00316     m_threads_push_tail = 0;
00317 }
00318 
00319 
00320 //------------------------------------------------------------------------------
00321 //"sc_runnable::~sc_runnable"
00322 //
00323 // This is the object instance destructor for this class.
00324 //------------------------------------------------------------------------------
00325 inline sc_runnable::~sc_runnable()
00326 {
00327     delete m_methods_push_head;
00328     delete m_threads_push_head;
00329 }
00330 
00331 
00332 //------------------------------------------------------------------------------
00333 //"sc_runnable::toggle"
00334 //
00335 // This method moves the push queue to the pop queue and zeros the push
00336 // queue.
00337 //------------------------------------------------------------------------------
00338 inline void sc_runnable::toggle()
00339 {
00340     m_methods_pop = m_methods_push_head->next_runnable();
00341     m_methods_push_head->set_next_runnable(SC_NO_METHODS);
00342     m_methods_push_tail = m_methods_push_head;
00343     m_threads_pop = m_threads_push_head->next_runnable();
00344     m_threads_push_head->set_next_runnable(SC_NO_THREADS);
00345     m_threads_push_tail = m_threads_push_head;
00346 }
00347 
00348 #undef SC_NO_METHODS
00349 #undef SC_NO_THREADS
00350 
00351 } // namespace sc_core
00352 
00353 #endif // SC_RUNNABLE_INT_H
00354 
00355 // Taf!

Generated on Wed Jan 21 15:32:09 2009 for SystemC by  doxygen 1.5.5