// Filename: pipelineCyclerTrivialImpl.I // Created by: drose (31Jan06) // //////////////////////////////////////////////////////////////////// // // PANDA 3D SOFTWARE // Copyright (c) Carnegie Mellon University. All rights reserved. // // All use of this software is subject to the terms of the revised BSD // license. You should have received a copy of this license along // with this source code in a file named "LICENSE." // //////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////// // Function: PipelineCyclerTrivialImpl::Constructor // Access: Public // Description: //////////////////////////////////////////////////////////////////// INLINE PipelineCyclerTrivialImpl:: PipelineCyclerTrivialImpl(CycleData *initial_data, Pipeline *) { // In the trivial implementation, a derived class (the // PipelineCycler template class) stores the CycleData object // directly within itself, and since we have no data members or // virtual functions, we get away with assuming the pointer is the // same as the 'this' pointer. // If this turns out not to be true on a particular platform, we // will have to store the pointer in this class, for a little bit of // extra overhead. #ifdef SIMPLE_STRUCT_POINTERS nassertv(initial_data == (CycleData *)this); #else _data = initial_data; #endif // SIMPLE_STRUCT_POINTERS } //////////////////////////////////////////////////////////////////// // Function: PipelineCyclerTrivialImpl::Copy Constructor // Access: Private // Description: //////////////////////////////////////////////////////////////////// INLINE PipelineCyclerTrivialImpl:: PipelineCyclerTrivialImpl(const PipelineCyclerTrivialImpl &) { // The copy constructor for the PipelineCyclerTrivialImpl case // doesn't work. Don't try to use it. The PipelineCycler template // class is #ifdeffed appropriately to call the normal constructor // instead. nassertv(false); } //////////////////////////////////////////////////////////////////// // Function: PipelineCyclerTrivialImpl::Copy Assignment // Access: Private // Description: //////////////////////////////////////////////////////////////////// INLINE void PipelineCyclerTrivialImpl:: operator = (const PipelineCyclerTrivialImpl &) { // The copy assignment operator for the PipelineCyclerTrivialImpl // case doesn't work. Don't try to use it. The PipelineCycler // template class is #ifdeffed appropriately not to call this // method. nassertv(false); } //////////////////////////////////////////////////////////////////// // Function: PipelineCyclerTrivialImpl::Destructor // Access: Public // Description: //////////////////////////////////////////////////////////////////// INLINE PipelineCyclerTrivialImpl:: ~PipelineCyclerTrivialImpl() { } //////////////////////////////////////////////////////////////////// // Function: PipelineCyclerTrivialImpl::acquire // Access: Public // Description: Grabs an overall lock on the cycler. Release it with // a call to release(). This lock should be held while // walking the list of stages. //////////////////////////////////////////////////////////////////// INLINE void PipelineCyclerTrivialImpl:: acquire(Thread *) { } //////////////////////////////////////////////////////////////////// // Function: PipelineCyclerTrivialImpl::release // Access: Public // Description: Release the overall lock on the cycler that was // grabbed via acquire(). //////////////////////////////////////////////////////////////////// INLINE void PipelineCyclerTrivialImpl:: release() { } //////////////////////////////////////////////////////////////////// // Function: PipelineCyclerTrivialImpl::read_unlocked // Access: Public // Description: Returns a const CycleData pointer, filled with the // data for the current stage of the pipeline as seen by // this thread. No lock is made on the contents; there // is no guarantee that some other thread won't modify // this object's data while you are working on it. // (However, the data within the returned CycleData // object itself is safe from modification; if another // thread modifies the data, it will perform a // copy-on-write, and thereby change the pointer stored // within the object.) //////////////////////////////////////////////////////////////////// INLINE const CycleData *PipelineCyclerTrivialImpl:: read_unlocked(Thread *) const { #ifdef SIMPLE_STRUCT_POINTERS return (const CycleData *)this; #else return _data; #endif // SIMPLE_STRUCT_POINTERS } //////////////////////////////////////////////////////////////////// // Function: PipelineCyclerTrivialImpl::read // Access: Public // Description: Returns a const CycleData pointer, filled with the // data for the current stage of the pipeline as seen by // this thread. This pointer should eventually be // released by calling release_read(). //////////////////////////////////////////////////////////////////// INLINE const CycleData *PipelineCyclerTrivialImpl:: read(Thread *) const { #ifdef SIMPLE_STRUCT_POINTERS return (const CycleData *)this; #else return _data; #endif // SIMPLE_STRUCT_POINTERS } //////////////////////////////////////////////////////////////////// // Function: PipelineCyclerTrivialImpl::increment_read // Access: Public // Description: Increments the count on a pointer previously // retrieved by read(); now the pointer will need to be // released twice. //////////////////////////////////////////////////////////////////// INLINE void PipelineCyclerTrivialImpl:: increment_read(const CycleData *) const { } //////////////////////////////////////////////////////////////////// // Function: PipelineCyclerTrivialImpl::release_read // Access: Public // Description: Releases a pointer previously obtained via a call to // read(). //////////////////////////////////////////////////////////////////// INLINE void PipelineCyclerTrivialImpl:: release_read(const CycleData *) const { } //////////////////////////////////////////////////////////////////// // Function: PipelineCyclerTrivialImpl::write // Access: Public // Description: Returns a non-const CycleData pointer, filled with a // unique copy of the data for the current stage of the // pipeline as seen by this thread. This pointer may // now be used to write to the data, and that copy of // the data will be propagated to all later stages of the // pipeline. This pointer should eventually be released // by calling release_write(). // // There may only be one outstanding write pointer on a // given stage at a time, and if there is a write // pointer there may be no read pointers on the same // stage (but see elevate_read). //////////////////////////////////////////////////////////////////// INLINE CycleData *PipelineCyclerTrivialImpl:: write(Thread *) { #ifdef SIMPLE_STRUCT_POINTERS return (CycleData *)this; #else return _data; #endif // SIMPLE_STRUCT_POINTERS } //////////////////////////////////////////////////////////////////// // Function: PipelineCyclerTrivialImpl::write_upstream // Access: Public // Description: This special variant on write() will automatically // propagate changes back to upstream pipeline stages. // If force_to_0 is false, then it propagates back only // as long as the CycleData pointers are equivalent, // guaranteeing that it does not modify upstream data // (other than the modification that will be performed // by the code that returns this pointer). This is // particularly appropriate for minor updates, where it // doesn't matter much if the update is lost, such as // storing a cached value. // // If force_to_0 is trivial, then the CycleData pointer for // the current pipeline stage is propagated all the way // back up to stage 0; after this call, there will be // only one CycleData pointer that is duplicated in all // stages between stage 0 and the current stage. This // may undo some recent changes that were made // independently at pipeline stage 0 (or any other // upstream stage). However, it guarantees that the // change that is to be applied at this pipeline stage // will stick. This is slightly dangerous because of // the risk of losing upstream changes; generally, this // should only be done when you are confident that there // are no upstream changes to be lost (for instance, for // an object that has been recently created). //////////////////////////////////////////////////////////////////// CycleData *PipelineCyclerTrivialImpl:: write_upstream(bool, Thread *) { #ifdef SIMPLE_STRUCT_POINTERS return (CycleData *)this; #else return _data; #endif // SIMPLE_STRUCT_POINTERS } //////////////////////////////////////////////////////////////////// // Function: PipelineCyclerTrivialImpl::elevate_read // Access: Public // Description: Elevates a currently-held read pointer into a write // pointer. This may or may not change the value of the // pointer. It is only valid to do this if this is the // only currently-outstanding read pointer on the // current stage. //////////////////////////////////////////////////////////////////// INLINE CycleData *PipelineCyclerTrivialImpl:: elevate_read(const CycleData *, Thread *) { #ifdef SIMPLE_STRUCT_POINTERS return (CycleData *)this; #else return _data; #endif // SIMPLE_STRUCT_POINTERS } //////////////////////////////////////////////////////////////////// // Function: PipelineCyclerTrivialImpl::elevate_read_upstream // Access: Public // Description: Elevates a currently-held read pointer into a write // pointer, like elevate_read(), but also propagates the // pointer back to upstream stages, like // write_upstream(). //////////////////////////////////////////////////////////////////// INLINE CycleData *PipelineCyclerTrivialImpl:: elevate_read_upstream(const CycleData *, bool, Thread *) { #ifdef SIMPLE_STRUCT_POINTERS return (CycleData *)this; #else return _data; #endif // SIMPLE_STRUCT_POINTERS } //////////////////////////////////////////////////////////////////// // Function: PipelineCyclerTrivialImpl::increment_write // Access: Public // Description: Increments the count on a pointer previously // retrieved by write(); now the pointer will need to be // released twice. //////////////////////////////////////////////////////////////////// INLINE void PipelineCyclerTrivialImpl:: increment_write(CycleData *) const { } //////////////////////////////////////////////////////////////////// // Function: PipelineCyclerTrivialImpl::release_write // Access: Public // Description: Releases a pointer previously obtained via a call to // write(). //////////////////////////////////////////////////////////////////// INLINE void PipelineCyclerTrivialImpl:: release_write(CycleData *) { } //////////////////////////////////////////////////////////////////// // Function: PipelineCyclerTrivialImpl::get_num_stages // Access: Public // Description: Returns the number of stages in the pipeline. //////////////////////////////////////////////////////////////////// INLINE int PipelineCyclerTrivialImpl:: get_num_stages() { return 1; } //////////////////////////////////////////////////////////////////// // Function: PipelineCyclerTrivialImpl::read_stage_unlocked // Access: Public // Description: Returns a const CycleData pointer, filled with the // data for the indicated stage of the pipeline. As in // read_unlocked(), no lock is held on the returned // pointer. //////////////////////////////////////////////////////////////////// INLINE const CycleData *PipelineCyclerTrivialImpl:: read_stage_unlocked(int) const { #ifdef SIMPLE_STRUCT_POINTERS return (const CycleData *)this; #else return _data; #endif // SIMPLE_STRUCT_POINTERS } //////////////////////////////////////////////////////////////////// // Function: PipelineCyclerTrivialImpl::read_stage // Access: Public // Description: Returns a const CycleData pointer, filled with the // data for the indicated pipeline stage. This pointer // should eventually be released by calling // release_read(). //////////////////////////////////////////////////////////////////// INLINE const CycleData *PipelineCyclerTrivialImpl:: read_stage(int, Thread *) const { #ifdef SIMPLE_STRUCT_POINTERS return (const CycleData *)this; #else return _data; #endif // SIMPLE_STRUCT_POINTERS } //////////////////////////////////////////////////////////////////// // Function: PipelineCyclerTrivialImpl::release_read_stage // Access: Public // Description: Releases a pointer previously obtained via a call to // read_stage(). //////////////////////////////////////////////////////////////////// INLINE void PipelineCyclerTrivialImpl:: release_read_stage(int, const CycleData *) const { } //////////////////////////////////////////////////////////////////// // Function: PipelineCyclerTrivialImpl::write_stage // Access: Public // Description: Returns a pointer suitable for writing to the nth // stage of the pipeline. This is for special // applications that need to update the entire pipeline // at once (for instance, to remove an invalid pointer). // This pointer should later be released with // release_write_stage(). //////////////////////////////////////////////////////////////////// INLINE CycleData *PipelineCyclerTrivialImpl:: write_stage(int, Thread *) { #ifdef SIMPLE_STRUCT_POINTERS return (CycleData *)this; #else return _data; #endif // SIMPLE_STRUCT_POINTERS } //////////////////////////////////////////////////////////////////// // Function: PipelineCyclerTrivialImpl::write_stage_upstream // Access: Public // Description: Returns a pointer suitable for writing to the nth // stage of the pipeline. This is for special // applications that need to update the entire pipeline // at once (for instance, to remove an invalid pointer). // This pointer should later be released with // release_write_stage(). //////////////////////////////////////////////////////////////////// INLINE CycleData *PipelineCyclerTrivialImpl:: write_stage_upstream(int, bool, Thread *) { #ifdef SIMPLE_STRUCT_POINTERS return (CycleData *)this; #else return _data; #endif // SIMPLE_STRUCT_POINTERS } //////////////////////////////////////////////////////////////////// // Function: PipelineCyclerTrivialImpl::elevate_read_stage // Access: Public // Description: Elevates a currently-held read pointer into a write // pointer. This may or may not change the value of the // pointer. It is only valid to do this if this is the // only currently-outstanding read pointer on the // current stage. //////////////////////////////////////////////////////////////////// INLINE CycleData *PipelineCyclerTrivialImpl:: elevate_read_stage(int, const CycleData *, Thread *) { #ifdef SIMPLE_STRUCT_POINTERS return (CycleData *)this; #else return _data; #endif // SIMPLE_STRUCT_POINTERS } //////////////////////////////////////////////////////////////////// // Function: PipelineCyclerTrivialImpl::elevate_read_stage_upstream // Access: Public // Description: Elevates a currently-held read pointer into a write // pointer. This may or may not change the value of the // pointer. It is only valid to do this if this is the // only currently-outstanding read pointer on the // current stage. //////////////////////////////////////////////////////////////////// INLINE CycleData *PipelineCyclerTrivialImpl:: elevate_read_stage_upstream(int, const CycleData *, bool, Thread *) { #ifdef SIMPLE_STRUCT_POINTERS return (CycleData *)this; #else return _data; #endif // SIMPLE_STRUCT_POINTERS } //////////////////////////////////////////////////////////////////// // Function: PipelineCyclerTrivialImpl::release_write_stage // Access: Public // Description: Releases a pointer previously obtained via a call to // write_stage(). //////////////////////////////////////////////////////////////////// INLINE void PipelineCyclerTrivialImpl:: release_write_stage(int, CycleData *) { } //////////////////////////////////////////////////////////////////// // Function: PipelineCyclerTrivialImpl::get_parent_type // Access: Public // Description: Returns the type of object that owns this cycler, as // reported by CycleData::get_parent_type(). //////////////////////////////////////////////////////////////////// INLINE TypeHandle PipelineCyclerTrivialImpl:: get_parent_type() const { return cheat()->get_parent_type(); } //////////////////////////////////////////////////////////////////// // Function: PipelineCyclerTrivialImpl::cheat // Access: Public // Description: Returns a pointer without counting it. This is only // intended for use as the return value for certain // nassertr() functions, so the application can recover // after a failure to manage the read and write pointers // correctly. You should never call this function // directly. //////////////////////////////////////////////////////////////////// INLINE CycleData *PipelineCyclerTrivialImpl:: cheat() const { #ifdef SIMPLE_STRUCT_POINTERS return (CycleData *)this; #else return _data; #endif // SIMPLE_STRUCT_POINTERS } //////////////////////////////////////////////////////////////////// // Function: PipelineCyclerTrivialImpl::get_read_count // Access: Public // Description: Returns the number of handles currently outstanding // to read the current stage of the data. This should // only be used for debugging purposes. //////////////////////////////////////////////////////////////////// INLINE int PipelineCyclerTrivialImpl:: get_read_count() const { return 0; } //////////////////////////////////////////////////////////////////// // Function: PipelineCyclerTrivialImpl::get_write_count // Access: Public // Description: Returns the number of handles currently outstanding // to read the current stage of the data. This will // normally only be either 0 or 1. This should only be // used for debugging purposes. //////////////////////////////////////////////////////////////////// INLINE int PipelineCyclerTrivialImpl:: get_write_count() const { return 0; }