140 lines
4.6 KiB
C
140 lines
4.6 KiB
C
|
/**
|
||
|
* 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."
|
||
|
*
|
||
|
* @file pipelineCyclerTrueImpl.h
|
||
|
* @author drose
|
||
|
* @date 2006-01-31
|
||
|
*/
|
||
|
|
||
|
#ifndef PIPELINECYCLERTRUEIMPL_H
|
||
|
#define PIPELINECYCLERTRUEIMPL_H
|
||
|
|
||
|
#include "pandabase.h"
|
||
|
#include "selectThreadImpl.h" // for THREADED_PIPELINE definition
|
||
|
|
||
|
#ifdef THREADED_PIPELINE
|
||
|
|
||
|
#include "pipelineCyclerLinks.h"
|
||
|
#include "cycleData.h"
|
||
|
#include "pointerTo.h"
|
||
|
#include "nodePointerTo.h"
|
||
|
#include "thread.h"
|
||
|
#include "reMutex.h"
|
||
|
#include "reMutexHolder.h"
|
||
|
|
||
|
class Pipeline;
|
||
|
|
||
|
/**
|
||
|
* This is the true, threaded implementation of PipelineCyclerBase. It is
|
||
|
* only compiled when threading is available and DO_PIPELINING is defined.
|
||
|
*
|
||
|
* This implementation is designed to do the actual work of cycling the data
|
||
|
* through a pipeline, and returning the actual CycleData appropriate to the
|
||
|
* current thread's pipeline stage.
|
||
|
*
|
||
|
* This is defined as a struct instead of a class, mainly to be consistent
|
||
|
* with PipelineCyclerTrivialImpl.
|
||
|
*/
|
||
|
struct EXPCL_PANDA_PIPELINE PipelineCyclerTrueImpl : public PipelineCyclerLinks {
|
||
|
private:
|
||
|
PipelineCyclerTrueImpl();
|
||
|
public:
|
||
|
PipelineCyclerTrueImpl(CycleData *initial_data, Pipeline *pipeline = nullptr);
|
||
|
PipelineCyclerTrueImpl(const PipelineCyclerTrueImpl ©);
|
||
|
void operator = (const PipelineCyclerTrueImpl ©);
|
||
|
~PipelineCyclerTrueImpl();
|
||
|
|
||
|
INLINE void acquire();
|
||
|
INLINE void acquire(Thread *current_thread);
|
||
|
INLINE void release();
|
||
|
|
||
|
INLINE const CycleData *read_unlocked(Thread *current_thread) const;
|
||
|
|
||
|
INLINE const CycleData *read(Thread *current_thread) const;
|
||
|
INLINE void increment_read(const CycleData *pointer) const;
|
||
|
INLINE void release_read(const CycleData *pointer) const;
|
||
|
|
||
|
INLINE CycleData *write(Thread *current_thread);
|
||
|
INLINE CycleData *write_upstream(bool force_to_0, Thread *current_thread);
|
||
|
INLINE CycleData *elevate_read(const CycleData *pointer, Thread *current_thread);
|
||
|
INLINE CycleData *elevate_read_upstream(const CycleData *pointer, bool force_to_0, Thread *current_thread);
|
||
|
INLINE void increment_write(CycleData *pointer) const;
|
||
|
INLINE void release_write(CycleData *pointer);
|
||
|
|
||
|
INLINE int get_num_stages();
|
||
|
INLINE const CycleData *read_stage_unlocked(int pipeline_stage) const;
|
||
|
INLINE const CycleData *read_stage(int pipeline_stage, Thread *current_thread) const;
|
||
|
INLINE void release_read_stage(int pipeline_stage, const CycleData *pointer) const;
|
||
|
CycleData *write_stage(int pipeline_stage, Thread *current_thread);
|
||
|
CycleData *write_stage_upstream(int pipeline_stage, bool force_to_0,
|
||
|
Thread *current_thread);
|
||
|
INLINE CycleData *elevate_read_stage(int pipeline_stage, const CycleData *pointer,
|
||
|
Thread *current_thread);
|
||
|
INLINE CycleData *elevate_read_stage_upstream(int pipeline_stage, const CycleData *pointer,
|
||
|
bool force_to_0, Thread *current_thread);
|
||
|
INLINE void release_write_stage(int pipeline_stage, CycleData *pointer);
|
||
|
|
||
|
INLINE TypeHandle get_parent_type() const;
|
||
|
|
||
|
INLINE CycleData *cheat() const;
|
||
|
INLINE int get_read_count() const;
|
||
|
INLINE int get_write_count() const;
|
||
|
|
||
|
public:
|
||
|
// We redefine the ReMutex class, solely so we can define the output()
|
||
|
// operator. This is only useful for debugging, but does no harm in the
|
||
|
// production case.
|
||
|
class CyclerMutex : public ReMutex {
|
||
|
public:
|
||
|
INLINE CyclerMutex(PipelineCyclerTrueImpl *cycler);
|
||
|
|
||
|
#ifdef DEBUG_THREADS
|
||
|
virtual void output(std::ostream &out) const;
|
||
|
PipelineCyclerTrueImpl *_cycler;
|
||
|
#endif // DEBUG_THREADS
|
||
|
};
|
||
|
|
||
|
private:
|
||
|
PT(CycleData) cycle();
|
||
|
INLINE PT(CycleData) cycle_2();
|
||
|
INLINE PT(CycleData) cycle_3();
|
||
|
void set_num_stages(int num_stages);
|
||
|
|
||
|
private:
|
||
|
Pipeline *_pipeline;
|
||
|
|
||
|
// An array of PT(CycleData) objects representing the different copies of
|
||
|
// the cycled data, one for each stage.
|
||
|
class CycleDataNode : public MemoryBase {
|
||
|
public:
|
||
|
INLINE CycleDataNode();
|
||
|
INLINE CycleDataNode(const CycleDataNode ©);
|
||
|
INLINE ~CycleDataNode();
|
||
|
INLINE void operator = (const CycleDataNode ©);
|
||
|
|
||
|
NPT(CycleData) _cdata;
|
||
|
int _writes_outstanding;
|
||
|
};
|
||
|
CycleDataNode *_data;
|
||
|
int _num_stages;
|
||
|
|
||
|
// This is 0 if it's clean, or set to Pipeline::_next_cycle_seq if it's
|
||
|
// scheduled to be cycled during the next cycle() call.
|
||
|
unsigned int _dirty;
|
||
|
|
||
|
CyclerMutex _lock;
|
||
|
|
||
|
friend class Pipeline;
|
||
|
};
|
||
|
|
||
|
#include "pipelineCyclerTrueImpl.I"
|
||
|
|
||
|
#endif // THREADED_PIPELINE
|
||
|
|
||
|
#endif
|