Panda3D
|
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 }