mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-04 10:54:24 -04:00
thread_priority, frame_budget, etc.
This commit is contained in:
parent
d9dede923f
commit
72dad6e9d5
@ -309,6 +309,8 @@ unlock_and_do_task() {
|
|||||||
_total_dt += _dt;
|
_total_dt += _dt;
|
||||||
++_num_frames;
|
++_num_frames;
|
||||||
|
|
||||||
|
_chain->_time_in_frame += _dt;
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,25 +25,3 @@ INLINE bool AsyncTaskChain::
|
|||||||
is_started() const {
|
is_started() const {
|
||||||
return (_state == S_started);
|
return (_state == S_started);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
// Function: AsyncTaskChain::set_tick_clock
|
|
||||||
// Access: Published
|
|
||||||
// Description: Sets the tick_clock flag. When this is true,
|
|
||||||
// get_clock()->tick() will be called automatically at
|
|
||||||
// each task epoch. This is false by default.
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
INLINE void AsyncTaskChain::
|
|
||||||
set_tick_clock(bool clock) {
|
|
||||||
_tick_clock = clock;
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
// Function: AsyncTaskChain::get_tick_clock
|
|
||||||
// Access: Published
|
|
||||||
// Description: Returns the tick_clock flag.. See set_tick_clock().
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
INLINE bool AsyncTaskChain::
|
|
||||||
get_tick_clock() const {
|
|
||||||
return _tick_clock;
|
|
||||||
}
|
|
||||||
|
@ -40,14 +40,18 @@ AsyncTaskChain::
|
|||||||
AsyncTaskChain(AsyncTaskManager *manager, const string &name) :
|
AsyncTaskChain(AsyncTaskManager *manager, const string &name) :
|
||||||
Namable(name),
|
Namable(name),
|
||||||
_manager(manager),
|
_manager(manager),
|
||||||
|
_cvar(manager->_lock),
|
||||||
_tick_clock(false),
|
_tick_clock(false),
|
||||||
_num_threads(0),
|
_num_threads(0),
|
||||||
_cvar(manager->_lock),
|
_thread_priority(TP_normal),
|
||||||
_num_tasks(0),
|
_frame_budget(-1.0),
|
||||||
_num_busy_threads(0),
|
_num_busy_threads(0),
|
||||||
|
_num_tasks(0),
|
||||||
_state(S_initial),
|
_state(S_initial),
|
||||||
_current_sort(INT_MAX),
|
_current_sort(INT_MAX),
|
||||||
_needs_cleanup(false)
|
_needs_cleanup(false),
|
||||||
|
_current_frame(0),
|
||||||
|
_time_in_frame(0.0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,6 +71,38 @@ AsyncTaskChain::
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: AsyncTaskChain::set_tick_clock
|
||||||
|
// Access: Published
|
||||||
|
// Description: Sets the tick_clock flag. When this is true,
|
||||||
|
// get_clock()->tick() will be called automatically at
|
||||||
|
// each task epoch. This is false by default.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void AsyncTaskChain::
|
||||||
|
set_tick_clock(bool tick_clock) {
|
||||||
|
if (_manager != (AsyncTaskManager *)NULL) {
|
||||||
|
MutexHolder holder(_manager->_lock);
|
||||||
|
_tick_clock = tick_clock;
|
||||||
|
} else {
|
||||||
|
_tick_clock = tick_clock;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: AsyncTaskChain::get_tick_clock
|
||||||
|
// Access: Published
|
||||||
|
// Description: Returns the tick_clock flag. See set_tick_clock().
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
bool AsyncTaskChain::
|
||||||
|
get_tick_clock() const {
|
||||||
|
if (_manager != (AsyncTaskManager *)NULL) {
|
||||||
|
MutexHolder holder(_manager->_lock);
|
||||||
|
return _tick_clock;
|
||||||
|
} else {
|
||||||
|
return _tick_clock;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: AsyncTaskChain::set_num_threads
|
// Function: AsyncTaskChain::set_num_threads
|
||||||
// Access: Published
|
// Access: Published
|
||||||
@ -120,6 +156,77 @@ get_num_running_threads() const {
|
|||||||
return _threads.size();
|
return _threads.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: AsyncTaskChain::set_thread_priority
|
||||||
|
// Access: Published
|
||||||
|
// Description: Changes the priority associated with threads that
|
||||||
|
// serve this task chain. This may require stopping the
|
||||||
|
// threads if they are already running.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void AsyncTaskChain::
|
||||||
|
set_thread_priority(ThreadPriority priority) {
|
||||||
|
MutexHolder holder(_manager->_lock);
|
||||||
|
if (_thread_priority != priority) {
|
||||||
|
do_stop_threads();
|
||||||
|
_thread_priority = priority;
|
||||||
|
|
||||||
|
if (_num_tasks != 0) {
|
||||||
|
do_start_threads();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: AsyncTaskChain::get_thread_priority
|
||||||
|
// Access: Published
|
||||||
|
// Description: Returns the priority associated with threads that
|
||||||
|
// serve this task chain.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
ThreadPriority AsyncTaskChain::
|
||||||
|
get_thread_priority() const {
|
||||||
|
MutexHolder holder(_manager->_lock);
|
||||||
|
return _thread_priority;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: AsyncTaskChain::set_frame_budget
|
||||||
|
// Access: Published
|
||||||
|
// Description: Sets the maximum amount of time per frame the tasks
|
||||||
|
// on this chain are granted for execution. If this is
|
||||||
|
// less than zero, there is no limit; if it is >= 0, it
|
||||||
|
// represents a maximum amount of time (in seconds) that
|
||||||
|
// will be used to execute tasks. If this time is
|
||||||
|
// exceeded in any one frame, the task chain will stop
|
||||||
|
// executing tasks until the next frame, as defined by
|
||||||
|
// the TaskManager's clock.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void AsyncTaskChain::
|
||||||
|
set_frame_budget(double frame_budget) {
|
||||||
|
if (_manager != (AsyncTaskManager *)NULL) {
|
||||||
|
MutexHolder holder(_manager->_lock);
|
||||||
|
_frame_budget = frame_budget;
|
||||||
|
} else {
|
||||||
|
_frame_budget = frame_budget;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: AsyncTaskChain::get_frame_budget
|
||||||
|
// Access: Published
|
||||||
|
// Description: Returns the maximum amount of time per frame the
|
||||||
|
// tasks on this chain are granted for execution. See
|
||||||
|
// set_frame_budget().
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
double AsyncTaskChain::
|
||||||
|
get_frame_budget() const {
|
||||||
|
if (_manager != (AsyncTaskManager *)NULL) {
|
||||||
|
MutexHolder holder(_manager->_lock);
|
||||||
|
return _frame_budget;
|
||||||
|
} else {
|
||||||
|
return _frame_budget;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: AsyncTaskChain::stop_threads
|
// Function: AsyncTaskChain::stop_threads
|
||||||
// Access: Published
|
// Access: Published
|
||||||
@ -618,6 +725,7 @@ finish_sort_group() {
|
|||||||
// There are no more tasks in this epoch; advance to the next epoch.
|
// There are no more tasks in this epoch; advance to the next epoch.
|
||||||
if (_tick_clock) {
|
if (_tick_clock) {
|
||||||
_manager->_clock->tick();
|
_manager->_clock->tick();
|
||||||
|
_manager->_frame_cvar.signal_all();
|
||||||
}
|
}
|
||||||
if (!_threads.empty()) {
|
if (!_threads.empty()) {
|
||||||
PStatClient::thread_tick(get_name());
|
PStatClient::thread_tick(get_name());
|
||||||
@ -705,7 +813,7 @@ do_start_threads() {
|
|||||||
}
|
}
|
||||||
strm << "_" << i;
|
strm << "_" << i;
|
||||||
PT(AsyncTaskChainThread) thread = new AsyncTaskChainThread(strm.str(), this);
|
PT(AsyncTaskChainThread) thread = new AsyncTaskChainThread(strm.str(), this);
|
||||||
if (thread->start(TP_low, true)) {
|
if (thread->start(_thread_priority, true)) {
|
||||||
_threads.push_back(thread);
|
_threads.push_back(thread);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -778,14 +886,24 @@ do_poll() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (!_active.empty() && _state != S_shutdown && _state != S_aborting) {
|
while (!_active.empty()) {
|
||||||
|
if (_state == S_shutdown || _state == S_aborting) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int frame = _manager->_clock->get_frame_count();
|
||||||
|
if (_current_frame != frame) {
|
||||||
|
_current_frame = frame;
|
||||||
|
_time_in_frame = 0.0;
|
||||||
|
}
|
||||||
|
if (_frame_budget >= 0.0 && _time_in_frame > _frame_budget) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
_current_sort = _active.front()->get_sort();
|
_current_sort = _active.front()->get_sort();
|
||||||
service_one_task(NULL);
|
service_one_task(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_state != S_shutdown && _state != S_aborting) {
|
finish_sort_group();
|
||||||
finish_sort_group();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
@ -935,6 +1053,24 @@ thread_main() {
|
|||||||
while (_chain->_state != S_shutdown && _chain->_state != S_aborting) {
|
while (_chain->_state != S_shutdown && _chain->_state != S_aborting) {
|
||||||
if (!_chain->_active.empty() &&
|
if (!_chain->_active.empty() &&
|
||||||
_chain->_active.front()->get_sort() == _chain->_current_sort) {
|
_chain->_active.front()->get_sort() == _chain->_current_sort) {
|
||||||
|
|
||||||
|
int frame = _chain->_manager->_clock->get_frame_count();
|
||||||
|
if (_chain->_current_frame != frame) {
|
||||||
|
_chain->_current_frame = frame;
|
||||||
|
_chain->_time_in_frame = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we've exceeded our frame budget, sleep until the next
|
||||||
|
// frame.
|
||||||
|
while (_chain->_frame_budget >= 0.0 && _chain->_time_in_frame > _chain->_frame_budget) {
|
||||||
|
_chain->_manager->_frame_cvar.wait();
|
||||||
|
frame = _chain->_manager->_clock->get_frame_count();
|
||||||
|
if (_chain->_current_frame != frame) {
|
||||||
|
_chain->_current_frame = frame;
|
||||||
|
_chain->_time_in_frame = 0.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
PStatTimer timer(_task_pcollector);
|
PStatTimer timer(_task_pcollector);
|
||||||
_chain->_num_busy_threads++;
|
_chain->_num_busy_threads++;
|
||||||
_chain->service_one_task(this);
|
_chain->service_one_task(this);
|
||||||
|
@ -61,13 +61,19 @@ public:
|
|||||||
~AsyncTaskChain();
|
~AsyncTaskChain();
|
||||||
|
|
||||||
PUBLISHED:
|
PUBLISHED:
|
||||||
INLINE void set_tick_clock(bool tick_clock);
|
void set_tick_clock(bool tick_clock);
|
||||||
INLINE bool get_tick_clock() const;
|
bool get_tick_clock() const;
|
||||||
|
|
||||||
BLOCKING void set_num_threads(int num_threads);
|
BLOCKING void set_num_threads(int num_threads);
|
||||||
int get_num_threads() const;
|
int get_num_threads() const;
|
||||||
int get_num_running_threads() const;
|
int get_num_running_threads() const;
|
||||||
|
|
||||||
|
BLOCKING void set_thread_priority(ThreadPriority priority);
|
||||||
|
ThreadPriority get_thread_priority() const;
|
||||||
|
|
||||||
|
void set_frame_budget(double frame_budget);
|
||||||
|
double get_frame_budget() const;
|
||||||
|
|
||||||
BLOCKING void stop_threads();
|
BLOCKING void stop_threads();
|
||||||
void start_threads();
|
void start_threads();
|
||||||
INLINE bool is_started() const;
|
INLINE bool is_started() const;
|
||||||
@ -152,7 +158,9 @@ protected:
|
|||||||
|
|
||||||
bool _tick_clock;
|
bool _tick_clock;
|
||||||
int _num_threads;
|
int _num_threads;
|
||||||
|
ThreadPriority _thread_priority;
|
||||||
Threads _threads;
|
Threads _threads;
|
||||||
|
double _frame_budget;
|
||||||
int _num_busy_threads;
|
int _num_busy_threads;
|
||||||
int _num_tasks;
|
int _num_tasks;
|
||||||
TaskHeap _active;
|
TaskHeap _active;
|
||||||
@ -161,6 +169,9 @@ protected:
|
|||||||
State _state;
|
State _state;
|
||||||
int _current_sort;
|
int _current_sort;
|
||||||
bool _needs_cleanup;
|
bool _needs_cleanup;
|
||||||
|
|
||||||
|
int _current_frame;
|
||||||
|
double _time_in_frame;
|
||||||
|
|
||||||
static PStatCollector _task_pcollector;
|
static PStatCollector _task_pcollector;
|
||||||
static PStatCollector _wait_pcollector;
|
static PStatCollector _wait_pcollector;
|
||||||
|
@ -35,7 +35,8 @@ TypeHandle AsyncTaskManager::_type_handle;
|
|||||||
AsyncTaskManager::
|
AsyncTaskManager::
|
||||||
AsyncTaskManager(const string &name) :
|
AsyncTaskManager(const string &name) :
|
||||||
Namable(name),
|
Namable(name),
|
||||||
_clock(ClockObject::get_global_clock())
|
_clock(ClockObject::get_global_clock()),
|
||||||
|
_frame_cvar(_lock)
|
||||||
{
|
{
|
||||||
// Make a default task chain.
|
// Make a default task chain.
|
||||||
do_make_task_chain("");
|
do_make_task_chain("");
|
||||||
@ -468,6 +469,10 @@ poll() {
|
|||||||
AsyncTaskChain *chain = (*tci);
|
AsyncTaskChain *chain = (*tci);
|
||||||
chain->do_poll();
|
chain->do_poll();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Just in case the clock was ticked explicitly by one of our
|
||||||
|
// polling chains.
|
||||||
|
_frame_cvar.signal_all();
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
|
@ -121,6 +121,8 @@ protected:
|
|||||||
int _num_tasks;
|
int _num_tasks;
|
||||||
TasksByName _tasks_by_name;
|
TasksByName _tasks_by_name;
|
||||||
PT(ClockObject) _clock;
|
PT(ClockObject) _clock;
|
||||||
|
|
||||||
|
ConditionVarFull _frame_cvar; // Signalled when the clock ticks.
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static TypeHandle get_class_type() {
|
static TypeHandle get_class_type() {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user