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