Rename Nz::Functor to Nz::AbstractFunctor
This commit is contained in:
parent
da49b39465
commit
f2e77fb8a5
|
|
@ -13,15 +13,15 @@
|
||||||
|
|
||||||
namespace Nz
|
namespace Nz
|
||||||
{
|
{
|
||||||
struct Functor
|
struct AbstractFunctor
|
||||||
{
|
{
|
||||||
virtual ~Functor() {}
|
virtual ~AbstractFunctor() {}
|
||||||
|
|
||||||
virtual void Run() = 0;
|
virtual void Run() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename F>
|
template<typename F>
|
||||||
struct FunctorWithoutArgs : Functor
|
struct FunctorWithoutArgs : AbstractFunctor
|
||||||
{
|
{
|
||||||
FunctorWithoutArgs(F func);
|
FunctorWithoutArgs(F func);
|
||||||
|
|
||||||
|
|
@ -32,7 +32,7 @@ namespace Nz
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename F, typename... Args>
|
template<typename F, typename... Args>
|
||||||
struct FunctorWithArgs : Functor
|
struct FunctorWithArgs : AbstractFunctor
|
||||||
{
|
{
|
||||||
FunctorWithArgs(F func, Args&&... args);
|
FunctorWithArgs(F func, Args&&... args);
|
||||||
|
|
||||||
|
|
@ -44,7 +44,7 @@ namespace Nz
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename C>
|
template<typename C>
|
||||||
struct MemberWithoutArgs : Functor
|
struct MemberWithoutArgs : AbstractFunctor
|
||||||
{
|
{
|
||||||
MemberWithoutArgs(void (C::*func)(), C* object);
|
MemberWithoutArgs(void (C::*func)(), C* object);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ namespace Nz
|
||||||
static void WaitForTasks();
|
static void WaitForTasks();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static void AddTaskFunctor(Functor* taskFunctor);
|
static void AddTaskFunctor(AbstractFunctor* taskFunctor);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,10 +32,10 @@ namespace Nz
|
||||||
template<typename F>
|
template<typename F>
|
||||||
void TransientResources::PushReleaseCallback(F&& callback)
|
void TransientResources::PushReleaseCallback(F&& callback)
|
||||||
{
|
{
|
||||||
using Functor = ReleasableLambda<std::remove_cv_t<std::remove_reference_t<F>>>;
|
using ReleaseFunctor = ReleasableLambda<std::remove_cv_t<std::remove_reference_t<F>>>;
|
||||||
|
|
||||||
constexpr std::size_t functorSize = sizeof(Functor);
|
constexpr std::size_t functorSize = sizeof(ReleaseFunctor);
|
||||||
constexpr std::size_t functorAlignment = alignof(Functor);
|
constexpr std::size_t functorAlignment = alignof(ReleaseFunctor);
|
||||||
|
|
||||||
// Try to minimize lost space
|
// Try to minimize lost space
|
||||||
struct
|
struct
|
||||||
|
|
@ -77,7 +77,7 @@ namespace Nz
|
||||||
Block& targetBlock = *bestBlock.block;
|
Block& targetBlock = *bestBlock.block;
|
||||||
targetBlock.resize(bestBlock.alignedOffset + functorSize);
|
targetBlock.resize(bestBlock.alignedOffset + functorSize);
|
||||||
|
|
||||||
Functor* releasable = reinterpret_cast<Functor*>(&targetBlock[bestBlock.alignedOffset]);
|
ReleaseFunctor* releasable = reinterpret_cast<ReleaseFunctor*>(&targetBlock[bestBlock.alignedOffset]);
|
||||||
PlacementNew(releasable, std::forward<F>(callback));
|
PlacementNew(releasable, std::forward<F>(callback));
|
||||||
|
|
||||||
m_releaseQueue.push_back(releasable);
|
m_releaseQueue.push_back(releasable);
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,7 @@ namespace Nz
|
||||||
return s_workerCount > 0;
|
return s_workerCount > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TaskSchedulerImpl::Run(Functor** tasks, unsigned int count)
|
void TaskSchedulerImpl::Run(AbstractFunctor** tasks, unsigned int count)
|
||||||
{
|
{
|
||||||
// On s'assure que des tâches ne sont pas déjà en cours
|
// On s'assure que des tâches ne sont pas déjà en cours
|
||||||
Wait();
|
Wait();
|
||||||
|
|
@ -82,7 +82,7 @@ namespace Nz
|
||||||
// On réveille les threads pour qu'ils sortent de la boucle et terminent.
|
// On réveille les threads pour qu'ils sortent de la boucle et terminent.
|
||||||
pthread_mutex_lock(&s_mutexQueue);
|
pthread_mutex_lock(&s_mutexQueue);
|
||||||
// On commence par vider la queue et demander qu'ils s'arrêtent.
|
// On commence par vider la queue et demander qu'ils s'arrêtent.
|
||||||
std::queue<Functor*> emptyQueue;
|
std::queue<AbstractFunctor*> emptyQueue;
|
||||||
std::swap(s_tasks, emptyQueue);
|
std::swap(s_tasks, emptyQueue);
|
||||||
s_shouldFinish = true;
|
s_shouldFinish = true;
|
||||||
pthread_cond_broadcast(&s_cvNotEmpty);
|
pthread_cond_broadcast(&s_cvNotEmpty);
|
||||||
|
|
@ -114,9 +114,9 @@ namespace Nz
|
||||||
Wait();
|
Wait();
|
||||||
}
|
}
|
||||||
|
|
||||||
Functor* TaskSchedulerImpl::PopQueue()
|
AbstractFunctor* TaskSchedulerImpl::PopQueue()
|
||||||
{
|
{
|
||||||
Functor* task = nullptr;
|
AbstractFunctor* task = nullptr;
|
||||||
|
|
||||||
pthread_mutex_lock(&s_mutexQueue);
|
pthread_mutex_lock(&s_mutexQueue);
|
||||||
|
|
||||||
|
|
@ -153,7 +153,7 @@ namespace Nz
|
||||||
// On quitte s'il doit terminer.
|
// On quitte s'il doit terminer.
|
||||||
while (!s_shouldFinish)
|
while (!s_shouldFinish)
|
||||||
{
|
{
|
||||||
Functor* task = PopQueue();
|
AbstractFunctor* task = PopQueue();
|
||||||
|
|
||||||
if (task)
|
if (task)
|
||||||
{
|
{
|
||||||
|
|
@ -184,7 +184,7 @@ namespace Nz
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::queue<Functor*> TaskSchedulerImpl::s_tasks;
|
std::queue<AbstractFunctor*> TaskSchedulerImpl::s_tasks;
|
||||||
std::unique_ptr<pthread_t[]> TaskSchedulerImpl::s_threads;
|
std::unique_ptr<pthread_t[]> TaskSchedulerImpl::s_threads;
|
||||||
std::atomic<bool> TaskSchedulerImpl::s_isDone;
|
std::atomic<bool> TaskSchedulerImpl::s_isDone;
|
||||||
std::atomic<bool> TaskSchedulerImpl::s_isWaiting;
|
std::atomic<bool> TaskSchedulerImpl::s_isWaiting;
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@
|
||||||
|
|
||||||
namespace Nz
|
namespace Nz
|
||||||
{
|
{
|
||||||
struct Functor;
|
struct AbstractFunctor;
|
||||||
|
|
||||||
class TaskSchedulerImpl
|
class TaskSchedulerImpl
|
||||||
{
|
{
|
||||||
|
|
@ -36,16 +36,16 @@ namespace Nz
|
||||||
|
|
||||||
static bool Initialize(unsigned int workerCount);
|
static bool Initialize(unsigned int workerCount);
|
||||||
static bool IsInitialized();
|
static bool IsInitialized();
|
||||||
static void Run(Functor** tasks, unsigned int count);
|
static void Run(AbstractFunctor** tasks, unsigned int count);
|
||||||
static void Uninitialize();
|
static void Uninitialize();
|
||||||
static void WaitForTasks();
|
static void WaitForTasks();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static Functor* PopQueue();
|
static AbstractFunctor* PopQueue();
|
||||||
static void Wait();
|
static void Wait();
|
||||||
static void* WorkerProc(void* userdata);
|
static void* WorkerProc(void* userdata);
|
||||||
|
|
||||||
static std::queue<Functor*> s_tasks;
|
static std::queue<AbstractFunctor*> s_tasks;
|
||||||
static std::unique_ptr<pthread_t[]> s_threads;
|
static std::unique_ptr<pthread_t[]> s_threads;
|
||||||
static std::atomic<bool> s_isDone;
|
static std::atomic<bool> s_isDone;
|
||||||
static std::atomic<bool> s_isWaiting;
|
static std::atomic<bool> s_isWaiting;
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ namespace Nz
|
||||||
{
|
{
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
std::vector<Functor*> s_pendingWorks;
|
std::vector<AbstractFunctor*> s_pendingWorks;
|
||||||
unsigned int s_workerCount = 0;
|
unsigned int s_workerCount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -130,7 +130,7 @@ namespace Nz
|
||||||
* \remark A task containing a call on this class is undefined behaviour
|
* \remark A task containing a call on this class is undefined behaviour
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void TaskScheduler::AddTaskFunctor(Functor* taskFunctor)
|
void TaskScheduler::AddTaskFunctor(AbstractFunctor* taskFunctor)
|
||||||
{
|
{
|
||||||
if (!Initialize())
|
if (!Initialize())
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,7 @@ namespace Nz
|
||||||
return s_workerCount > 0;
|
return s_workerCount > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TaskSchedulerImpl::Run(Functor** tasks, std::size_t count)
|
void TaskSchedulerImpl::Run(AbstractFunctor** tasks, std::size_t count)
|
||||||
{
|
{
|
||||||
// On s'assure que des tâches ne sont pas déjà en cours
|
// On s'assure que des tâches ne sont pas déjà en cours
|
||||||
WaitForMultipleObjects(s_workerCount, &s_doneEvents[0], true, INFINITE);
|
WaitForMultipleObjects(s_workerCount, &s_doneEvents[0], true, INFINITE);
|
||||||
|
|
@ -104,7 +104,7 @@ namespace Nz
|
||||||
|
|
||||||
EnterCriticalSection(&worker.queueMutex);
|
EnterCriticalSection(&worker.queueMutex);
|
||||||
|
|
||||||
std::queue<Functor*> emptyQueue;
|
std::queue<AbstractFunctor*> emptyQueue;
|
||||||
std::swap(worker.queue, emptyQueue); // Et on vide la queue (merci std::swap)
|
std::swap(worker.queue, emptyQueue); // Et on vide la queue (merci std::swap)
|
||||||
|
|
||||||
LeaveCriticalSection(&worker.queueMutex);
|
LeaveCriticalSection(&worker.queueMutex);
|
||||||
|
|
@ -145,7 +145,7 @@ namespace Nz
|
||||||
WaitForMultipleObjects(s_workerCount, &s_doneEvents[0], true, INFINITE);
|
WaitForMultipleObjects(s_workerCount, &s_doneEvents[0], true, INFINITE);
|
||||||
}
|
}
|
||||||
|
|
||||||
Functor* TaskSchedulerImpl::StealTask(std::size_t workerID)
|
AbstractFunctor* TaskSchedulerImpl::StealTask(std::size_t workerID)
|
||||||
{
|
{
|
||||||
bool shouldRetry;
|
bool shouldRetry;
|
||||||
do
|
do
|
||||||
|
|
@ -162,7 +162,7 @@ namespace Nz
|
||||||
// Ce worker a-t-il encore des tâches dans sa file d'attente ?
|
// Ce worker a-t-il encore des tâches dans sa file d'attente ?
|
||||||
if (worker.workCount > 0)
|
if (worker.workCount > 0)
|
||||||
{
|
{
|
||||||
Functor* task = nullptr;
|
AbstractFunctor* task = nullptr;
|
||||||
|
|
||||||
// Est-ce qu'il utilise la queue maintenant ?
|
// Est-ce qu'il utilise la queue maintenant ?
|
||||||
if (TryEnterCriticalSection(&worker.queueMutex))
|
if (TryEnterCriticalSection(&worker.queueMutex))
|
||||||
|
|
@ -203,7 +203,7 @@ namespace Nz
|
||||||
|
|
||||||
while (worker.running)
|
while (worker.running)
|
||||||
{
|
{
|
||||||
Functor* task = nullptr;
|
AbstractFunctor* task = nullptr;
|
||||||
|
|
||||||
if (worker.workCount > 0) // Permet d'éviter d'entrer inutilement dans une section critique
|
if (worker.workCount > 0) // Permet d'éviter d'entrer inutilement dans une section critique
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -24,18 +24,18 @@ namespace Nz
|
||||||
|
|
||||||
static bool Initialize(std::size_t workerCount);
|
static bool Initialize(std::size_t workerCount);
|
||||||
static bool IsInitialized();
|
static bool IsInitialized();
|
||||||
static void Run(Functor** tasks, std::size_t count);
|
static void Run(AbstractFunctor** tasks, std::size_t count);
|
||||||
static void Uninitialize();
|
static void Uninitialize();
|
||||||
static void WaitForTasks();
|
static void WaitForTasks();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static Functor* StealTask(std::size_t workerID);
|
static AbstractFunctor* StealTask(std::size_t workerID);
|
||||||
static unsigned int __stdcall WorkerProc(void* userdata);
|
static unsigned int __stdcall WorkerProc(void* userdata);
|
||||||
|
|
||||||
struct Worker
|
struct Worker
|
||||||
{
|
{
|
||||||
std::atomic_size_t workCount;
|
std::atomic_size_t workCount;
|
||||||
std::queue<Functor*> queue;
|
std::queue<AbstractFunctor*> queue;
|
||||||
CRITICAL_SECTION queueMutex;
|
CRITICAL_SECTION queueMutex;
|
||||||
HANDLE wakeEvent;
|
HANDLE wakeEvent;
|
||||||
volatile bool running;
|
volatile bool running;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue