Skip to content

Instantly share code, notes, and snippets.

@hamsham
Created November 18, 2014 09:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hamsham/6f9e47f4d6537065936d to your computer and use it in GitHub Desktop.
Save hamsham/6f9e47f4d6537065936d to your computer and use it in GitHub Desktop.
An (incomplete) example in setting up a Worker/Dispatcher system in C++.
/**
* An (incomplete) example in setting up a Worker/Dispatcher system.
*
* g++ -std=c++11 -Wall -Werror -Wextra -pedantic -pedantic-errors work_dispatch.cpp -o work_dispatch
*/
#include <iostream>
#include <vector>
#include <unordered_map>
/**----------------------------------------------------------------------------
*
-----------------------------------------------------------------------------*/
enum work_data_t : uint32_t {
WORK_DATA_BOOL,
WORK_DATA_CHAR,
WORK_DATA_INT,
WORK_DATA_UINT,
WORK_DATA_FLOAT,
WORK_DATA_POINTER
};
/**----------------------------------------------------------------------------
*
-----------------------------------------------------------------------------*/
template <uint32_t id>
struct task_t {
enum : uint32_t {
TASK_ID = id
};
uint32_t taskAction;
work_data_t taskType;
union {
bool bData;
char cData;
int iData;
int uData;
float fData;
void* pData;
};
};
/**----------------------------------------------------------------------------
*
-----------------------------------------------------------------------------*/
template <uint32_t id>
class worker_t;
template <uint32_t id>
class dispatcher_t;
/**----------------------------------------------------------------------------
*
-----------------------------------------------------------------------------*/
template <uint32_t id>
class worker_t {
template <uint32_t>
friend class dispatcher_t;
private:
dispatcher_t<id>* pParent = nullptr;
protected:
virtual void handleTask(const task_t<id>&) = 0;
public:
virtual ~worker_t();
void setDispatcher(dispatcher_t<id>* const pDispatcher = nullptr);
};
template <uint32_t id>
worker_t<id>::~worker_t() {
setDispatcher(nullptr);
}
template <uint32_t id>
void worker_t<id>::setDispatcher(dispatcher_t<id>* const pDispatcher) {
if (pParent == pDispatcher) {
return;
}
if (pParent != nullptr) {
pParent->unassignWorker(*this);
}
pParent = pDispatcher;
if (pParent != nullptr) {
pParent->assignWorker(*this);
}
}
/**----------------------------------------------------------------------------
*
-----------------------------------------------------------------------------*/
template <uint32_t id>
class dispatcher_t {
template <uint32_t>
friend class worker_t;
private:
typedef std::vector<task_t<id>> taskList_t;
typedef std::unordered_map<worker_t<id>*, worker_t<id>*> workerMap_t;
taskList_t tasks;
workerMap_t workers;
public:
void assignWorker(worker_t<id>& w);
void unassignWorker(worker_t<id>& w);
bool hasWorker(const worker_t<id>&) const;
bool hasWorker(worker_t<id>&);
void clearWorkers();
void dispatchTasks();
void pushTask(const task_t<id>&);
};
template <uint32_t id>
void dispatcher_t<id>::assignWorker(worker_t<id>& w) {
if (this->hasWorker(w) == false) {
worker_t<id>* const pWorker = &w;
pWorker->pParent = this;
workers[pWorker] = pWorker;
}
}
template <uint32_t id>
void dispatcher_t<id>::unassignWorker(worker_t<id>& w) {
if (workers.erase(&w) != 0) { // insurance
w.pParent = nullptr;
}
}
template <uint32_t id>
bool dispatcher_t<id>::hasWorker(const worker_t<id>& w) const {
return workers.find(&w) != workers.end();
}
template <uint32_t id>
bool dispatcher_t<id>::hasWorker(worker_t<id>& w) {
return workers.find(&w) != workers.end();
}
template <uint32_t id>
void dispatcher_t<id>::clearWorkers() {
typename workerMap_t::iterator iter = workers.begin();
while (iter != workers.end()) {
worker_t<id>* const pWorker = iter->second;
pWorker->pParent = nullptr;
++iter;
}
workers.clear();
}
template <uint32_t id>
void dispatcher_t<id>::dispatchTasks() {
const unsigned sentinel = tasks.size();
for (unsigned i = 0; i < sentinel; ++i) {
typename workerMap_t::iterator iter = workers.begin();
while (iter != workers.end()) {
worker_t<id>* const pWorker = iter->second;
pWorker->handleTask(tasks[i]);
++iter;
}
}
tasks.erase(tasks.begin(), tasks.begin()+sentinel);
}
template <uint32_t id>
void dispatcher_t<id>::pushTask(const task_t<id>& t) {
tasks.push_back(t);
}
/**----------------------------------------------------------------------------
*
-----------------------------------------------------------------------------*/
class testWorker_t final : virtual public worker_t<0> {
public:
virtual ~testWorker_t() {}
private:
virtual void handleTask(const task_t<0>&) {
std::cout << "Hello World!" << std::endl;
}
};
int main() {
task_t<0> testTask;
testWorker_t testWorker{};
dispatcher_t<0> testDispatcher{};
testDispatcher.assignWorker(testWorker);
testDispatcher.pushTask(testTask);
testDispatcher.dispatchTasks();
testDispatcher.clearWorkers();
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment