Panda3D

pipelineCyclerTrueImpl.I

00001 // Filename: pipelineCyclerTrueImpl.I
00002 // Created by:  drose (31Jan06)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) Carnegie Mellon University.  All rights reserved.
00008 //
00009 // All use of this software is subject to the terms of the revised BSD
00010 // license.  You should have received a copy of this license along
00011 // with this source code in a file named "LICENSE."
00012 //
00013 ////////////////////////////////////////////////////////////////////
00014 
00015 
00016 ////////////////////////////////////////////////////////////////////
00017 //     Function: PipelineCyclerTrueImpl::acquire
00018 //       Access: Public
00019 //  Description: Grabs an overall lock on the cycler.  Release it with
00020 //               a call to release().  This lock should be held while
00021 //               walking the list of stages.
00022 ////////////////////////////////////////////////////////////////////
00023 INLINE void PipelineCyclerTrueImpl::
00024 acquire() {
00025   TAU_PROFILE("void PipelineCyclerTrueImpl::acquire()", " ", TAU_USER);
00026   _lock.acquire();
00027 }
00028 
00029 ////////////////////////////////////////////////////////////////////
00030 //     Function: PipelineCyclerTrueImpl::acquire
00031 //       Access: Public
00032 //  Description: Grabs an overall lock on the cycler.  Release it with
00033 //               a call to release().  This lock should be held while
00034 //               walking the list of stages.
00035 ////////////////////////////////////////////////////////////////////
00036 INLINE void PipelineCyclerTrueImpl::
00037 acquire(Thread *current_thread) {
00038   TAU_PROFILE("void PipelineCyclerTrueImpl::acquire(Thread *)", " ", TAU_USER);
00039   _lock.acquire(current_thread);
00040 }
00041 
00042 ////////////////////////////////////////////////////////////////////
00043 //     Function: PipelineCyclerTrueImpl::release
00044 //       Access: Public
00045 //  Description: Release the overall lock on the cycler that was
00046 //               grabbed via acquire().
00047 ////////////////////////////////////////////////////////////////////
00048 INLINE void PipelineCyclerTrueImpl::
00049 release() {
00050   TAU_PROFILE("void PipelineCyclerTrueImpl::release()", " ", TAU_USER);
00051   _lock.release();
00052 }
00053 
00054 ////////////////////////////////////////////////////////////////////
00055 //     Function: PipelineCyclerTrueImpl::read_unlocked
00056 //       Access: Public
00057 //  Description: Returns a const CycleData pointer, filled with the
00058 //               data for the current stage of the pipeline as seen by
00059 //               this thread.  No lock is made on the contents; there
00060 //               is no guarantee that some other thread won't modify
00061 //               this object's data while you are working on it.
00062 //               (However, the data within the returned CycleData
00063 //               object itself is safe from modification; if another
00064 //               thread modifies the data, it will perform a
00065 //               copy-on-write, and thereby change the pointer stored
00066 //               within the object.)
00067 ////////////////////////////////////////////////////////////////////
00068 INLINE const CycleData *PipelineCyclerTrueImpl::
00069 read_unlocked(Thread *current_thread) const {
00070   TAU_PROFILE("const CycleData *PipelineCyclerTrueImpl::read_unlocked(Thread *)", " ", TAU_USER);
00071   int pipeline_stage = current_thread->get_pipeline_stage();
00072 #ifdef _DEBUG
00073   nassertr(pipeline_stage >= 0 && pipeline_stage < _num_stages, NULL);
00074 #endif
00075   return _data[pipeline_stage];
00076 }
00077 
00078 ////////////////////////////////////////////////////////////////////
00079 //     Function: PipelineCyclerTrueImpl::read
00080 //       Access: Public
00081 //  Description: Returns a const CycleData pointer, filled with the
00082 //               data for the current stage of the pipeline as seen by
00083 //               this thread.  This pointer should eventually be
00084 //               released by calling release_read().
00085 //
00086 //               There should be no outstanding write pointers on the
00087 //               data when this function is called.
00088 ////////////////////////////////////////////////////////////////////
00089 INLINE const CycleData *PipelineCyclerTrueImpl::
00090 read(Thread *current_thread) const {
00091   TAU_PROFILE("const CycleData *PipelineCyclerTrueImpl::read(Thread *)", " ", TAU_USER);
00092   int pipeline_stage = current_thread->get_pipeline_stage();
00093 #ifdef _DEBUG
00094   nassertr(pipeline_stage >= 0 && pipeline_stage < _num_stages, NULL);
00095 #endif
00096   _lock.acquire(current_thread);
00097   return _data[pipeline_stage];
00098 }
00099 
00100 ////////////////////////////////////////////////////////////////////
00101 //     Function: PipelineCyclerTrueImpl::increment_read
00102 //       Access: Public
00103 //  Description: Increments the count on a pointer previously
00104 //               retrieved by read(); now the pointer will need to be
00105 //               released twice.
00106 ////////////////////////////////////////////////////////////////////
00107 INLINE void PipelineCyclerTrueImpl::
00108 increment_read(const CycleData *pointer) const {
00109   TAU_PROFILE("void PipelineCyclerTrueImpl::increment_read(const CycleData *)", " ", TAU_USER);
00110 #ifdef _DEBUG
00111   int pipeline_stage = Thread::get_current_pipeline_stage();
00112   nassertv(pipeline_stage >= 0 && pipeline_stage < _num_stages);
00113   nassertv(_data[pipeline_stage] == pointer);
00114 #endif
00115   _lock.elevate_lock();
00116 }
00117 
00118 ////////////////////////////////////////////////////////////////////
00119 //     Function: PipelineCyclerTrueImpl::release_read
00120 //       Access: Public
00121 //  Description: Releases a pointer previously obtained via a call to
00122 //               read().
00123 ////////////////////////////////////////////////////////////////////
00124 INLINE void PipelineCyclerTrueImpl::
00125 release_read(const CycleData *pointer) const {
00126   TAU_PROFILE("void PipelineCyclerTrueImpl::release_read(const CycleData *)", " ", TAU_USER);
00127 #ifdef _DEBUG
00128   int pipeline_stage = Thread::get_current_pipeline_stage();
00129   nassertv(pipeline_stage >= 0 && pipeline_stage < _num_stages);
00130   nassertv(_data[pipeline_stage] == pointer);
00131 #endif
00132   _lock.release();
00133 }
00134 
00135 ////////////////////////////////////////////////////////////////////
00136 //     Function: PipelineCyclerTrueImpl::write
00137 //       Access: Public
00138 //  Description: Returns a non-const CycleData pointer, filled with a
00139 //               unique copy of the data for the current stage of the
00140 //               pipeline as seen by this thread.  This pointer may
00141 //               now be used to write to the data, and that copy of
00142 //               the data will be propagated to all later stages of the
00143 //               pipeline.  This pointer should eventually be released
00144 //               by calling release_write().
00145 //
00146 //               There may only be one outstanding write pointer on a
00147 //               given stage at a time, and if there is a write
00148 //               pointer there may be no read pointers on the same
00149 //               stage (but see elevate_read).
00150 ////////////////////////////////////////////////////////////////////
00151 INLINE CycleData *PipelineCyclerTrueImpl::
00152 write(Thread *current_thread) {
00153   TAU_PROFILE("CycleData *PipelineCyclerTrueImpl::write(Thread *)", " ", TAU_USER);
00154   return write_stage(current_thread->get_pipeline_stage(), current_thread);
00155 }
00156 
00157 ////////////////////////////////////////////////////////////////////
00158 //     Function: PipelineCyclerTrueImpl::write_upstream
00159 //       Access: Public
00160 //  Description: This special variant on write() will automatically
00161 //               propagate changes back to upstream pipeline stages.
00162 //               If force_to_0 is false, then it propagates back only
00163 //               as long as the CycleData pointers are equivalent,
00164 //               guaranteeing that it does not modify upstream data
00165 //               (other than the modification that will be performed
00166 //               by the code that returns this pointer).  This is
00167 //               particularly appropriate for minor updates, where it
00168 //               doesn't matter much if the update is lost, such as
00169 //               storing a cached value.
00170 //
00171 //               If force_to_0 is true, then the CycleData pointer for
00172 //               the current pipeline stage is propagated all the way
00173 //               back up to stage 0; after this call, there will be
00174 //               only one CycleData pointer that is duplicated in all
00175 //               stages between stage 0 and the current stage.  This
00176 //               may undo some recent changes that were made
00177 //               independently at pipeline stage 0 (or any other
00178 //               upstream stage).  However, it guarantees that the
00179 //               change that is to be applied at this pipeline stage
00180 //               will stick.  This is slightly dangerous because of
00181 //               the risk of losing upstream changes; generally, this
00182 //               should only be done when you are confident that there
00183 //               are no upstream changes to be lost (for instance, for
00184 //               an object that has been recently created).
00185 ////////////////////////////////////////////////////////////////////
00186 INLINE CycleData *PipelineCyclerTrueImpl::
00187 write_upstream(bool force_to_0, Thread *current_thread) {
00188   TAU_PROFILE("CycleData *PipelineCyclerTrueImpl::write_upstream(bool, Thread *)", " ", TAU_USER);
00189   return write_stage_upstream(current_thread->get_pipeline_stage(), force_to_0,
00190                               current_thread);
00191 }
00192 
00193 ////////////////////////////////////////////////////////////////////
00194 //     Function: PipelineCyclerTrueImpl::elevate_read
00195 //       Access: Public
00196 //  Description: Elevates a currently-held read pointer into a write
00197 //               pointer.  This may or may not change the value of the
00198 //               pointer.  It is only valid to do this if this is the
00199 //               only currently-outstanding read pointer on the
00200 //               current stage.
00201 ////////////////////////////////////////////////////////////////////
00202 INLINE CycleData *PipelineCyclerTrueImpl::
00203 elevate_read(const CycleData *pointer, Thread *current_thread) {
00204   TAU_PROFILE("CycleData *PipelineCyclerTrueImpl::elevate_read(const CycleData *)", " ", TAU_USER);
00205 #ifdef _DEBUG
00206   int pipeline_stage = current_thread->get_pipeline_stage();
00207   nassertr(pipeline_stage >= 0 && pipeline_stage < _num_stages, NULL);
00208   nassertr(_data[pipeline_stage] == pointer, NULL);
00209 #endif
00210   CycleData *new_pointer = write(current_thread);
00211   _lock.release();
00212   return new_pointer;
00213 }
00214 
00215 ////////////////////////////////////////////////////////////////////
00216 //     Function: PipelineCyclerTrueImpl::elevate_read_upstream
00217 //       Access: Public
00218 //  Description: Elevates a currently-held read pointer into a write
00219 //               pointer, like elevate_read(), but also propagates the
00220 //               pointer back to upstream stages, like
00221 //               write_upstream().
00222 ////////////////////////////////////////////////////////////////////
00223 INLINE CycleData *PipelineCyclerTrueImpl::
00224 elevate_read_upstream(const CycleData *pointer, bool force_to_0, Thread *current_thread) {
00225   TAU_PROFILE("CycleData *PipelineCyclerTrueImpl::elevate_read_upstream(const CycleData *, bool)", " ", TAU_USER);
00226 #ifdef _DEBUG
00227   int pipeline_stage = current_thread->get_pipeline_stage();
00228   nassertr(pipeline_stage >= 0 && pipeline_stage < _num_stages, NULL);
00229   nassertr(_data[pipeline_stage] == pointer, NULL);
00230 #endif
00231   CycleData *new_pointer = write_upstream(force_to_0, current_thread);
00232   _lock.release();
00233   return new_pointer;
00234 }
00235 
00236 ////////////////////////////////////////////////////////////////////
00237 //     Function: PipelineCyclerTrueImpl::increment_write
00238 //       Access: Public
00239 //  Description: Increments the count on a pointer previously
00240 //               retrieved by write(); now the pointer will need to be
00241 //               released twice.
00242 ////////////////////////////////////////////////////////////////////
00243 INLINE void PipelineCyclerTrueImpl::
00244 increment_write(CycleData *pointer) const {
00245   TAU_PROFILE("void PipelineCyclerTrueImpl::increment_write(CycleData *)", " ", TAU_USER);
00246 #ifdef _DEBUG
00247   int pipeline_stage = Thread::get_current_pipeline_stage();
00248   nassertv(pipeline_stage >= 0 && pipeline_stage < _num_stages);
00249   nassertv(_data[pipeline_stage] == pointer);
00250 #endif
00251   _lock.elevate_lock();
00252 }
00253 
00254 ////////////////////////////////////////////////////////////////////
00255 //     Function: PipelineCyclerTrueImpl::release_write
00256 //       Access: Public
00257 //  Description: Releases a pointer previously obtained via a call to
00258 //               write().
00259 ////////////////////////////////////////////////////////////////////
00260 INLINE void PipelineCyclerTrueImpl::
00261 release_write(CycleData *pointer) {
00262   TAU_PROFILE("void PipelineCyclerTrueImpl::release_write(CycleData *)", " ", TAU_USER);
00263 #ifdef _DEBUG
00264   int pipeline_stage = Thread::get_current_pipeline_stage();
00265   return release_write_stage(pipeline_stage, pointer);
00266 #else
00267   _lock.release();
00268 #endif
00269 }
00270 
00271 ////////////////////////////////////////////////////////////////////
00272 //     Function: PipelineCyclerTrueImpl::get_num_stages
00273 //       Access: Public
00274 //  Description: Returns the number of stages in the pipeline.
00275 ////////////////////////////////////////////////////////////////////
00276 INLINE int PipelineCyclerTrueImpl::
00277 get_num_stages() {
00278   return _num_stages;
00279 }
00280 
00281 ////////////////////////////////////////////////////////////////////
00282 //     Function: PipelineCyclerTrueImpl::read_stage_unlocked
00283 //       Access: Public
00284 //  Description: Returns a const CycleData pointer, filled with the
00285 //               data for the indicated stage of the pipeline.  As in
00286 //               read_unlocked(), no lock is held on the returned
00287 //               pointer.
00288 ////////////////////////////////////////////////////////////////////
00289 INLINE const CycleData *PipelineCyclerTrueImpl::
00290 read_stage_unlocked(int pipeline_stage) const {
00291   TAU_PROFILE("const CycleData *PipelineCyclerTrueImpl::read_stage_unlocked(int)", " ", TAU_USER);
00292 #ifdef _DEBUG
00293   nassertr(pipeline_stage >= 0 && pipeline_stage < _num_stages, NULL);
00294 #endif
00295   return _data[pipeline_stage];
00296 }
00297 
00298 ////////////////////////////////////////////////////////////////////
00299 //     Function: PipelineCyclerTrueImpl::read_stage
00300 //       Access: Public
00301 //  Description: Returns a const CycleData pointer, filled with the
00302 //               data for the indicated stage of the pipeline.  This
00303 //               pointer should eventually be released by calling
00304 //               release_read_stage().
00305 //
00306 //               There should be no outstanding write pointers on the
00307 //               data when this function is called.
00308 ////////////////////////////////////////////////////////////////////
00309 INLINE const CycleData *PipelineCyclerTrueImpl::
00310 read_stage(int pipeline_stage, Thread *current_thread) const {
00311   TAU_PROFILE("const CycleData *PipelineCyclerTrueImpl::read_stage(int, Thread *)", " ", TAU_USER);
00312 #ifdef _DEBUG
00313   nassertr(pipeline_stage >= 0 && pipeline_stage < _num_stages, NULL);
00314 #endif
00315   _lock.acquire(current_thread);
00316   return _data[pipeline_stage];
00317 }
00318 
00319 ////////////////////////////////////////////////////////////////////
00320 //     Function: PipelineCyclerTrueImpl::release_read_stage
00321 //       Access: Public
00322 //  Description: Releases a pointer previously obtained via a call to
00323 //               read_stage().
00324 ////////////////////////////////////////////////////////////////////
00325 INLINE void PipelineCyclerTrueImpl::
00326 release_read_stage(int pipeline_stage, const CycleData *pointer) const {
00327   TAU_PROFILE("void PipelineCyclerTrueImpl::release_read_stage(int, const CycleData *)", " ", TAU_USER);
00328 #ifdef _DEBUG
00329   nassertv(pipeline_stage >= 0 && pipeline_stage < _num_stages);
00330   nassertv(_data[pipeline_stage] == pointer);
00331 #endif
00332   _lock.release();
00333 }
00334 
00335 ////////////////////////////////////////////////////////////////////
00336 //     Function: PipelineCyclerTrueImpl::elevate_read_stage
00337 //       Access: Public
00338 //  Description: Elevates a currently-held read pointer into a write
00339 //               pointer.  This may or may not change the value of the
00340 //               pointer.  It is only valid to do this if this is the
00341 //               only currently-outstanding read pointer on the
00342 //               indicated stage.
00343 ////////////////////////////////////////////////////////////////////
00344 INLINE CycleData *PipelineCyclerTrueImpl::
00345 elevate_read_stage(int pipeline_stage, const CycleData *pointer,
00346                    Thread *current_thread) {
00347   TAU_PROFILE("CycleData *PipelineCyclerTrueImpl::elevate_read_stage(int, const CycleData *)", " ", TAU_USER);
00348 #ifdef _DEBUG
00349   nassertr(pipeline_stage >= 0 && pipeline_stage < _num_stages, NULL);
00350   nassertr(_data[pipeline_stage] == pointer, NULL);
00351 #endif
00352   CycleData *new_pointer = write_stage(pipeline_stage, current_thread);
00353   _lock.release();
00354   return new_pointer;
00355 }
00356 
00357 ////////////////////////////////////////////////////////////////////
00358 //     Function: PipelineCyclerTrueImpl::elevate_read_stage_upstream
00359 //       Access: Public
00360 //  Description: Elevates a currently-held read pointer into a write
00361 //               pointer.  This may or may not change the value of the
00362 //               pointer.  It is only valid to do this if this is the
00363 //               only currently-outstanding read pointer on the
00364 //               indicated stage.
00365 ////////////////////////////////////////////////////////////////////
00366 INLINE CycleData *PipelineCyclerTrueImpl::
00367 elevate_read_stage_upstream(int pipeline_stage, const CycleData *pointer, 
00368                             bool force_to_0, Thread *current_thread) {
00369   TAU_PROFILE("CycleData *PipelineCyclerTrueImpl::elevate_read_stage(int, const CycleData *)", " ", TAU_USER);
00370 #ifdef _DEBUG
00371   nassertr(pipeline_stage >= 0 && pipeline_stage < _num_stages, NULL);
00372   nassertr(_data[pipeline_stage] == pointer, NULL);
00373 #endif
00374   CycleData *new_pointer = 
00375     write_stage_upstream(pipeline_stage, force_to_0, current_thread);
00376   _lock.release();
00377   return new_pointer;
00378 }
00379 
00380 ////////////////////////////////////////////////////////////////////
00381 //     Function: PipelineCyclerTrueImpl::release_write_stage
00382 //       Access: Public
00383 //  Description: Releases a pointer previously obtained via a call to
00384 //               write_stage().
00385 ////////////////////////////////////////////////////////////////////
00386 INLINE void PipelineCyclerTrueImpl::
00387 release_write_stage(int pipeline_stage, CycleData *pointer) {
00388   TAU_PROFILE("void PipelineCyclerTrueImpl::release_write_stage(int, const CycleData *)", " ", TAU_USER);
00389 #ifdef _DEBUG
00390   nassertv(pipeline_stage >= 0 && pipeline_stage < _num_stages);
00391   nassertv(_data[pipeline_stage] == pointer);
00392 #endif
00393   _lock.release();
00394 }
00395 
00396 ////////////////////////////////////////////////////////////////////
00397 //     Function: PipelineCyclerTrueImpl::get_parent_type
00398 //       Access: Public
00399 //  Description: Returns the type of object that owns this cycler, as
00400 //               reported by CycleData::get_parent_type().
00401 ////////////////////////////////////////////////////////////////////
00402 INLINE TypeHandle PipelineCyclerTrueImpl::
00403 get_parent_type() const {
00404   return _data[0]->get_parent_type();
00405 }
00406 
00407 ////////////////////////////////////////////////////////////////////
00408 //     Function: PipelineCyclerTrueImpl::cheat
00409 //       Access: Public
00410 //  Description: Returns a pointer without counting it.  This is only
00411 //               intended for use as the return value for certain
00412 //               nassertr() functions, so the application can recover
00413 //               after a failure to manage the read and write pointers
00414 //               correctly.  You should never call this function
00415 //               directly.
00416 ////////////////////////////////////////////////////////////////////
00417 INLINE CycleData *PipelineCyclerTrueImpl::
00418 cheat() const {
00419   TAU_PROFILE("CycleData *PipelineCyclerTrueImpl::cheat()", " ", TAU_USER);
00420   int pipeline_stage = Thread::get_current_pipeline_stage();
00421   nassertr(pipeline_stage >= 0 && pipeline_stage < _num_stages, NULL);
00422   return _data[pipeline_stage];
00423 }
00424 
00425 ////////////////////////////////////////////////////////////////////
00426 //     Function: PipelineCyclerTrueImpl::get_read_count
00427 //       Access: Public
00428 //  Description: Returns the number of handles currently outstanding
00429 //               to read the current stage of the data.  This should
00430 //               only be used for debugging purposes.
00431 ////////////////////////////////////////////////////////////////////
00432 INLINE int PipelineCyclerTrueImpl::
00433 get_read_count() const {
00434   return 0;
00435 }
00436 
00437 ////////////////////////////////////////////////////////////////////
00438 //     Function: PipelineCyclerTrueImpl::get_write_count
00439 //       Access: Public
00440 //  Description: Returns the number of handles currently outstanding
00441 //               to read the current stage of the data.  This will
00442 //               normally only be either 0 or 1.  This should only be
00443 //               used for debugging purposes.
00444 ////////////////////////////////////////////////////////////////////
00445 INLINE int PipelineCyclerTrueImpl::
00446 get_write_count() const {
00447   return 0;
00448 }
00449 
00450 ////////////////////////////////////////////////////////////////////
00451 //     Function: PipelineCyclerTrueImpl::cycle_2
00452 //       Access: Private
00453 //  Description: This is a special implementation of cycle() for the
00454 //               special case of just two stages to the pipeline.  It
00455 //               does the same thing as cycle(), but is a little bit
00456 //               faster because it knows there are exactly two stages.
00457 ////////////////////////////////////////////////////////////////////
00458 INLINE PT(CycleData) PipelineCyclerTrueImpl::
00459 cycle_2() {
00460   TAU_PROFILE("PT(CycleData) PipelineCyclerTrueImpl::cycle_2()", " ", TAU_USER);
00461   PT(CycleData) last_val = _data[1].p();
00462   nassertr(_lock.debug_is_locked(), last_val);
00463   nassertr(_dirty, last_val);
00464   nassertr(_num_stages == 2, last_val);
00465 
00466   _data[1] = _data[0];
00467 
00468   // No longer dirty.
00469   _dirty = false;
00470   return last_val;
00471 }
00472 
00473 ////////////////////////////////////////////////////////////////////
00474 //     Function: PipelineCyclerTrueImpl::cycle_3
00475 //       Access: Private
00476 //  Description: This is a special implementation of cycle() for the
00477 //               special case of exactly three stages to the pipeline.
00478 //               It does the same thing as cycle(), but is a little
00479 //               bit faster because it knows there are exactly three
00480 //               stages.
00481 ////////////////////////////////////////////////////////////////////
00482 INLINE PT(CycleData) PipelineCyclerTrueImpl::
00483 cycle_3() {
00484   TAU_PROFILE("PT(CycleData) PipelineCyclerTrueImpl::cycle_3()", " ", TAU_USER);
00485   PT(CycleData) last_val = _data[2].p();
00486   nassertr(_lock.debug_is_locked(), last_val);
00487   nassertr(_dirty, last_val);
00488   nassertr(_num_stages == 3, last_val);
00489 
00490   _data[2] = _data[1];
00491   _data[1] = _data[0];
00492 
00493   if (_data[2] == _data[1]) {
00494     // No longer dirty.
00495     _dirty = false;
00496   }
00497 
00498   return last_val;
00499 }
00500 
00501 ////////////////////////////////////////////////////////////////////
00502 //     Function: PipelineCyclerTrueImpl::CyclerMutex::Constructor
00503 //       Access: Public
00504 //  Description: 
00505 ////////////////////////////////////////////////////////////////////
00506 INLINE PipelineCyclerTrueImpl::CyclerMutex::
00507 CyclerMutex(PipelineCyclerTrueImpl *cycler) {
00508 #ifdef DEBUG_THREADS
00509   _cycler = cycler;
00510 #endif
00511 }
 All Classes Functions Variables Enumerations