Panda3D
 All Classes Functions Variables Enumerations
pipelineCyclerDummyImpl.I
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 &copy) :
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 &copy) {
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 }
 All Classes Functions Variables Enumerations