summaryrefslogtreecommitdiff
path: root/src/mongo/scripting/v8_deadline_monitor.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/scripting/v8_deadline_monitor.h')
-rw-r--r--src/mongo/scripting/v8_deadline_monitor.h219
1 files changed, 108 insertions, 111 deletions
diff --git a/src/mongo/scripting/v8_deadline_monitor.h b/src/mongo/scripting/v8_deadline_monitor.h
index 362701c2762..11d2851162c 100644
--- a/src/mongo/scripting/v8_deadline_monitor.h
+++ b/src/mongo/scripting/v8_deadline_monitor.h
@@ -37,133 +37,130 @@
namespace mongo {
- /**
- * DeadlineMonitor
- *
- * Monitors tasks which are required to complete before a deadline. When
- * a deadline is started on a _Task*, either the deadline must be stopped,
- * or _Task::kill() will be called when the deadline arrives.
- *
- * Each instance of a DeadlineMonitor spawns a thread which waits for one of the
- * following conditions:
- * - a task is added to the monitor
- * - a task is removed from the monitor
- * - the nearest deadline has arrived
- *
- * Ownership:
- * The _Task* must not be freed until the deadline has elapsed or stopDeadline()
- * has been called.
- *
- * NOTE: Each instance of this class spawns a new thread. It is intended to be a stop-gap
- * solution for simple deadline monitoring until a more robust solution can be
- * implemented.
- *
- * NOTE: timing is based on wallclock time, which may not be precise.
- */
- template <typename _Task>
- class DeadlineMonitor {
+/**
+ * DeadlineMonitor
+ *
+ * Monitors tasks which are required to complete before a deadline. When
+ * a deadline is started on a _Task*, either the deadline must be stopped,
+ * or _Task::kill() will be called when the deadline arrives.
+ *
+ * Each instance of a DeadlineMonitor spawns a thread which waits for one of the
+ * following conditions:
+ * - a task is added to the monitor
+ * - a task is removed from the monitor
+ * - the nearest deadline has arrived
+ *
+ * Ownership:
+ * The _Task* must not be freed until the deadline has elapsed or stopDeadline()
+ * has been called.
+ *
+ * NOTE: Each instance of this class spawns a new thread. It is intended to be a stop-gap
+ * solution for simple deadline monitoring until a more robust solution can be
+ * implemented.
+ *
+ * NOTE: timing is based on wallclock time, which may not be precise.
+ */
+template <typename _Task>
+class DeadlineMonitor {
MONGO_DISALLOW_COPYING(DeadlineMonitor);
- public:
- DeadlineMonitor() {
- // NOTE(schwerin): Because _monitorThread takes a pointer to "this", all of the fields
- // of this instance must be initialized before the thread is created. As a result, we
- // should not create the thread in the initializer list. Creating it there leaves us
- // vulnerable to errors introduced by rearranging the order of fields in the class.
- _monitorThread =
- stdx::thread(&mongo::DeadlineMonitor<_Task>::deadlineMonitorThread, this);
- }
- ~DeadlineMonitor() {
- {
- // ensure the monitor thread has been stopped before destruction
- stdx::lock_guard<stdx::mutex> lk(_deadlineMutex);
- _inShutdown = true;
- _newDeadlineAvailable.notify_one();
- }
- _monitorThread.join();
- }
+public:
+ DeadlineMonitor() {
+ // NOTE(schwerin): Because _monitorThread takes a pointer to "this", all of the fields
+ // of this instance must be initialized before the thread is created. As a result, we
+ // should not create the thread in the initializer list. Creating it there leaves us
+ // vulnerable to errors introduced by rearranging the order of fields in the class.
+ _monitorThread = stdx::thread(&mongo::DeadlineMonitor<_Task>::deadlineMonitorThread, this);
+ }
- /**
- * Start monitoring a task for deadline lapse. User must call stopDeadline() before
- * deleting the task. Note that stopDeadline() cannot be called from within the
- * kill() method.
- * @param task the task to kill()
- * @param timeoutMs number of milliseconds before the deadline expires
- */
- void startDeadline(_Task* const task, uint64_t timeoutMs) {
- const auto deadline = Date_t::now() + Milliseconds(timeoutMs);
+ ~DeadlineMonitor() {
+ {
+ // ensure the monitor thread has been stopped before destruction
stdx::lock_guard<stdx::mutex> lk(_deadlineMutex);
+ _inShutdown = true;
+ _newDeadlineAvailable.notify_one();
+ }
+ _monitorThread.join();
+ }
- _tasks[task] = deadline;
+ /**
+ * Start monitoring a task for deadline lapse. User must call stopDeadline() before
+ * deleting the task. Note that stopDeadline() cannot be called from within the
+ * kill() method.
+ * @param task the task to kill()
+ * @param timeoutMs number of milliseconds before the deadline expires
+ */
+ void startDeadline(_Task* const task, uint64_t timeoutMs) {
+ const auto deadline = Date_t::now() + Milliseconds(timeoutMs);
+ stdx::lock_guard<stdx::mutex> lk(_deadlineMutex);
- if (deadline < _nearestDeadlineWallclock) {
- _nearestDeadlineWallclock = deadline;
- _newDeadlineAvailable.notify_one();
- }
- }
+ _tasks[task] = deadline;
- /**
- * Stop monitoring a task. Can be called multiple times, before or after a
- * deadline has expired (as long as the task remains allocated).
- * @return true if the task was found and erased
- */
- bool stopDeadline(_Task* const task) {
- stdx::lock_guard<stdx::mutex> lk(_deadlineMutex);
- return _tasks.erase(task);
+ if (deadline < _nearestDeadlineWallclock) {
+ _nearestDeadlineWallclock = deadline;
+ _newDeadlineAvailable.notify_one();
}
+ }
- private:
- /**
- * Main deadline monitor loop. Waits on a condition variable until a task
- * is started, stopped, or the nearest deadline arrives. If a deadline arrives,
- * _Task::kill() is invoked.
- */
- void deadlineMonitorThread() {
- stdx::unique_lock<stdx::mutex> lk(_deadlineMutex);
- while (!_inShutdown) {
+ /**
+ * Stop monitoring a task. Can be called multiple times, before or after a
+ * deadline has expired (as long as the task remains allocated).
+ * @return true if the task was found and erased
+ */
+ bool stopDeadline(_Task* const task) {
+ stdx::lock_guard<stdx::mutex> lk(_deadlineMutex);
+ return _tasks.erase(task);
+ }
- // get the next interval to wait
- const Date_t now = Date_t::now();
+private:
+ /**
+ * Main deadline monitor loop. Waits on a condition variable until a task
+ * is started, stopped, or the nearest deadline arrives. If a deadline arrives,
+ * _Task::kill() is invoked.
+ */
+ void deadlineMonitorThread() {
+ stdx::unique_lock<stdx::mutex> lk(_deadlineMutex);
+ while (!_inShutdown) {
+ // get the next interval to wait
+ const Date_t now = Date_t::now();
- // wait for a task to be added or a deadline to expire
- if (_nearestDeadlineWallclock > now) {
- if (_nearestDeadlineWallclock == Date_t::max()) {
- _newDeadlineAvailable.wait(lk);
- }
- else {
- _newDeadlineAvailable.wait_until(
- lk, _nearestDeadlineWallclock.toSystemTimePoint());
- }
- continue;
+ // wait for a task to be added or a deadline to expire
+ if (_nearestDeadlineWallclock > now) {
+ if (_nearestDeadlineWallclock == Date_t::max()) {
+ _newDeadlineAvailable.wait(lk);
+ } else {
+ _newDeadlineAvailable.wait_until(lk,
+ _nearestDeadlineWallclock.toSystemTimePoint());
}
+ continue;
+ }
- // set the next interval to wait for deadline completion
- _nearestDeadlineWallclock = Date_t::max();
- typename TaskDeadlineMap::iterator i = _tasks.begin();
- while (i != _tasks.end()) {
- if (i->second < now) {
- // deadline expired
- i->first->kill();
- _tasks.erase(i++);
- }
- else {
- if (i->second < _nearestDeadlineWallclock) {
- // nearest deadline seen so far
- _nearestDeadlineWallclock = i->second;
- }
- ++i;
+ // set the next interval to wait for deadline completion
+ _nearestDeadlineWallclock = Date_t::max();
+ typename TaskDeadlineMap::iterator i = _tasks.begin();
+ while (i != _tasks.end()) {
+ if (i->second < now) {
+ // deadline expired
+ i->first->kill();
+ _tasks.erase(i++);
+ } else {
+ if (i->second < _nearestDeadlineWallclock) {
+ // nearest deadline seen so far
+ _nearestDeadlineWallclock = i->second;
}
+ ++i;
}
}
}
+ }
- typedef unordered_map<_Task*, Date_t> TaskDeadlineMap;
- TaskDeadlineMap _tasks; // map of running tasks with deadlines
- stdx::mutex _deadlineMutex; // protects all non-const members, except _monitorThread
- stdx::condition_variable _newDeadlineAvailable; // Signaled for timeout, start and stop
- stdx::thread _monitorThread; // the deadline monitor thread
- Date_t _nearestDeadlineWallclock = Date_t::max(); // absolute time of the nearest deadline
- bool _inShutdown = false;
- };
+ typedef unordered_map<_Task*, Date_t> TaskDeadlineMap;
+ TaskDeadlineMap _tasks; // map of running tasks with deadlines
+ stdx::mutex _deadlineMutex; // protects all non-const members, except _monitorThread
+ stdx::condition_variable _newDeadlineAvailable; // Signaled for timeout, start and stop
+ stdx::thread _monitorThread; // the deadline monitor thread
+ Date_t _nearestDeadlineWallclock = Date_t::max(); // absolute time of the nearest deadline
+ bool _inShutdown = false;
+};
-} // namespace mongo
+} // namespace mongo