Panda3D
pipelineCyclerTrueImpl.I
1 // Filename: pipelineCyclerTrueImpl.I
2 // Created by: drose (31Jan06)
3 //
4 ////////////////////////////////////////////////////////////////////
5 //
6 // PANDA 3D SOFTWARE
7 // Copyright (c) Carnegie Mellon University. All rights reserved.
8 //
9 // All use of this software is subject to the terms of the revised BSD
10 // license. You should have received a copy of this license along
11 // with this source code in a file named "LICENSE."
12 //
13 ////////////////////////////////////////////////////////////////////
14 
15 
16 ////////////////////////////////////////////////////////////////////
17 // Function: PipelineCyclerTrueImpl::acquire
18 // Access: Public
19 // Description: Grabs an overall lock on the cycler. Release it with
20 // a call to release(). This lock should be held while
21 // walking the list of stages.
22 ////////////////////////////////////////////////////////////////////
23 INLINE void PipelineCyclerTrueImpl::
24 acquire() {
25  TAU_PROFILE("void PipelineCyclerTrueImpl::acquire()", " ", TAU_USER);
26  _lock.acquire();
27 }
28 
29 ////////////////////////////////////////////////////////////////////
30 // Function: PipelineCyclerTrueImpl::acquire
31 // Access: Public
32 // Description: Grabs an overall lock on the cycler. Release it with
33 // a call to release(). This lock should be held while
34 // walking the list of stages.
35 ////////////////////////////////////////////////////////////////////
36 INLINE void PipelineCyclerTrueImpl::
37 acquire(Thread *current_thread) {
38  TAU_PROFILE("void PipelineCyclerTrueImpl::acquire(Thread *)", " ", TAU_USER);
39  _lock.acquire(current_thread);
40 }
41 
42 ////////////////////////////////////////////////////////////////////
43 // Function: PipelineCyclerTrueImpl::release
44 // Access: Public
45 // Description: Release the overall lock on the cycler that was
46 // grabbed via acquire().
47 ////////////////////////////////////////////////////////////////////
48 INLINE void PipelineCyclerTrueImpl::
49 release() {
50  TAU_PROFILE("void PipelineCyclerTrueImpl::release()", " ", TAU_USER);
51  _lock.release();
52 }
53 
54 ////////////////////////////////////////////////////////////////////
55 // Function: PipelineCyclerTrueImpl::read_unlocked
56 // Access: Public
57 // Description: Returns a const CycleData pointer, filled with the
58 // data for the current stage of the pipeline as seen by
59 // this thread. No lock is made on the contents; there
60 // is no guarantee that some other thread won't modify
61 // this object's data while you are working on it.
62 // (However, the data within the returned CycleData
63 // object itself is safe from modification; if another
64 // thread modifies the data, it will perform a
65 // copy-on-write, and thereby change the pointer stored
66 // within the object.)
67 ////////////////////////////////////////////////////////////////////
68 INLINE const CycleData *PipelineCyclerTrueImpl::
69 read_unlocked(Thread *current_thread) const {
70  TAU_PROFILE("const CycleData *PipelineCyclerTrueImpl::read_unlocked(Thread *)", " ", TAU_USER);
71  int pipeline_stage = current_thread->get_pipeline_stage();
72 #ifdef _DEBUG
73  nassertr(pipeline_stage >= 0 && pipeline_stage < _num_stages, NULL);
74 #endif
75  return _data[pipeline_stage]._cdata;
76 }
77 
78 ////////////////////////////////////////////////////////////////////
79 // Function: PipelineCyclerTrueImpl::read
80 // Access: Public
81 // Description: Returns a const CycleData pointer, filled with the
82 // data for the current stage of the pipeline as seen by
83 // this thread. This pointer should eventually be
84 // released by calling release_read().
85 //
86 // There should be no outstanding write pointers on the
87 // data when this function is called.
88 ////////////////////////////////////////////////////////////////////
89 INLINE const CycleData *PipelineCyclerTrueImpl::
90 read(Thread *current_thread) const {
91  TAU_PROFILE("const CycleData *PipelineCyclerTrueImpl::read(Thread *)", " ", TAU_USER);
92  int pipeline_stage = current_thread->get_pipeline_stage();
93 #ifdef _DEBUG
94  nassertr(pipeline_stage >= 0 && pipeline_stage < _num_stages, NULL);
95 #endif
96  _lock.acquire(current_thread);
97  return _data[pipeline_stage]._cdata;
98 }
99 
100 ////////////////////////////////////////////////////////////////////
101 // Function: PipelineCyclerTrueImpl::increment_read
102 // Access: Public
103 // Description: Increments the count on a pointer previously
104 // retrieved by read(); now the pointer will need to be
105 // released twice.
106 ////////////////////////////////////////////////////////////////////
107 INLINE void PipelineCyclerTrueImpl::
108 increment_read(const CycleData *pointer) const {
109  TAU_PROFILE("void PipelineCyclerTrueImpl::increment_read(const CycleData *)", " ", TAU_USER);
110 #ifdef _DEBUG
111  int pipeline_stage = Thread::get_current_pipeline_stage();
112  nassertv(pipeline_stage >= 0 && pipeline_stage < _num_stages);
113  nassertv(_data[pipeline_stage]._cdata == pointer);
114 #endif
115  _lock.elevate_lock();
116 }
117 
118 ////////////////////////////////////////////////////////////////////
119 // Function: PipelineCyclerTrueImpl::release_read
120 // Access: Public
121 // Description: Releases a pointer previously obtained via a call to
122 // read().
123 ////////////////////////////////////////////////////////////////////
124 INLINE void PipelineCyclerTrueImpl::
125 release_read(const CycleData *pointer) const {
126  TAU_PROFILE("void PipelineCyclerTrueImpl::release_read(const CycleData *)", " ", TAU_USER);
127 #ifdef _DEBUG
128  int pipeline_stage = Thread::get_current_pipeline_stage();
129  nassertv(pipeline_stage >= 0 && pipeline_stage < _num_stages);
130  nassertv(_data[pipeline_stage]._cdata == pointer);
131 #endif
132  _lock.release();
133 }
134 
135 ////////////////////////////////////////////////////////////////////
136 // Function: PipelineCyclerTrueImpl::write
137 // Access: Public
138 // Description: Returns a non-const CycleData pointer, filled with a
139 // unique copy of the data for the current stage of the
140 // pipeline as seen by this thread. This pointer may
141 // now be used to write to the data, and that copy of
142 // the data will be propagated to all later stages of the
143 // pipeline. This pointer should eventually be released
144 // by calling release_write().
145 //
146 // There may only be one outstanding write pointer on a
147 // given stage at a time, and if there is a write
148 // pointer there may be no read pointers on the same
149 // stage (but see elevate_read).
150 ////////////////////////////////////////////////////////////////////
151 INLINE CycleData *PipelineCyclerTrueImpl::
152 write(Thread *current_thread) {
153  TAU_PROFILE("CycleData *PipelineCyclerTrueImpl::write(Thread *)", " ", TAU_USER);
154  return write_stage(current_thread->get_pipeline_stage(), current_thread);
155 }
156 
157 ////////////////////////////////////////////////////////////////////
158 // Function: PipelineCyclerTrueImpl::write_upstream
159 // Access: Public
160 // Description: This special variant on write() will automatically
161 // propagate changes back to upstream pipeline stages.
162 // If force_to_0 is false, then it propagates back only
163 // as long as the CycleData pointers are equivalent,
164 // guaranteeing that it does not modify upstream data
165 // (other than the modification that will be performed
166 // by the code that returns this pointer). This is
167 // particularly appropriate for minor updates, where it
168 // doesn't matter much if the update is lost, such as
169 // storing a cached value.
170 //
171 // If force_to_0 is true, then the CycleData pointer for
172 // the current pipeline stage is propagated all the way
173 // back up to stage 0; after this call, there will be
174 // only one CycleData pointer that is duplicated in all
175 // stages between stage 0 and the current stage. This
176 // may undo some recent changes that were made
177 // independently at pipeline stage 0 (or any other
178 // upstream stage). However, it guarantees that the
179 // change that is to be applied at this pipeline stage
180 // will stick. This is slightly dangerous because of
181 // the risk of losing upstream changes; generally, this
182 // should only be done when you are confident that there
183 // are no upstream changes to be lost (for instance, for
184 // an object that has been recently created).
185 ////////////////////////////////////////////////////////////////////
186 INLINE CycleData *PipelineCyclerTrueImpl::
187 write_upstream(bool force_to_0, Thread *current_thread) {
188  TAU_PROFILE("CycleData *PipelineCyclerTrueImpl::write_upstream(bool, Thread *)", " ", TAU_USER);
189  return write_stage_upstream(current_thread->get_pipeline_stage(), force_to_0,
190  current_thread);
191 }
192 
193 ////////////////////////////////////////////////////////////////////
194 // Function: PipelineCyclerTrueImpl::elevate_read
195 // Access: Public
196 // Description: Elevates a currently-held read pointer into a write
197 // pointer. This may or may not change the value of the
198 // pointer. It is only valid to do this if this is the
199 // only currently-outstanding read pointer on the
200 // current stage.
201 ////////////////////////////////////////////////////////////////////
202 INLINE CycleData *PipelineCyclerTrueImpl::
203 elevate_read(const CycleData *pointer, Thread *current_thread) {
204  TAU_PROFILE("CycleData *PipelineCyclerTrueImpl::elevate_read(const CycleData *)", " ", TAU_USER);
205 #ifdef _DEBUG
206  int pipeline_stage = current_thread->get_pipeline_stage();
207  nassertr(pipeline_stage >= 0 && pipeline_stage < _num_stages, NULL);
208  nassertr(_data[pipeline_stage]._cdata == pointer, NULL);
209 #endif
210  CycleData *new_pointer = write(current_thread);
211  _lock.release();
212  return new_pointer;
213 }
214 
215 ////////////////////////////////////////////////////////////////////
216 // Function: PipelineCyclerTrueImpl::elevate_read_upstream
217 // Access: Public
218 // Description: Elevates a currently-held read pointer into a write
219 // pointer, like elevate_read(), but also propagates the
220 // pointer back to upstream stages, like
221 // write_upstream().
222 ////////////////////////////////////////////////////////////////////
223 INLINE CycleData *PipelineCyclerTrueImpl::
224 elevate_read_upstream(const CycleData *pointer, bool force_to_0, Thread *current_thread) {
225  TAU_PROFILE("CycleData *PipelineCyclerTrueImpl::elevate_read_upstream(const CycleData *, bool)", " ", TAU_USER);
226 #ifdef _DEBUG
227  int pipeline_stage = current_thread->get_pipeline_stage();
228  nassertr(pipeline_stage >= 0 && pipeline_stage < _num_stages, NULL);
229  nassertr(_data[pipeline_stage]._cdata == pointer, NULL);
230 #endif
231  CycleData *new_pointer = write_upstream(force_to_0, current_thread);
232  _lock.release();
233  return new_pointer;
234 }
235 
236 ////////////////////////////////////////////////////////////////////
237 // Function: PipelineCyclerTrueImpl::increment_write
238 // Access: Public
239 // Description: Increments the count on a pointer previously
240 // retrieved by write(); now the pointer will need to be
241 // released twice.
242 ////////////////////////////////////////////////////////////////////
243 INLINE void PipelineCyclerTrueImpl::
244 increment_write(CycleData *pointer) const {
245  TAU_PROFILE("void PipelineCyclerTrueImpl::increment_write(CycleData *)", " ", TAU_USER);
246  int pipeline_stage = Thread::get_current_pipeline_stage();
247 #ifdef _DEBUG
248  nassertv(pipeline_stage >= 0 && pipeline_stage < _num_stages);
249  nassertv(_data[pipeline_stage]._cdata == pointer);
250 #endif
251  ++(_data[pipeline_stage]._writes_outstanding);
252  _lock.elevate_lock();
253 }
254 
255 ////////////////////////////////////////////////////////////////////
256 // Function: PipelineCyclerTrueImpl::release_write
257 // Access: Public
258 // Description: Releases a pointer previously obtained via a call to
259 // write().
260 ////////////////////////////////////////////////////////////////////
261 INLINE void PipelineCyclerTrueImpl::
262 release_write(CycleData *pointer) {
263  TAU_PROFILE("void PipelineCyclerTrueImpl::release_write(CycleData *)", " ", TAU_USER);
264  int pipeline_stage = Thread::get_current_pipeline_stage();
265  return release_write_stage(pipeline_stage, pointer);
266 }
267 
268 ////////////////////////////////////////////////////////////////////
269 // Function: PipelineCyclerTrueImpl::get_num_stages
270 // Access: Public
271 // Description: Returns the number of stages in the pipeline.
272 ////////////////////////////////////////////////////////////////////
273 INLINE int PipelineCyclerTrueImpl::
274 get_num_stages() {
275  return _num_stages;
276 }
277 
278 ////////////////////////////////////////////////////////////////////
279 // Function: PipelineCyclerTrueImpl::read_stage_unlocked
280 // Access: Public
281 // Description: Returns a const CycleData pointer, filled with the
282 // data for the indicated stage of the pipeline. As in
283 // read_unlocked(), no lock is held on the returned
284 // pointer.
285 ////////////////////////////////////////////////////////////////////
286 INLINE const CycleData *PipelineCyclerTrueImpl::
287 read_stage_unlocked(int pipeline_stage) const {
288  TAU_PROFILE("const CycleData *PipelineCyclerTrueImpl::read_stage_unlocked(int)", " ", TAU_USER);
289 #ifdef _DEBUG
290  nassertr(pipeline_stage >= 0 && pipeline_stage < _num_stages, NULL);
291 #endif
292  return _data[pipeline_stage]._cdata;
293 }
294 
295 ////////////////////////////////////////////////////////////////////
296 // Function: PipelineCyclerTrueImpl::read_stage
297 // Access: Public
298 // Description: Returns a const CycleData pointer, filled with the
299 // data for the indicated stage of the pipeline. This
300 // pointer should eventually be released by calling
301 // release_read_stage().
302 //
303 // There should be no outstanding write pointers on the
304 // data when this function is called.
305 ////////////////////////////////////////////////////////////////////
306 INLINE const CycleData *PipelineCyclerTrueImpl::
307 read_stage(int pipeline_stage, Thread *current_thread) const {
308  TAU_PROFILE("const CycleData *PipelineCyclerTrueImpl::read_stage(int, Thread *)", " ", TAU_USER);
309 #ifdef _DEBUG
310  nassertr(pipeline_stage >= 0 && pipeline_stage < _num_stages, NULL);
311 #endif
312  _lock.acquire(current_thread);
313  return _data[pipeline_stage]._cdata;
314 }
315 
316 ////////////////////////////////////////////////////////////////////
317 // Function: PipelineCyclerTrueImpl::release_read_stage
318 // Access: Public
319 // Description: Releases a pointer previously obtained via a call to
320 // read_stage().
321 ////////////////////////////////////////////////////////////////////
322 INLINE void PipelineCyclerTrueImpl::
323 release_read_stage(int pipeline_stage, const CycleData *pointer) const {
324  TAU_PROFILE("void PipelineCyclerTrueImpl::release_read_stage(int, const CycleData *)", " ", TAU_USER);
325 #ifdef _DEBUG
326  nassertv(pipeline_stage >= 0 && pipeline_stage < _num_stages);
327  nassertv(_data[pipeline_stage]._cdata == pointer);
328 #endif
329  _lock.release();
330 }
331 
332 ////////////////////////////////////////////////////////////////////
333 // Function: PipelineCyclerTrueImpl::elevate_read_stage
334 // Access: Public
335 // Description: Elevates a currently-held read pointer into a write
336 // pointer. This may or may not change the value of the
337 // pointer. It is only valid to do this if this is the
338 // only currently-outstanding read pointer on the
339 // indicated stage.
340 ////////////////////////////////////////////////////////////////////
341 INLINE CycleData *PipelineCyclerTrueImpl::
342 elevate_read_stage(int pipeline_stage, const CycleData *pointer,
343  Thread *current_thread) {
344  TAU_PROFILE("CycleData *PipelineCyclerTrueImpl::elevate_read_stage(int, const CycleData *)", " ", TAU_USER);
345 #ifdef _DEBUG
346  nassertr(pipeline_stage >= 0 && pipeline_stage < _num_stages, NULL);
347  nassertr(_data[pipeline_stage]._cdata == pointer, NULL);
348 #endif
349  CycleData *new_pointer = write_stage(pipeline_stage, current_thread);
350  _lock.release();
351  return new_pointer;
352 }
353 
354 ////////////////////////////////////////////////////////////////////
355 // Function: PipelineCyclerTrueImpl::elevate_read_stage_upstream
356 // Access: Public
357 // Description: Elevates a currently-held read pointer into a write
358 // pointer. This may or may not change the value of the
359 // pointer. It is only valid to do this if this is the
360 // only currently-outstanding read pointer on the
361 // indicated stage.
362 ////////////////////////////////////////////////////////////////////
363 INLINE CycleData *PipelineCyclerTrueImpl::
364 elevate_read_stage_upstream(int pipeline_stage, const CycleData *pointer,
365  bool force_to_0, Thread *current_thread) {
366  TAU_PROFILE("CycleData *PipelineCyclerTrueImpl::elevate_read_stage(int, const CycleData *)", " ", TAU_USER);
367 #ifdef _DEBUG
368  nassertr(pipeline_stage >= 0 && pipeline_stage < _num_stages, NULL);
369  nassertr(_data[pipeline_stage]._cdata == pointer, NULL);
370 #endif
371  CycleData *new_pointer =
372  write_stage_upstream(pipeline_stage, force_to_0, current_thread);
373  _lock.release();
374  return new_pointer;
375 }
376 
377 ////////////////////////////////////////////////////////////////////
378 // Function: PipelineCyclerTrueImpl::release_write_stage
379 // Access: Public
380 // Description: Releases a pointer previously obtained via a call to
381 // write_stage().
382 ////////////////////////////////////////////////////////////////////
383 INLINE void PipelineCyclerTrueImpl::
384 release_write_stage(int pipeline_stage, CycleData *pointer) {
385  TAU_PROFILE("void PipelineCyclerTrueImpl::release_write_stage(int, const CycleData *)", " ", TAU_USER);
386 #ifdef _DEBUG
387  nassertv(pipeline_stage >= 0 && pipeline_stage < _num_stages);
388  nassertv(_data[pipeline_stage]._cdata == pointer);
389  nassertv(_data[pipeline_stage]._writes_outstanding > 0);
390 #endif
391  --(_data[pipeline_stage]._writes_outstanding);
392  _lock.release();
393 }
394 
395 ////////////////////////////////////////////////////////////////////
396 // Function: PipelineCyclerTrueImpl::get_parent_type
397 // Access: Public
398 // Description: Returns the type of object that owns this cycler, as
399 // reported by CycleData::get_parent_type().
400 ////////////////////////////////////////////////////////////////////
401 INLINE TypeHandle PipelineCyclerTrueImpl::
402 get_parent_type() const {
403  return _data[0]._cdata->get_parent_type();
404 }
405 
406 ////////////////////////////////////////////////////////////////////
407 // Function: PipelineCyclerTrueImpl::cheat
408 // Access: Public
409 // Description: Returns a pointer without counting it. This is only
410 // intended for use as the return value for certain
411 // nassertr() functions, so the application can recover
412 // after a failure to manage the read and write pointers
413 // correctly. You should never call this function
414 // directly.
415 ////////////////////////////////////////////////////////////////////
416 INLINE CycleData *PipelineCyclerTrueImpl::
417 cheat() const {
418  TAU_PROFILE("CycleData *PipelineCyclerTrueImpl::cheat()", " ", TAU_USER);
419  int pipeline_stage = Thread::get_current_pipeline_stage();
420  nassertr(pipeline_stage >= 0 && pipeline_stage < _num_stages, NULL);
421  return _data[pipeline_stage]._cdata;
422 }
423 
424 ////////////////////////////////////////////////////////////////////
425 // Function: PipelineCyclerTrueImpl::get_read_count
426 // Access: Public
427 // Description: Returns the number of handles currently outstanding
428 // to read the current stage of the data. This should
429 // only be used for debugging purposes.
430 ////////////////////////////////////////////////////////////////////
431 INLINE int PipelineCyclerTrueImpl::
432 get_read_count() const {
433  return 0;
434 }
435 
436 ////////////////////////////////////////////////////////////////////
437 // Function: PipelineCyclerTrueImpl::get_write_count
438 // Access: Public
439 // Description: Returns the number of handles currently outstanding
440 // to read the current stage of the data. This will
441 // normally only be either 0 or 1. This should only be
442 // used for debugging purposes.
443 ////////////////////////////////////////////////////////////////////
444 INLINE int PipelineCyclerTrueImpl::
445 get_write_count() const {
446  return 0;
447 }
448 
449 ////////////////////////////////////////////////////////////////////
450 // Function: PipelineCyclerTrueImpl::cycle_2
451 // Access: Private
452 // Description: This is a special implementation of cycle() for the
453 // special case of just two stages to the pipeline. It
454 // does the same thing as cycle(), but is a little bit
455 // faster because it knows there are exactly two stages.
456 ////////////////////////////////////////////////////////////////////
457 INLINE PT(CycleData) PipelineCyclerTrueImpl::
458 cycle_2() {
459  TAU_PROFILE("PT(CycleData) PipelineCyclerTrueImpl::cycle_2()", " ", TAU_USER);
460  PT(CycleData) last_val = _data[1]._cdata.p();
461  nassertr(_lock.debug_is_locked(), last_val);
462  nassertr(_dirty, last_val);
463  nassertr(_num_stages == 2, last_val);
464 
465  nassertr(_data[1]._writes_outstanding == 0, last_val);
466  _data[1]._cdata = _data[0]._cdata;
467 
468  // No longer dirty.
469  _dirty = false;
470  return last_val;
471 }
472 
473 ////////////////////////////////////////////////////////////////////
474 // Function: PipelineCyclerTrueImpl::cycle_3
475 // Access: Private
476 // Description: This is a special implementation of cycle() for the
477 // special case of exactly three stages to the pipeline.
478 // It does the same thing as cycle(), but is a little
479 // bit faster because it knows there are exactly three
480 // stages.
481 ////////////////////////////////////////////////////////////////////
482 INLINE PT(CycleData) PipelineCyclerTrueImpl::
483 cycle_3() {
484  TAU_PROFILE("PT(CycleData) PipelineCyclerTrueImpl::cycle_3()", " ", TAU_USER);
485  PT(CycleData) last_val = _data[2]._cdata.p();
486  nassertr(_lock.debug_is_locked(), last_val);
487  nassertr(_dirty, last_val);
488  nassertr(_num_stages == 3, last_val);
489 
490  nassertr(_data[2]._writes_outstanding == 0, last_val);
491  nassertr(_data[1]._writes_outstanding == 0, last_val);
492  _data[2]._cdata = _data[1]._cdata;
493  _data[1]._cdata = _data[0]._cdata;
494 
495  if (_data[2]._cdata == _data[1]._cdata) {
496  // No longer dirty.
497  _dirty = false;
498  }
499 
500  return last_val;
501 }
502 
503 ////////////////////////////////////////////////////////////////////
504 // Function: PipelineCyclerTrueImpl::CyclerMutex::Constructor
505 // Access: Public
506 // Description:
507 ////////////////////////////////////////////////////////////////////
508 INLINE PipelineCyclerTrueImpl::CyclerMutex::
509 CyclerMutex(PipelineCyclerTrueImpl *cycler) {
510 #ifdef DEBUG_THREADS
511  _cycler = cycler;
512 #endif
513 }
514 
515 ////////////////////////////////////////////////////////////////////
516 // Function: PipelineCyclerTrueImpl::CyclerMutex::Constructor
517 // Access: Public
518 // Description:
519 ////////////////////////////////////////////////////////////////////
520 INLINE PipelineCyclerTrueImpl::CycleDataNode::
521 CycleDataNode() :
522  _writes_outstanding(0)
523 {
524 }
525 
526 ////////////////////////////////////////////////////////////////////
527 // Function: PipelineCyclerTrueImpl::CyclerMutex::Copy Constructor
528 // Access: Public
529 // Description:
530 ////////////////////////////////////////////////////////////////////
531 INLINE PipelineCyclerTrueImpl::CycleDataNode::
532 CycleDataNode(const PipelineCyclerTrueImpl::CycleDataNode &copy) :
533  _cdata(copy._cdata),
534  _writes_outstanding(0)
535 {
536 }
537 
538 ////////////////////////////////////////////////////////////////////
539 // Function: PipelineCyclerTrueImpl::CyclerMutex::Destructor
540 // Access: Public
541 // Description:
542 ////////////////////////////////////////////////////////////////////
543 INLINE PipelineCyclerTrueImpl::CycleDataNode::
544 ~CycleDataNode() {
545  nassertv(_writes_outstanding == 0);
546 }
547 
548 ////////////////////////////////////////////////////////////////////
549 // Function: PipelineCyclerTrueImpl::CyclerMutex::Copy Assignment
550 // Access: Public
551 // Description:
552 ////////////////////////////////////////////////////////////////////
553 INLINE void PipelineCyclerTrueImpl::CycleDataNode::
554 operator = (const PipelineCyclerTrueImpl::CycleDataNode &copy) {
555  _cdata = copy._cdata;
556 }
int get_pipeline_stage() const
Returns the Pipeline stage number associated with this thread.
Definition: thread.I:84
A single page of data maintained by a PipelineCycler.
Definition: cycleData.h:50
A thread; that is, a lightweight process.
Definition: thread.h:51
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:85
static int get_current_pipeline_stage()
Returns the integer pipeline stage associated with the current thread.
Definition: thread.I:167