Skip to content

Instantly share code, notes, and snippets.

@jessechounard
Last active December 15, 2015 01:09
Show Gist options
  • Select an option

  • Save jessechounard/5178092 to your computer and use it in GitHub Desktop.

Select an option

Save jessechounard/5178092 to your computer and use it in GitHub Desktop.
An object to hold and perform a sequence of tasks.
#include "TaskQueue.hpp"
namespace NinjaParty
{
bool TaskQueue::IsComplete() const
{
return tasks.empty();
}
void TaskQueue::Update(float deltaSeconds)
{
if(tasks.empty())
return;
Task &task = tasks.front();
switch(task.taskType)
{
case TaskType::Action:
task.action();
tasks.pop();
break;
case TaskType::Condition:
if(task.condition())
tasks.pop();
break;
case TaskType::TimedCondition:
task.currentTime += deltaSeconds;
if(task.timedCondition(task.currentTime))
tasks.pop();
break;
}
}
TaskQueue& TaskQueue::Perform(const Action &action)
{
tasks.push(Task(action));
return *this;
}
TaskQueue& TaskQueue::Wait(float seconds)
{
return WaitUntil([=](float s){return s > seconds;});
}
TaskQueue& TaskQueue::WaitFor(const Condition &condition)
{
tasks.push(Task(condition));
return *this;
}
TaskQueue& TaskQueue::WaitUntil(const TimedCondition &timedCondition)
{
tasks.push(Task(timedCondition));
return *this;
}
TaskQueue::Task::Task(Action action)
: taskType(TaskType::Action), action(action)
{
}
TaskQueue::Task::Task(Condition condition)
: taskType(TaskType::Condition), condition(condition)
{
}
TaskQueue::Task::Task(TimedCondition timedCondition)
: taskType(TaskType::TimedCondition), timedCondition(timedCondition), currentTime(0)
{
}
TaskQueue::Task::Task(const Task &task)
: taskType(task.taskType)
{
switch(task.taskType)
{
case TaskType::Action:
action = task.action;
break;
case TaskType::Condition:
condition = task.condition;
break;
case TaskType::TimedCondition:
timedCondition = task.timedCondition;
currentTime = task.currentTime;
break;
}
}
TaskQueue::Task::~Task()
{
}
}
// This work is based heavily on Nick Gravelyn's implementation in C# for Unity3D:
// https://gist.github.com/nickgravelyn/2480060
// See also Renaud Bédard's implementation that inspired Nick's work:
// http://theinstructionlimit.com/a-replacement-for-coroutines
#ifndef NINJAPARTY_TASKQUEUE_HPP
#define NINJAPARTY_TASKQUEUE_HPP
#include <functional>
#include <queue>
namespace NinjaParty
{
typedef std::function<void ()> Action;
typedef std::function<bool ()> Condition;
typedef std::function<bool (float)> TimedCondition;
class TaskQueue
{
public:
bool IsComplete() const;
void Update(float deltaSeconds);
TaskQueue& Perform(const Action &action);
TaskQueue& Wait(float seconds);
TaskQueue& WaitFor(const Condition &condition);
TaskQueue& WaitUntil(const TimedCondition &timedCondition);
private:
enum class TaskType
{
Action,
Condition,
TimedCondition,
};
struct Task
{
Task(Action action);
Task(Condition condition);
Task(TimedCondition timedCondition);
Task(const Task &task);
~Task();
TaskType taskType;
Action action;
Condition condition;
TimedCondition timedCondition;
float currentTime;
};
std::queue<Task> tasks;
};
}
#endif//NINJAPARTY_TASKQUEUE_HPP
#include <iostream>
#include <thread>
#include "TaskQueue.hpp"
bool state = false;
NinjaParty::TaskQueue taskQueue;
void SetupToggle()
{
taskQueue.Perform([]() {std::cout << (state ? "true" : "false") << std::endl;})
.Perform([]() {state = !state;})
.Wait(1.0f)
.Perform([]() {SetupToggle();});
}
int main()
{
SetupToggle();
float totalTime = 0;
auto previousTime = std::chrono::high_resolution_clock::now();
do
{
auto currentTime = std::chrono::high_resolution_clock::now();
float deltaSeconds = std::chrono::duration_cast<std::chrono::milliseconds>
(currentTime - previousTime).count() / 1000.0f;
previousTime = currentTime;
totalTime += deltaSeconds;
taskQueue.Update(deltaSeconds);
// Sleep to simulate 60 frames per second
std::this_thread::sleep_for(std::chrono::milliseconds(16));
} while(totalTime < 10.0f);
return 0;
}
@jessechounard
Copy link
Author

Requires C++11 to compile. Tested in XCode 4.6.1

Example command-line:
clang++ -std=c++11 -stdlib=libc++ TaskManager.cpp main.cpp
./a.out

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment