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