mirror of
https://github.com/wolfpld/tracy.git
synced 2024-11-27 00:04:35 +00:00
d6c5d3f6db
Everything can be confined to a single thread that does job dispatch, and then waits for the jobs to finish. TaskDispatch has always executed outstanding work during this wait, so no workers are needed.
89 lines
2.0 KiB
C++
89 lines
2.0 KiB
C++
#include <assert.h>
|
|
#include <stdio.h>
|
|
|
|
#include "../public/common/TracySystem.hpp"
|
|
#include "TracyTaskDispatch.hpp"
|
|
|
|
namespace tracy
|
|
{
|
|
|
|
TaskDispatch::TaskDispatch( size_t workers, const char* name )
|
|
: m_exit( false )
|
|
, m_jobs( 0 )
|
|
{
|
|
m_workers.reserve( workers );
|
|
for( size_t i=0; i<workers; i++ )
|
|
{
|
|
m_workers.emplace_back( std::thread( [this, name, i]{ SetName( name, i ); Worker(); } ) );
|
|
}
|
|
}
|
|
|
|
TaskDispatch::~TaskDispatch()
|
|
{
|
|
m_exit.store( true, std::memory_order_release );
|
|
m_queueLock.lock();
|
|
m_cvWork.notify_all();
|
|
m_queueLock.unlock();
|
|
|
|
for( auto& worker : m_workers )
|
|
{
|
|
worker.join();
|
|
}
|
|
}
|
|
|
|
void TaskDispatch::Queue( const std::function<void(void)>& f )
|
|
{
|
|
std::lock_guard<std::mutex> lock( m_queueLock );
|
|
m_queue.emplace_back( f );
|
|
m_cvWork.notify_one();
|
|
}
|
|
|
|
void TaskDispatch::Queue( std::function<void(void)>&& f )
|
|
{
|
|
std::lock_guard<std::mutex> lock( m_queueLock );
|
|
m_queue.emplace_back( std::move( f ) );
|
|
m_cvWork.notify_one();
|
|
}
|
|
|
|
void TaskDispatch::Sync()
|
|
{
|
|
std::unique_lock<std::mutex> lock( m_queueLock );
|
|
while( !m_queue.empty() )
|
|
{
|
|
auto f = m_queue.back();
|
|
m_queue.pop_back();
|
|
lock.unlock();
|
|
f();
|
|
lock.lock();
|
|
}
|
|
m_cvJobs.wait( lock, [this]{ return m_jobs == 0; } );
|
|
}
|
|
|
|
void TaskDispatch::Worker()
|
|
{
|
|
for(;;)
|
|
{
|
|
std::unique_lock<std::mutex> lock( m_queueLock );
|
|
m_cvWork.wait( lock, [this]{ return !m_queue.empty() || m_exit.load( std::memory_order_acquire ); } );
|
|
if( m_exit.load( std::memory_order_acquire ) ) return;
|
|
auto f = m_queue.back();
|
|
m_queue.pop_back();
|
|
m_jobs++;
|
|
lock.unlock();
|
|
f();
|
|
lock.lock();
|
|
m_jobs--;
|
|
if( m_jobs == 0 && m_queue.empty() ) m_cvJobs.notify_one();
|
|
lock.unlock();
|
|
}
|
|
}
|
|
|
|
void TaskDispatch::SetName( const char* name, size_t num )
|
|
{
|
|
char tmp[128];
|
|
snprintf( tmp, sizeof( tmp ), "%s #%zu", name, num );
|
|
SetThreadName( tmp );
|
|
}
|
|
|
|
}
|