Added Task Scheduler
Former-commit-id: ac37f749ae78f364db3d3edfabc8221802579989
This commit is contained in:
parent
023e497777
commit
ef567bd223
|
|
@ -0,0 +1,29 @@
|
|||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine - Core module"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef NAZARA_TASKSCHEDULER_HPP
|
||||
#define NAZARA_TASKSCHEDULER_HPP
|
||||
|
||||
#include <Nazara/Prerequesites.hpp>
|
||||
#include <Nazara/Core/Functor.hpp>
|
||||
|
||||
class NAZARA_API NzTaskScheduler
|
||||
{
|
||||
public:
|
||||
template<typename F> static void AddTask(F function);
|
||||
template<typename F, typename... Args> static void AddTask(F function, Args... args);
|
||||
template<typename C> static void AddTask(void (C::*function)(), C* object);
|
||||
static bool Initialize();
|
||||
static void Uninitialize();
|
||||
static void WaitForTasks();
|
||||
|
||||
private:
|
||||
static void AddTaskFunctor(NzFunctor* taskFunctor);
|
||||
};
|
||||
|
||||
#include <Nazara/Core/TaskScheduler.inl>
|
||||
|
||||
#endif // NAZARA_TASKSCHEDULER_HPP
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine - Core module"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
template<typename F>
|
||||
void NzTaskScheduler::AddTask(F function)
|
||||
{
|
||||
AddTaskFunctor(new NzFunctorWithoutArgs<F>(function));
|
||||
}
|
||||
|
||||
template<typename F, typename... Args>
|
||||
void NzTaskScheduler::AddTask(F function, Args... args)
|
||||
{
|
||||
AddTaskFunctor(new NzFunctorWithArgs<F, Args...>(function, args...));
|
||||
}
|
||||
|
||||
template<typename C>
|
||||
void NzTaskScheduler::AddTask(void (C::*function)(), C* object)
|
||||
{
|
||||
AddTaskFunctor(new NzMemberWithoutArgs<C>(function, object));
|
||||
}
|
||||
|
||||
#include <Nazara/Core/DebugOff.hpp>
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine - Renderer module"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef NAZARA_SHADERBUILDER_HPP
|
||||
#define NAZARA_SHADERBUILDER_HPP
|
||||
|
||||
#include <Nazara/Prerequesites.hpp>
|
||||
#include <Nazara/Renderer/Shader.hpp>
|
||||
|
||||
class NAZARA_API NzShaderBuilder
|
||||
{
|
||||
public:
|
||||
NzShaderBuilder() = default;
|
||||
NzShaderBuilder(nzShaderLanguage language);
|
||||
~NzShaderBuilder();
|
||||
|
||||
bool Create(nzShaderLanguage language);
|
||||
void Destroy();
|
||||
|
||||
bool IsValid();
|
||||
|
||||
void SetDeferred(bool deferredRendering);
|
||||
void SetDiffuseMapping(bool diffuseMapping);
|
||||
void SetInstancing(bool instancing);
|
||||
void SetLighting(bool lighting);
|
||||
void SetNormalMapping(bool normalMapping);
|
||||
void SetParallaxMapping(bool parallaxMapping);
|
||||
|
||||
private:
|
||||
NzShaderImpl* m_impl = nullptr;
|
||||
};
|
||||
|
||||
#endif // NAZARA_SHADER_HPP
|
||||
|
|
@ -0,0 +1,150 @@
|
|||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine - Core module"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
|
||||
|
||||
#include <Nazara/Core/TaskScheduler.hpp>
|
||||
#include <Nazara/Core/ConditionVariable.hpp>
|
||||
#include <Nazara/Core/Error.hpp>
|
||||
#include <Nazara/Core/LockGuard.hpp>
|
||||
#include <Nazara/Core/Mutex.hpp>
|
||||
#include <Nazara/Core/Thread.hpp>
|
||||
#include <queue>
|
||||
#include <vector>
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
namespace
|
||||
{
|
||||
struct TaskSchedulerImpl
|
||||
{
|
||||
std::queue<NzFunctor*> tasks;
|
||||
std::vector<NzThread*> workers;
|
||||
NzConditionVariable waiterConditionVariable;
|
||||
NzConditionVariable workerConditionVariable;
|
||||
NzMutex taskMutex;
|
||||
NzMutex waiterConditionVariableMutex;
|
||||
NzMutex workerConditionVariableMutex;
|
||||
volatile bool running = true;
|
||||
};
|
||||
|
||||
TaskSchedulerImpl* s_impl = nullptr;
|
||||
|
||||
void WorkerFunc()
|
||||
{
|
||||
do
|
||||
{
|
||||
NzFunctor* task;
|
||||
{
|
||||
NzLockGuard lock(s_impl->taskMutex);
|
||||
if (!s_impl->tasks.empty())
|
||||
{
|
||||
task = s_impl->tasks.front();
|
||||
s_impl->tasks.pop();
|
||||
}
|
||||
else
|
||||
task = nullptr;
|
||||
}
|
||||
|
||||
// Avons-nous une tâche ?
|
||||
if (task)
|
||||
task->Run(); // Chouette ! Allons travailler gaiement
|
||||
else
|
||||
{
|
||||
// On peut signaler à tout le monde qu'il n'y a plus de tâches
|
||||
s_impl->waiterConditionVariableMutex.Lock();
|
||||
s_impl->waiterConditionVariable.SignalAll();
|
||||
s_impl->waiterConditionVariableMutex.Unlock();
|
||||
|
||||
// Dans le cas contraire, nous attendons qu'une nouvelle tâche arrive
|
||||
s_impl->workerConditionVariableMutex.Lock();
|
||||
s_impl->workerConditionVariable.Wait(&s_impl->workerConditionVariableMutex);
|
||||
s_impl->workerConditionVariableMutex.Unlock();
|
||||
}
|
||||
}
|
||||
while (s_impl->running);
|
||||
}
|
||||
}
|
||||
|
||||
bool NzTaskScheduler::Initialize()
|
||||
{
|
||||
if (s_impl)
|
||||
return true; // Déjà initialisé
|
||||
|
||||
s_impl = new TaskSchedulerImpl;
|
||||
|
||||
unsigned int workerCount = NzThread::HardwareConcurrency();
|
||||
for (unsigned int i = 0; i < workerCount; ++i)
|
||||
{
|
||||
NzThread* thread = new NzThread(WorkerFunc);
|
||||
s_impl->workers.push_back(thread);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void NzTaskScheduler::Uninitialize()
|
||||
{
|
||||
if (s_impl)
|
||||
{
|
||||
s_impl->running = false;
|
||||
|
||||
s_impl->workerConditionVariableMutex.Lock();
|
||||
s_impl->workerConditionVariable.SignalAll();
|
||||
s_impl->workerConditionVariableMutex.Unlock();
|
||||
|
||||
for (NzThread* thread : s_impl->workers)
|
||||
{
|
||||
thread->Join();
|
||||
delete thread;
|
||||
}
|
||||
|
||||
delete s_impl;
|
||||
}
|
||||
}
|
||||
|
||||
void NzTaskScheduler::AddTaskFunctor(NzFunctor* taskFunctor)
|
||||
{
|
||||
#ifdef NAZARA_CORE_SAFE
|
||||
if (!s_impl)
|
||||
{
|
||||
NazaraError("Task scheduler is not initialized");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
{
|
||||
NzLockGuard lock(s_impl->taskMutex);
|
||||
s_impl->tasks.push(taskFunctor);
|
||||
}
|
||||
|
||||
s_impl->workerConditionVariableMutex.Lock();
|
||||
s_impl->workerConditionVariable.Signal();
|
||||
s_impl->workerConditionVariableMutex.Unlock();
|
||||
}
|
||||
|
||||
void NzTaskScheduler::WaitForTasks()
|
||||
{
|
||||
#ifdef NAZARA_CORE_SAFE
|
||||
if (!s_impl)
|
||||
{
|
||||
NazaraError("Task scheduler is not initialized");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
s_impl->taskMutex.Lock();
|
||||
// Tout d'abord, il y a-t-il des tâches en attente ?
|
||||
if (s_impl->tasks.empty())
|
||||
{
|
||||
s_impl->taskMutex.Unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
// On verrouille d'abord la mutex entourant le signal (Pour ne pas perdre le signal en chemin)
|
||||
s_impl->waiterConditionVariableMutex.Lock();
|
||||
// Et ensuite seulement on déverrouille la mutex des tâches
|
||||
s_impl->taskMutex.Unlock();
|
||||
s_impl->waiterConditionVariable.Wait(&s_impl->waiterConditionVariableMutex);
|
||||
s_impl->waiterConditionVariableMutex.Unlock();
|
||||
}
|
||||
Loading…
Reference in New Issue