-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathTask.cpp
101 lines (90 loc) · 4.69 KB
/
Task.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
#include "Task.h"
#include "Service.h"
#include "XFS/Result.h"
#include <cassert>
#include <sstream>
void Task::complete(HRESULT result) const {
XFS::Result(ReqID, serviceHandle(), result).attach((WFSIDCCARDDATA**)0).send(hWnd, WFS_EXECUTE_COMPLETE);
}
HSERVICE Task::serviceHandle() const {
return mService.handle();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
TaskContainer::~TaskContainer() {
boost::lock_guard<boost::recursive_mutex> lock(tasksMutex);
for (TaskList::iterator it = tasks.begin(); it != tasks.end(); ++it) {
(*it)->cancel();
}
tasks.clear();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
bool TaskContainer::addTask(const Task::Ptr& task) {
boost::lock_guard<boost::recursive_mutex> lock(tasksMutex);
std::pair<TaskList::iterator, bool> r = tasks.insert(task);
// Вставляться должны уникальные по ReqID элементы.
assert(r.second == true && "[TaskContainer::addTask] Adding task with existing <ServiceHandle, ReqID>");
assert(!tasks.empty() && "[TaskContainer::addTask] Task insertion was not performed");
// Получаем первый индекс -- по времени дедлайна
typedef TaskList::nth_index<0>::type Index0;
Index0& byDeadline = tasks.get<0>();
return *byDeadline.begin() == task;
}
bool TaskContainer::cancelTask(HSERVICE hService, REQUESTID ReqID) {
boost::lock_guard<boost::recursive_mutex> lock(tasksMutex);
// Получаем второй индекс -- по трекинговому номеру
typedef TaskList::nth_index<1>::type Index1;
Index1& byID = tasks.get<1>();
Index1::iterator it = byID.find(boost::make_tuple(hService, ReqID));
if (it == byID.end()) {
return false;
}
// Сигнализируем зарегистрированным слушателем о том, что задача отменена.
(*it)->cancel();
byID.erase(it);
return true;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
DWORD TaskContainer::getTimeout() const {
boost::lock_guard<boost::recursive_mutex> lock(tasksMutex);
// Если имеются задачи, то ожидаем до их таймаута, в противном случае до бесконечности.
if (!tasks.empty()) {
// Время до ближайшего таймаута.
bc::steady_clock::duration dur = (*tasks.begin())->deadline - bc::steady_clock::now();
// Преобразуем его в миллисекунды
return (DWORD)bc::duration_cast<bc::milliseconds>(dur).count();
}
return INFINITE;
}
void TaskContainer::processTimeouts(bc::steady_clock::time_point now) {
boost::lock_guard<boost::recursive_mutex> lock(tasksMutex);
// Получаем первый индекс -- по времени дедлайна
typedef TaskList::nth_index<0>::type Index0;
Index0& byDeadline = tasks.get<0>();
Index0::iterator begin = byDeadline.begin();
Index0::iterator it = begin;
for (; it != byDeadline.end(); ++it) {
// Извлекаем все задачи, чей таймаут наступил. Так как все задачи упорядочены по
// времени таймаута (чем раньше таймаут, тем ближе к голове очереди), то первая
// задача, таймаут которой еще не наступил, прерывает цепочку таймаутов.
if ((*it)->deadline > now) {
break;
}
// Сигнализируем зарегистрированным слушателем о том, что произошел таймаут.
(*it)->timeout();
}
// Удаляем завершенные таймаутом задачи.
byDeadline.erase(begin, it);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void TaskContainer::notifyChanges(const SCARD_READERSTATE& state, bool deviceChange) {
{XFS::Logger() << "TaskContainer::notifyChanges";}
boost::lock_guard<boost::recursive_mutex> lock(tasksMutex);
for (TaskList::iterator it = tasks.begin(); it != tasks.end();) {
// Если задача ожидала этого события, то удаляем ее из списка.
if ((*it)->match(state, deviceChange)) {
it = tasks.erase(it);
continue;
}
++it;
}
}