00001
00002
00003
00004
00005
00006
00007
00008
00009 static const char rcsid[] __attribute__((used)) = "$Id: TaskQueue.cpp 1230 2014-11-16 02:32:01Z sella $";
00010
00011 #include "TaskQueue.h"
00012 #include "CommonMacro.h"
00013 #include "Time.h"
00014
00015 #include <stdio.h>
00016 #include <assert.h>
00017 #include <stdlib.h>
00018 #include <unistd.h>
00019 #include <sys/time.h>
00020
00021 #include <algorithm>
00022
00023 using namespace sella::util;
00024
00025 class CompareTask {
00026 public:
00027 bool operator()(const Task::shared &t1, const Task::shared &t2) const {
00028 if (UNLIKELY(t1 == NULL)) {
00029 return true;
00030 } else if (UNLIKELY(t2 == NULL)) {
00031 return false;
00032 }
00033
00034 const timeval &tv1 = t1->getTimer();
00035 const timeval &tv2 = t2->getTimer();
00036
00037 if (UNLIKELY(timercmp(&tv1, &tv2, ==))) {
00038 return t1->getPriority() < t2->getPriority();
00039 } else if (!timerisset(&tv1)) {
00040 return false;
00041 } else if (!timerisset(&tv2)) {
00042 return true;
00043 } else if (timercmp(&tv1, &tv2, <)) {
00044 return false;
00045 }
00046 return true;
00047 }
00048 };
00049
00050 TaskQueue::TaskQueue(const size_t capacity) : libutilxx__log(::libutilxx__log) {
00051 reserve(capacity);
00052 }
00053
00054 TaskQueue::TaskQueue(Log::shared log, const size_t capacity) : libutilxx__log(log) {
00055 reserve(capacity);
00056 }
00057
00058 TaskQueue::~TaskQueue() { }
00059
00060 size_t TaskQueue::size(void) const {
00061 return heap.size();
00062 }
00063
00064 bool TaskQueue::empty(void) const {
00065 return heap.empty();
00066 }
00067
00068 void TaskQueue::clear(void) {
00069 heap.clear();
00070 }
00071
00072 Task::shared TaskQueue::top(void) const {
00073 assert(!heap.empty());
00074
00075 return heap.front();
00076 }
00077
00078 void TaskQueue::push(Task::shared &task) {
00079 assert(task.get() != NULL);
00080
00081 heap.push_back(task);
00082 push_heap(heap.begin(), heap.end(), CompareTask());
00083 }
00084
00085 void TaskQueue::push(Task::shared &task, const std::chrono::system_clock::duration &delay, int priority) {
00086 assert(task.get() != NULL);
00087
00088 task->setDelay(delay);
00089 if (priority) task->setPriority(priority);
00090
00091 push(task);
00092 }
00093
00094 void TaskQueue::push(Task::shared &task, const std::chrono::system_clock::time_point &time, int priority) {
00095 assert(task.get() != NULL);
00096
00097 task->setTimer(time);
00098 if (priority) task->setPriority(priority);
00099
00100 push(task);
00101 }
00102
00103 void TaskQueue::push(Task::shared &task, time_t sec, suseconds_t usec, int priority) {
00104 assert(task.get() != NULL);
00105
00106 task->setDelay(sec, usec);
00107 if (priority) task->setPriority(priority);
00108
00109 push(task);
00110 }
00111
00112 void TaskQueue::push(Task::shared &task, timeval &tv, int priority) {
00113 assert(task.get() != NULL);
00114
00115 task->setTimer(tv);
00116 if (priority) task->setPriority(priority);
00117
00118 push(task);
00119 }
00120
00121 bool TaskQueue::repush(Task::shared &task, const std::chrono::system_clock::duration &delay, int priority, bool strict) {
00122 timeval tv = Time::chronototv(delay);
00123
00124 return repush(task, tv, priority, strict);
00125 }
00126
00127 bool TaskQueue::repush(Task::shared &task, const std::chrono::system_clock::time_point &time, int priority, bool strict) {
00128 timeval tv = Time::chronototv(time);
00129
00130 return repush(task, tv, priority, strict);
00131 }
00132
00133 bool TaskQueue::repush(Task::shared &task, time_t sec, suseconds_t usec, int priority, bool strict) {
00134 assert(task.get() != NULL);
00135
00136 if (task.unique()) {
00137 if (strict) {
00138 return false;
00139 }
00140
00141 push(task, sec, usec, priority);
00142
00143 return true;
00144 }
00145
00146 for (auto it = heap.cbegin(); it != heap.cend(); ++it) {
00147 if (*it == task) {
00148 (*it)->setDelay(sec, usec);
00149 if (priority) (*it)->setPriority(priority);
00150 make_heap(heap.begin(), heap.end(), CompareTask());
00151
00152 return true;
00153 }
00154 }
00155
00156 if (strict) {
00157 return false;
00158 }
00159
00160 push(task, sec, usec, priority);
00161
00162 return true;
00163 }
00164
00165 bool TaskQueue::repush(Task::shared &task, timeval &tv, int priority, bool strict) {
00166 assert(task.get() != NULL);
00167
00168 if (task.unique()) {
00169 if (strict) {
00170 return false;
00171 }
00172
00173 push(task, tv, priority);
00174
00175 return true;
00176 }
00177
00178 for (auto it = heap.cbegin(); it != heap.cend(); ++it) {
00179 if (*it == task) {
00180 (*it)->setTimer(tv);
00181 if (priority) (*it)->setPriority(priority);
00182 make_heap(heap.begin(), heap.end(), CompareTask());
00183
00184 return true;
00185 }
00186 }
00187
00188 if (strict) {
00189 return false;
00190 }
00191
00192 push(task, tv, priority);
00193
00194 return true;
00195 }
00196
00197 void TaskQueue::pop(void) {
00198 assert(!heap.empty());
00199
00200 pop_heap(heap.begin(), heap.end(), CompareTask());
00201 heap.pop_back();
00202 }
00203
00204 bool TaskQueue::erase(Task::shared &task, bool firstonly) {
00205 bool found = false;
00206
00207 if (task.unique()) {
00208 return false;
00209 }
00210
00211 auto it = heap.begin();
00212 while (it != heap.end()) {
00213 if (*it == task) {
00214 it = heap.erase(it);
00215
00216 found = true;
00217 if (firstonly) break;
00218 } else {
00219 ++it;
00220 }
00221 }
00222
00223 make_heap(heap.begin(), heap.end(), CompareTask());
00224
00225 return found;
00226 }
00227
00228 bool TaskQueue::erase(void *object) {
00229 bool found = false;
00230
00231 auto it = heap.begin();
00232 while (it != heap.end()) {
00233 if ((*it)->getObject() == object) {
00234 it = heap.erase(it);
00235
00236 found = true;
00237 } else {
00238 ++it;
00239 }
00240 }
00241
00242 make_heap(heap.begin(), heap.end(), CompareTask());
00243
00244 return found;
00245 }
00246
00247 size_t TaskQueue::capacity(void) const {
00248 return heap.capacity();
00249 }
00250
00251 void TaskQueue::reserve(size_t capacity) {
00252 heap.reserve(capacity);
00253 }
00254
00255 void TaskQueue::setLog(Log::shared log) {
00256 this->libutilxx__log = log;
00257 }
00258
00259 void TaskQueue::print(void) const {
00260 Task::shared task;
00261 timeval now, timer, delay;
00262
00263 if (libutilxx__log == NULL) {
00264 return;
00265 }
00266
00267 gettimeofday(&now, NULL);
00268 INFO("[TaskQueue Heap] - now %10lu.%06lu, %zd queued", now.tv_sec, now.tv_usec, heap.size());
00269
00270 if (heap.empty()) {
00271 INFO(" heap => empty");
00272
00273 return;
00274 }
00275
00276 for (auto it = heap.begin(); it != heap.end(); ++it) {
00277 timer = (*it)->getTimer();
00278 if (timerisset(&timer)) {
00279
00280 delay.tv_sec = timer.tv_sec - now.tv_sec;
00281 delay.tv_usec = timer.tv_usec - now.tv_usec;
00282 if (delay.tv_sec > 0 && delay.tv_usec < 0) {
00283 --delay.tv_sec;
00284 delay.tv_usec += 1000000;
00285 }
00286
00287 INFO(" heap => task(%10p) obj: %10p pri: %3d timer: %10lu.%06lu delay: %4d.%d", (*it).get(), (*it)->getObject(), (*it)->getPriority(), timer.tv_sec, timer.tv_usec, (signed) delay.tv_sec, (signed) delay.tv_usec);
00288 } else {
00289 INFO(" heap => task(%10p) obj: %10p pri: %3d timer: %10lu.%06lu delay: -inf", (*it).get(), (*it)->getObject(), (*it)->getPriority(), timer.tv_sec, timer.tv_usec);
00290 }
00291 }
00292 }
00293
00294
00295
00296