15 #include "pipelineCyclerTrueImpl.h" 17 #ifdef THREADED_PIPELINE 19 #include "config_pipeline.h" 27 PipelineCyclerTrueImpl::
37 _num_stages = _pipeline->get_num_stages();
38 _data =
new CycleDataNode[_num_stages];
39 for (
int i = 0; i < _num_stages; ++i) {
40 _data[i]._cdata = initial_data;
43 _pipeline->add_cycler(
this);
51 PipelineCyclerTrueImpl::
52 PipelineCyclerTrueImpl(
const PipelineCyclerTrueImpl ©) :
53 _pipeline(copy._pipeline),
60 _num_stages = _pipeline->get_num_stages();
61 nassertv(_num_stages == copy._num_stages);
62 _data =
new CycleDataNode[_num_stages];
71 for (
int i = 0; i < _num_stages; ++i) {
72 PT(
CycleData) &new_pt = pointers[copy._data[i]._cdata];
74 new_pt = copy._data[i]._cdata->make_copy();
76 _data[i]._cdata = new_pt.p();
79 _pipeline->add_cycler(
this);
81 _pipeline->add_dirty_cycler(
this);
90 void PipelineCyclerTrueImpl::
91 operator = (
const PipelineCyclerTrueImpl ©) {
99 for (
int i = 0; i < _num_stages; ++i) {
100 PT(
CycleData) &new_pt = pointers[copy._data[i]._cdata];
101 if (new_pt == NULL) {
102 new_pt = copy._data[i]._cdata->make_copy();
104 _data[i]._cdata = new_pt.p();
107 if (copy._dirty && !_dirty) {
108 _pipeline->add_dirty_cycler(
this);
117 PipelineCyclerTrueImpl::
118 ~PipelineCyclerTrueImpl() {
121 _pipeline->remove_cycler(
this);
139 write_stage(
int pipeline_stage,
Thread *current_thread) {
140 _lock.acquire(current_thread);
143 nassertd(pipeline_stage >= 0 && pipeline_stage < _num_stages) {
149 CycleData *old_data = _data[pipeline_stage]._cdata;
155 if (_data[pipeline_stage]._writes_outstanding == 0) {
160 if (old_data->get_node_ref_count() != 1) {
162 _data[pipeline_stage]._cdata = old_data->make_copy();
163 if (pipeline_cat.is_debug()) {
165 <<
"Copy-on-write a: " << old_data <<
" becomes " 166 << _data[pipeline_stage]._cdata <<
"\n";
172 if (!_dirty && _num_stages != 1) {
173 _pipeline->add_dirty_cycler(
this);
178 ++(_data[pipeline_stage]._writes_outstanding);
179 return _data[pipeline_stage]._cdata;
190 write_stage_upstream(
int pipeline_stage,
bool force_to_0,
Thread *current_thread) {
191 _lock.acquire(current_thread);
194 nassertd(pipeline_stage >= 0 && pipeline_stage < _num_stages) {
200 CycleData *old_data = _data[pipeline_stage]._cdata;
202 if (old_data->get_ref_count() != 1 || force_to_0) {
205 int external_count = old_data->get_ref_count() - 1;
206 int k = pipeline_stage - 1;
207 while (k >= 0 && _data[k]._cdata == old_data) {
217 if (external_count > 0 && _data[pipeline_stage]._writes_outstanding == 0) {
220 PT(
CycleData) new_data = old_data->make_copy();
221 if (pipeline_cat.is_debug()) {
223 <<
"Copy-on-write b: " << old_data <<
" becomes " 228 k = pipeline_stage - 1;
229 while (k >= 0 && (_data[k]._cdata == old_data || force_to_0)) {
230 nassertr(_data[k]._writes_outstanding == 0, NULL);
231 _data[k]._cdata = new_data.p();
235 _data[pipeline_stage]._cdata = new_data;
237 if (k >= 0 || pipeline_stage + 1 < _num_stages) {
241 _pipeline->add_dirty_cycler(
this);
245 }
else if (k >= 0 && force_to_0) {
250 nassertr(_data[k]._writes_outstanding == 0, NULL);
251 _data[k]._cdata = old_data;
257 ++(_data[pipeline_stage]._writes_outstanding);
258 return _data[pipeline_stage]._cdata;
281 PT(
CycleData) last_val = _data[_num_stages - 1]._cdata.p();
282 nassertr(_lock.debug_is_locked(), last_val);
283 nassertr(_dirty, last_val);
286 for (i = _num_stages - 1; i > 0; --i) {
287 nassertr(_data[i]._writes_outstanding == 0, last_val);
288 _data[i]._cdata = _data[i - 1]._cdata;
291 for (i = 1; i < _num_stages; ++i) {
292 if (_data[i]._cdata != _data[i - 1]._cdata) {
309 void PipelineCyclerTrueImpl::
310 set_num_stages(
int num_stages) {
311 nassertv(_lock.debug_is_locked());
313 if (num_stages <= _num_stages) {
316 for (
int i = _num_stages; i < num_stages; ++i) {
317 nassertv(_data[i]._writes_outstanding == 0);
318 _data[i]._cdata.clear();
321 _num_stages = num_stages;
326 CycleDataNode *new_data =
new CycleDataNode[num_stages];
328 for (i = 0; i < _num_stages; ++i) {
329 nassertv(_data[i]._writes_outstanding == 0);
330 new_data[i]._cdata = _data[i]._cdata;
332 for (i = _num_stages; i < num_stages; ++i) {
333 new_data[i]._cdata = _data[_num_stages - 1]._cdata;
337 _num_stages = num_stages;
348 void PipelineCyclerTrueImpl::CyclerMutex::
349 output(ostream &out)
const {
350 out <<
"CyclerMutex ";
351 _cycler->cheat()->
output(out);
353 #endif // DEBUG_THREADS 355 #endif // THREADED_PIPELINE This is our own Panda specialization on the default STL map.
virtual void output(ostream &out) const
Formats the contents of the CycleData in some meaningful way for humans.
A single page of data maintained by a PipelineCycler.
TypeHandle get_parent_type() const
Returns the type of object that owns this cycler, as reported by CycleData::get_parent_type().
Similar to MutexHolder, but for a reentrant mutex.
static Pipeline * get_render_pipeline()
Returns a pointer to the global render pipeline.
This class manages a staged pipeline of data, for instance the render pipeline, so that each stage of...
A thread; that is, a lightweight process.