first iteration of the Provider and Task classes

This commit is contained in:
Anselme 2017-02-01 17:44:54 +01:00
parent 8b42ba055b
commit 0c54d5e37b
5 changed files with 239 additions and 1 deletions

View File

@ -5,7 +5,7 @@ set(VERSION_MAJOR 0)
set(VERSION_MINOR 1) set(VERSION_MINOR 1)
# choose source file # choose source file
file(GLOB LIB_SRC_LIST src/property.cpp src/serializable.cpp src/serializationmanager.cpp) file(GLOB LIB_SRC_LIST src/property.cpp src/serializable.cpp src/serializationmanager.cpp src/taskmanager.cpp src/provider.cpp)
file(GLOB LIB_HEAD_LIST src/*.h) file(GLOB LIB_HEAD_LIST src/*.h)
set(EXEC_SRC_LIST src/main.cpp) set(EXEC_SRC_LIST src/main.cpp)

2
src/provider.cpp Normal file
View File

@ -0,0 +1,2 @@
#include "provider.h"

41
src/provider.h Normal file
View File

@ -0,0 +1,41 @@
#ifndef PROVIDER_H
#define PROVIDER_H
#include "serializable.h"
#include "taskmanager.h"
class AbstractProvider : public Serializable
{
public:
virtual Task* getTask() = 0;
};
template <typename T>
class Provider : public AbstractProvider
{
protected:
struct ProviderTask : public Task
{
T* m_object = nullptr;
int m_progress = 0;
int m_flags;
std::string m_providerName;
/**
* @brief This should be overloaded
*/
virtual void performTask() { m_object = new T(); m_progress = 1; }
virtual int getProgressInt() { }
virtual Task::TaskTypeFlags getFlags() { return m_flags; }
virtual const std::string &getLabel() { return m_providerName; }
};
ProviderTask m_task;
public:
virtual Task* getTask() { return (Task*)&m_task; }
virtual T* provide() { return m_task.m_object; }
};
#endif // PROVIDER_H

129
src/taskmanager.cpp Normal file
View File

@ -0,0 +1,129 @@
#include "taskmanager.h"
// TASK THREAD
TaskThread::~TaskThread()
{
waitUntilOver();
for(std::thread * t : m_threads)
delete t;
}
void TaskThread::addTask(Task* task)
{
m_tasks.push_back(task);
++m_totalTasks;
}
void TaskThread::start(int nbThreads)
{
for(int i=0; i<nbThreads; ++i)
{
std::thread *thread = new std::thread(&TaskThread::run, this, i);
m_currentTasks.push_back(nullptr);
m_threads.push_back(thread);
}
}
void TaskThread::run(int id)
{
m_mutex.lock();
while(!m_tasks.empty())
{
m_currentTasks[id] = m_tasks.front();
m_tasks.pop_front();
m_mutex.unlock();
m_currentTasks[id]->performTask();
m_mutex.lock();
delete m_currentTasks[id];
m_currentTasks[id] = nullptr;
++m_tasksPerformed;
}
m_mutex.unlock();
}
void TaskThread::waitUntilOver()
{
for(std::thread * t : m_threads)
t->join();
}
bool TaskThread::isOver()
{
return m_tasksPerformed == m_totalTasks;
}
float TaskThread::getProgressProportion()
{
float progress = 1.f;
m_mutex.lock();
if(!isOver())
{
progress = m_tasksPerformed;
for(Task* t : m_currentTasks)
{
if(t != nullptr)
progress += t->getProgressProportion();
}
progress /= m_totalTasks;
}
m_mutex.unlock();
return progress;
}
// TASK MANAGER
void TaskManager::addTask(Task* task)
{
int flags = task->getFlags();
if(flags & Task::GPU)
m_gpuTasks.addTask(task);
else if(flags & Task::HDD)
m_hddTasks.addTask(task);
else if(flags & Task::NET)
m_netTasks.addTask(task);
else
m_cpuTasks.addTask(task);
}
void TaskManager::start()
{
m_hddTasks.start(1); // Reading multiple files simultaneously makes no sense
m_cpuTasks.start(4);
m_gpuTasks.start(1); // GPU tasks must be regouped on only one thread to easily have access to an OpenGL context
m_netTasks.start(4);
}
void TaskManager::waitUntilOver()
{
m_hddTasks.waitUntilOver();
m_cpuTasks.waitUntilOver();
m_gpuTasks.waitUntilOver();
m_netTasks.waitUntilOver();
}
bool TaskManager::isOver()
{
return m_hddTasks.isOver()
&& m_cpuTasks.isOver()
&& m_gpuTasks.isOver()
&& m_netTasks.isOver();
}
float TaskManager::getProgress(int flags)
{
float progress = 0;
int nbTypes = 0;
if(flags & Task::GPU)
progress += m_gpuTasks.getProgressProportion(), ++nbTypes;
else if(flags & Task::HDD)
progress += m_hddTasks.getProgressProportion(), ++nbTypes;
else if(flags & Task::NET)
progress += m_netTasks.getProgressProportion(), ++nbTypes;
else
progress += m_cpuTasks.getProgressProportion(), ++nbTypes;
if(nbTypes != 0)
return progress/nbTypes;
else
return 1.f;
}

66
src/taskmanager.h Normal file
View File

@ -0,0 +1,66 @@
#ifndef TASKMANAGER_H
#define TASKMANAGER_H
#include <string>
#include <list>
#include <vector>
#include <thread>
#include <mutex>
class Task
{
public:
enum TaskTypeFlags
{
HDD, // saving of loading to the file system
CPU, // computing something
GPU, // computing something on the GPU or transferring data between the RAM and the GPU RAM
NET // sending or receiving from the network
};
virtual void performTask() = 0;
virtual int getProgressInt() = 0;
virtual int getProgressTotal() { return 1; }
virtual float getProgressProportion() { return float(getProgressInt())/float(getProgressTotal()); }
virtual TaskTypeFlags getFlags() = 0;
virtual const std::string &getLabel() = 0;
};
class TaskThread
{
std::list<Task*> m_tasks;
std::vector<std::thread*> m_threads;
std::vector<Task*> m_currentTasks;
std::mutex m_mutex;
int m_tasksPerformed;
int m_totalTasks;
void run(int id);
public:
~TaskThread();
void addTask(Task* task);
void start(int nbThreads = 1);
void waitUntilOver();
bool isOver();
float getProgressProportion();
};
class TaskManager
{
TaskThread m_hddTasks;
TaskThread m_cpuTasks;
TaskThread m_gpuTasks;
TaskThread m_netTasks;
public:
void addTask(Task* task);
void start();
void waitUntilOver();
bool isOver();
float getProgress(int flags = Task::CPU | Task::GPU | Task::HDD | Task::NET);
};
#endif // TASKMANAGER_H