00001 // Filename: pipelineCyclerBase.I 00002 // Created by: drose (21Feb02) 00003 // 00004 //////////////////////////////////////////////////////////////////// 00005 // 00006 // PANDA 3D SOFTWARE 00007 // Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved 00008 // 00009 // All use of this software is subject to the terms of the Panda 3d 00010 // Software license. You should have received a copy of this license 00011 // along with this source code; you will also find a current copy of 00012 // the license at http://www.panda3d.org/license.txt . 00013 // 00014 // To contact the maintainers of this program write to 00015 // panda3d@yahoogroups.com . 00016 // 00017 //////////////////////////////////////////////////////////////////// 00018 00019 00020 #ifdef DO_PIPELINING 00021 // The following implementations are to support compiled-in pipeline 00022 // sanity checks. 00023 00024 //////////////////////////////////////////////////////////////////// 00025 // Function: PipelineCyclerBase::Constructor (sanity-check) 00026 // Access: Public 00027 // Description: 00028 //////////////////////////////////////////////////////////////////// 00029 INLINE PipelineCyclerBase:: 00030 PipelineCyclerBase(CycleData *initial_data, Pipeline *pipeline) : 00031 _data(initial_data), 00032 _pipeline(pipeline), 00033 _read_count(0), 00034 _write_count(0) 00035 { 00036 if (_pipeline == (Pipeline *)NULL) { 00037 _pipeline = Pipeline::get_render_pipeline(); 00038 } 00039 } 00040 00041 //////////////////////////////////////////////////////////////////// 00042 // Function: PipelineCyclerBase::Copy Constructor (sanity-check) 00043 // Access: Public 00044 // Description: 00045 //////////////////////////////////////////////////////////////////// 00046 INLINE PipelineCyclerBase:: 00047 PipelineCyclerBase(CycleData *, const PipelineCyclerBase ©) : 00048 _data(copy._data->make_copy()), 00049 _pipeline(copy._pipeline), 00050 _read_count(0), 00051 _write_count(0) 00052 { 00053 } 00054 00055 //////////////////////////////////////////////////////////////////// 00056 // Function: PipelineCyclerBase::Copy Assignment (sanity-check) 00057 // Access: Public 00058 // Description: 00059 //////////////////////////////////////////////////////////////////// 00060 INLINE void PipelineCyclerBase:: 00061 operator = (const PipelineCyclerBase ©) { 00062 nassertv(_read_count == 0 && _write_count == 0); 00063 _data = copy._data->make_copy(); 00064 _pipeline = copy._pipeline; 00065 } 00066 00067 //////////////////////////////////////////////////////////////////// 00068 // Function: PipelineCyclerBase::Destructor (sanity-check) 00069 // Access: Public 00070 // Description: 00071 //////////////////////////////////////////////////////////////////// 00072 INLINE PipelineCyclerBase:: 00073 ~PipelineCyclerBase() { 00074 nassertv(_read_count == 0 && _write_count == 0); 00075 } 00076 00077 //////////////////////////////////////////////////////////////////// 00078 // Function: PipelineCyclerBase::read (sanity-check) 00079 // Access: Public 00080 // Description: Returns a const CycleData pointer, filled with the 00081 // data for the current stage of the pipeline as seen by 00082 // this thread. This pointer should eventually be 00083 // released by calling release_read(). 00084 // 00085 // There should be no outstanding write pointers on the 00086 // data when this function is called. 00087 //////////////////////////////////////////////////////////////////// 00088 INLINE const CycleData *PipelineCyclerBase:: 00089 read() const { 00090 // This function isn't truly const, but it doesn't change the data 00091 // in any meaningful way, so we pretend it is. 00092 ((PipelineCyclerBase *)this)->_read_count++; 00093 00094 // It's not an error to grab a read pointer while someone else holds 00095 // a read or a write pointer. 00096 return _data; 00097 } 00098 00099 //////////////////////////////////////////////////////////////////// 00100 // Function: PipelineCyclerBase::increment_read (sanity-check) 00101 // Access: Public 00102 // Description: Increments the count on a pointer previously 00103 // retrieved by read(); now the pointer will need to be 00104 // released twice. 00105 //////////////////////////////////////////////////////////////////// 00106 INLINE void PipelineCyclerBase:: 00107 increment_read(const CycleData *pointer) const { 00108 // This function isn't truly const, but it doesn't change the data 00109 // in any meaningful way, so we pretend it is. 00110 nassertv(pointer == _data); 00111 nassertv(_read_count > 0); 00112 ((PipelineCyclerBase *)this)->_read_count++; 00113 } 00114 00115 //////////////////////////////////////////////////////////////////// 00116 // Function: PipelineCyclerBase::release_read (sanity-check) 00117 // Access: Public 00118 // Description: Releases a pointer previously obtained via a call to 00119 // read(). 00120 //////////////////////////////////////////////////////////////////// 00121 INLINE void PipelineCyclerBase:: 00122 release_read(const CycleData *pointer) const { 00123 // This function isn't truly const, but it doesn't change the data 00124 // in any meaningful way, so we pretend it is. 00125 nassertv(pointer == _data); 00126 nassertv(_read_count > 0); 00127 ((PipelineCyclerBase *)this)->_read_count--; 00128 } 00129 00130 //////////////////////////////////////////////////////////////////// 00131 // Function: PipelineCyclerBase::write (sanity-check) 00132 // Access: Public 00133 // Description: Returns a non-const CycleData pointer, filled with a 00134 // unique copy of the data for the current stage of the 00135 // pipeline as seen by this thread. This pointer may 00136 // now be used to write to the data, and that copy of 00137 // the data will be propagate to all later stages of the 00138 // pipeline. This pointer should eventually be released 00139 // by calling release_write(). 00140 // 00141 // There may only be one outstanding write pointer on a 00142 // given stage at a time, and if there is a write 00143 // pointer there may be no read pointers on the same 00144 // stage (but see elevate_read). 00145 //////////////////////////////////////////////////////////////////// 00146 INLINE CycleData *PipelineCyclerBase:: 00147 write() { 00148 _write_count++; 00149 00150 // It's an error to grab a write pointer while someone else holds a 00151 // read pointer, because doing so may invalidate the read pointer. 00152 nassertr(_read_count == 0, _data); 00153 00154 // It's not an error to do this while someone else holds a write 00155 // pointer, however. 00156 00157 return _data; 00158 } 00159 00160 //////////////////////////////////////////////////////////////////// 00161 // Function: PipelineCyclerBase::elevate_read (sanity-check) 00162 // Access: Public 00163 // Description: Elevates a currently-held read pointer into a write 00164 // pointer. This may or may not change the value of the 00165 // pointer. It is only valid to do this if this is the 00166 // only currently-outstanding read pointer on the 00167 // current stage. 00168 //////////////////////////////////////////////////////////////////// 00169 INLINE CycleData *PipelineCyclerBase:: 00170 elevate_read(const CycleData *pointer) { 00171 release_read(pointer); 00172 return write(); 00173 } 00174 00175 //////////////////////////////////////////////////////////////////// 00176 // Function: PipelineCyclerBase::release_write (sanity-check) 00177 // Access: Public 00178 // Description: Releases a pointer previously obtained via a call to 00179 // write(). 00180 //////////////////////////////////////////////////////////////////// 00181 INLINE void PipelineCyclerBase:: 00182 release_write(CycleData *pointer) { 00183 nassertv(pointer == _data); 00184 nassertv(_write_count > 0); 00185 _write_count--; 00186 } 00187 00188 //////////////////////////////////////////////////////////////////// 00189 // Function: PipelineCyclerBase::get_num_stages (sanity-check) 00190 // Access: Public 00191 // Description: Returns the number of stages in the pipeline. 00192 //////////////////////////////////////////////////////////////////// 00193 INLINE int PipelineCyclerBase:: 00194 get_num_stages() { 00195 return 1; 00196 } 00197 00198 //////////////////////////////////////////////////////////////////// 00199 // Function: PipelineCyclerBase::is_stage_unique (sanity-check) 00200 // Access: Public 00201 // Description: Returns true if the nth stage is a different pointer 00202 // than the previous stage, or false if its pointer is 00203 // shared with the previous one. 00204 //////////////////////////////////////////////////////////////////// 00205 INLINE bool PipelineCyclerBase:: 00206 is_stage_unique(int n) const { 00207 nassertr(n == 0, false); 00208 return true; 00209 } 00210 00211 //////////////////////////////////////////////////////////////////// 00212 // Function: PipelineCyclerBase::write_stage (sanity-check) 00213 // Access: Public 00214 // Description: Returns a pointer suitable for writing to the nth 00215 // stage of the pipeline. This is for special 00216 // applications that need to update the entire pipeline 00217 // at once (for instance, to remove an invalid pointer). 00218 // This pointer should later be released with 00219 // release_write_stage(). 00220 //////////////////////////////////////////////////////////////////// 00221 INLINE CycleData *PipelineCyclerBase:: 00222 write_stage(int n) { 00223 nassertr(n == 0, (CycleData *)NULL); 00224 _write_count++; 00225 return _data; 00226 } 00227 00228 //////////////////////////////////////////////////////////////////// 00229 // Function: PipelineCyclerBase::release_write_stage (sanity-check) 00230 // Access: Public 00231 // Description: Releases a pointer previously obtained via a call to 00232 // write_stage(). 00233 //////////////////////////////////////////////////////////////////// 00234 INLINE void PipelineCyclerBase:: 00235 release_write_stage(int n, CycleData *pointer) { 00236 nassertv(n == 0 && pointer == _data); 00237 nassertv(_write_count > 0); 00238 _write_count--; 00239 } 00240 00241 //////////////////////////////////////////////////////////////////// 00242 // Function: PipelineCyclerBase::cheat (sanity-check) 00243 // Access: Public 00244 // Description: Returns a pointer without counting it. This is only 00245 // intended for use as the return value for certain 00246 // nassertr() functions, so the application can recover 00247 // after a failure to manage the read and write pointers 00248 // correctly. You should never call this function 00249 // directly. 00250 //////////////////////////////////////////////////////////////////// 00251 INLINE CycleData *PipelineCyclerBase:: 00252 cheat() const { 00253 return _data; 00254 } 00255 00256 //////////////////////////////////////////////////////////////////// 00257 // Function: PipelineCyclerBase::get_read_count (sanity-check) 00258 // Access: Public 00259 // Description: Returns the number of handles currently outstanding 00260 // to read the current stage of the data. This should 00261 // only be used for debugging purposes. 00262 //////////////////////////////////////////////////////////////////// 00263 INLINE int PipelineCyclerBase:: 00264 get_read_count() const { 00265 return _read_count; 00266 } 00267 00268 //////////////////////////////////////////////////////////////////// 00269 // Function: PipelineCyclerBase::get_write_count (sanity-check) 00270 // Access: Public 00271 // Description: Returns the number of handles currently outstanding 00272 // to read the current stage of the data. This will 00273 // normally only be either 0 or 1. This should only be 00274 // used for debugging purposes. 00275 //////////////////////////////////////////////////////////////////// 00276 INLINE int PipelineCyclerBase:: 00277 get_write_count() const { 00278 return _write_count; 00279 } 00280 00281 #else // !DO_PIPELINING 00282 // The following implementations are provided for when pipelining is 00283 // not compiled in. They are trivial functions that do as little as 00284 // possible. 00285 00286 //////////////////////////////////////////////////////////////////// 00287 // Function: PipelineCyclerBase::Constructor (trivial) 00288 // Access: Public 00289 // Description: 00290 //////////////////////////////////////////////////////////////////// 00291 INLINE PipelineCyclerBase:: 00292 PipelineCyclerBase(CycleData *initial_data, Pipeline *) { 00293 // In the trivial implementation, a derived class (the 00294 // PipelineCycler template class) stores the CycleData object 00295 // directly within itself, and since we have no data members or 00296 // virtual functions, we get away with assuming the pointer is the 00297 // same as the 'this' pointer. 00298 00299 // If this turns out not to be true on a particular platform, we 00300 // will have to store the pointer in this class, for a little bit of 00301 // extra overhead. 00302 #ifdef SIMPLE_STRUCT_POINTERS 00303 nassertv(initial_data == (CycleData *)this); 00304 #else 00305 _data = initial_data; 00306 #endif // SIMPLE_STRUCT_POINTERS 00307 } 00308 00309 //////////////////////////////////////////////////////////////////// 00310 // Function: PipelineCyclerBase::Copy Constructor (trivial) 00311 // Access: Public 00312 // Description: 00313 //////////////////////////////////////////////////////////////////// 00314 INLINE PipelineCyclerBase:: 00315 PipelineCyclerBase(CycleData *initial_data, const PipelineCyclerBase &) { 00316 // The copy constructor for the DO_PIPELINING case is 00317 #ifdef SIMPLE_STRUCT_POINTERS 00318 nassertv(initial_data == (CycleData *)this); 00319 #else 00320 _data = initial_data; 00321 #endif // SIMPLE_STRUCT_POINTERS 00322 } 00323 00324 //////////////////////////////////////////////////////////////////// 00325 // Function: PipelineCyclerBase::Copy Assignment (trivial) 00326 // Access: Public 00327 // Description: 00328 //////////////////////////////////////////////////////////////////// 00329 INLINE void PipelineCyclerBase:: 00330 operator = (const PipelineCyclerBase &) { 00331 // We don't reassign the _data pointer here; we assume it was set 00332 // correctly previously. 00333 } 00334 00335 //////////////////////////////////////////////////////////////////// 00336 // Function: PipelineCyclerBase::Destructor (trivial) 00337 // Access: Public 00338 // Description: 00339 //////////////////////////////////////////////////////////////////// 00340 INLINE PipelineCyclerBase:: 00341 ~PipelineCyclerBase() { 00342 } 00343 00344 //////////////////////////////////////////////////////////////////// 00345 // Function: PipelineCyclerBase::read (trivial) 00346 // Access: Public 00347 // Description: Returns a const CycleData pointer, filled with the 00348 // data for the current stage of the pipeline as seen by 00349 // this thread. This pointer should eventually be 00350 // released by calling release_read(). 00351 //////////////////////////////////////////////////////////////////// 00352 INLINE const CycleData *PipelineCyclerBase:: 00353 read() const { 00354 #ifdef SIMPLE_STRUCT_POINTERS 00355 return (const CycleData *)this; 00356 #else 00357 return _data; 00358 #endif // SIMPLE_STRUCT_POINTERS 00359 } 00360 00361 //////////////////////////////////////////////////////////////////// 00362 // Function: PipelineCyclerBase::increment_read (trivial) 00363 // Access: Public 00364 // Description: Increments the count on a pointer previously 00365 // retrieved by read(); now the pointer will need to be 00366 // released twice. 00367 //////////////////////////////////////////////////////////////////// 00368 INLINE void PipelineCyclerBase:: 00369 increment_read(const CycleData *) const { 00370 } 00371 00372 //////////////////////////////////////////////////////////////////// 00373 // Function: PipelineCyclerBase::release_read (trivial) 00374 // Access: Public 00375 // Description: Releases a pointer previously obtained via a call to 00376 // read(). 00377 //////////////////////////////////////////////////////////////////// 00378 INLINE void PipelineCyclerBase:: 00379 release_read(const CycleData *) const { 00380 } 00381 00382 //////////////////////////////////////////////////////////////////// 00383 // Function: PipelineCyclerBase::write (trivial) 00384 // Access: Public 00385 // Description: Returns a non-const CycleData pointer, filled with a 00386 // unique copy of the data for the current stage of the 00387 // pipeline as seen by this thread. This pointer may 00388 // now be used to write to the data, and that copy of 00389 // the data will be propagate to all later stages of the 00390 // pipeline. This pointer should eventually be released 00391 // by calling release_write(). 00392 // 00393 // There may only be one outstanding write pointer on a 00394 // given stage at a time, and if there is a write 00395 // pointer there may be no read pointers on the same 00396 // stage (but see elevate_read). 00397 //////////////////////////////////////////////////////////////////// 00398 INLINE CycleData *PipelineCyclerBase:: 00399 write() { 00400 #ifdef SIMPLE_STRUCT_POINTERS 00401 return (CycleData *)this; 00402 #else 00403 return _data; 00404 #endif // SIMPLE_STRUCT_POINTERS 00405 } 00406 00407 //////////////////////////////////////////////////////////////////// 00408 // Function: PipelineCyclerBase::elevate_read (trivial) 00409 // Access: Public 00410 // Description: Elevates a currently-held read pointer into a write 00411 // pointer. This may or may not change the value of the 00412 // pointer. It is only valid to do this if this is the 00413 // only currently-outstanding read pointer on the 00414 // current stage. 00415 //////////////////////////////////////////////////////////////////// 00416 INLINE CycleData *PipelineCyclerBase:: 00417 elevate_read(const CycleData *) { 00418 #ifdef SIMPLE_STRUCT_POINTERS 00419 return (CycleData *)this; 00420 #else 00421 return _data; 00422 #endif // SIMPLE_STRUCT_POINTERS 00423 } 00424 00425 //////////////////////////////////////////////////////////////////// 00426 // Function: PipelineCyclerBase::release_write (trivial) 00427 // Access: Public 00428 // Description: Releases a pointer previously obtained via a call to 00429 // write(). 00430 //////////////////////////////////////////////////////////////////// 00431 INLINE void PipelineCyclerBase:: 00432 release_write(CycleData *) { 00433 } 00434 00435 //////////////////////////////////////////////////////////////////// 00436 // Function: PipelineCyclerBase::get_num_stages (trivial) 00437 // Access: Public 00438 // Description: Returns the number of stages in the pipeline. 00439 //////////////////////////////////////////////////////////////////// 00440 INLINE int PipelineCyclerBase:: 00441 get_num_stages() { 00442 return 1; 00443 } 00444 00445 //////////////////////////////////////////////////////////////////// 00446 // Function: PipelineCyclerBase::is_stage_unique (trivial) 00447 // Access: Public 00448 // Description: Returns true if the nth stage is a different pointer 00449 // than the previous stage, or false if its pointer is 00450 // shared with the previous one. 00451 //////////////////////////////////////////////////////////////////// 00452 INLINE bool PipelineCyclerBase:: 00453 is_stage_unique(int n) const { 00454 return true; 00455 } 00456 00457 //////////////////////////////////////////////////////////////////// 00458 // Function: PipelineCyclerBase::write_stage (trivial) 00459 // Access: Public 00460 // Description: Returns a pointer suitable for writing to the nth 00461 // stage of the pipeline. This is for special 00462 // applications that need to update the entire pipeline 00463 // at once (for instance, to remove an invalid pointer). 00464 // This pointer should later be released with 00465 // release_write_stage(). 00466 //////////////////////////////////////////////////////////////////// 00467 INLINE CycleData *PipelineCyclerBase:: 00468 write_stage(int) { 00469 return (CycleData *)this; 00470 } 00471 00472 //////////////////////////////////////////////////////////////////// 00473 // Function: PipelineCyclerBase::release_write_stage (trivial) 00474 // Access: Public 00475 // Description: Releases a pointer previously obtained via a call to 00476 // write_stage(). 00477 //////////////////////////////////////////////////////////////////// 00478 INLINE void PipelineCyclerBase:: 00479 release_write_stage(int, CycleData *) { 00480 } 00481 00482 //////////////////////////////////////////////////////////////////// 00483 // Function: PipelineCyclerBase::cheat (trivial) 00484 // Access: Public 00485 // Description: Returns a pointer without counting it. This is only 00486 // intended for use as the return value for certain 00487 // nassertr() functions, so the application can recover 00488 // after a failure to manage the read and write pointers 00489 // correctly. You should never call this function 00490 // directly. 00491 //////////////////////////////////////////////////////////////////// 00492 INLINE CycleData *PipelineCyclerBase:: 00493 cheat() const { 00494 #ifdef SIMPLE_STRUCT_POINTERS 00495 return (CycleData *)this; 00496 #else 00497 return _data; 00498 #endif // SIMPLE_STRUCT_POINTERS 00499 } 00500 00501 //////////////////////////////////////////////////////////////////// 00502 // Function: PipelineCyclerBase::get_read_count (trivial) 00503 // Access: Public 00504 // Description: Returns the number of handles currently outstanding 00505 // to read the current stage of the data. This should 00506 // only be used for debugging purposes. 00507 //////////////////////////////////////////////////////////////////// 00508 INLINE int PipelineCyclerBase:: 00509 get_read_count() const { 00510 return 0; 00511 } 00512 00513 //////////////////////////////////////////////////////////////////// 00514 // Function: PipelineCyclerBase::get_write_count (trivial) 00515 // Access: Public 00516 // Description: Returns the number of handles currently outstanding 00517 // to read the current stage of the data. This will 00518 // normally only be either 0 or 1. This should only be 00519 // used for debugging purposes. 00520 //////////////////////////////////////////////////////////////////// 00521 INLINE int PipelineCyclerBase:: 00522 get_write_count() const { 00523 return 0; 00524 } 00525 00526 00527 #endif // DO_PIPELINING