-
Notifications
You must be signed in to change notification settings - Fork 0
/
task_runner.cpp
117 lines (92 loc) · 2.88 KB
/
task_runner.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
// Task Runner
// Problem:
// Given a list of tasks, their priorities, and their dependencies (which tasks must come before others),
// determine the order to write tasks
// Solution:
// Make a graph to represent dependencies, each vertex (task) is pointed to by its dependencies
// Add all tasks with no dependencies onto a priority queue
// While prioritiy queue is not empty
// Get max task T of the queue. Add T to taskList.
// For every task U that depends on T, remove T from U's depenency list.
// If U's dependency list is now empty, add U to the priority queue.
// Finally print out / return taskList which represents the tasks in the order they should be performed
#include <iostream>
#include <vector>
#include <set>
#include <queue>
#include <unordered_map>
#include <unordered_set>
using namespace std;
class TaskRunner {
public:
void addTask(int taskID, int priority);
void addDependency(int before, int after); // 'before' must be run before 'after'
void run();
private:
struct Task {
int id;
int priority;
set<int> neededTasks; // all the tasks I depend on
set<int> nextTasks; // all the tasks that depend on me
bool operator()(Task const &t1, Task const &t2) const
{
return t1.priority < t2.priority;
}
};
unordered_map<int, Task> tasks;
};
int main ()
{
TaskRunner tr;
tr.addTask(1, 2);
tr.addTask(2, 4);
tr.addTask(3, 5);
tr.addTask(4, 10);
tr.addTask(5, 1);
tr.addDependency(1, 3);
tr.addDependency(1, 4);
tr.addDependency(5, 2);
cout << "Run tasks in this order" << endl;
tr.run();
}
void TaskRunner::addTask(int taskID, int priority)
{
Task t;
t.id = taskID;
t.priority = priority;
tasks[taskID] = t;
}
void TaskRunner::addDependency(int before, int after)
{
tasks[before].nextTasks.insert(after);
tasks[after].neededTasks.insert(before);
}
void TaskRunner::run()
{
vector<int> taskList;
priority_queue<Task, vector<Task>, Task> q;
// enqueue every reachable task
for (auto t = tasks.begin(); t != tasks.end(); t++) {
if (t->second.neededTasks.empty()) {
q.push(t->second);
}
}
while (!q.empty()) {
Task t = q.top();
q.pop();
taskList.push_back(t.id);
// for every task that depended on me
for (auto next = t.nextTasks.begin(); next != t.nextTasks.end(); next++) {
int taskID = *next;
// unmark me as a dependency off that task
tasks[taskID].neededTasks.erase(t.id);
// if that task now has no uncleared dependencies, enqueue task
if (tasks[taskID].neededTasks.size() == 0) {
q.push(tasks[taskID]);
}
}
}
for (int i = 0; i < taskList.size(); i++) {
cout << taskList[i] << endl;
}
}