diff options
Diffstat (limited to 'src/mongo/util/background.h')
-rw-r--r-- | src/mongo/util/background.h | 251 |
1 files changed, 123 insertions, 128 deletions
diff --git a/src/mongo/util/background.h b/src/mongo/util/background.h index 64b7394f70b..03fcf945f0e 100644 --- a/src/mongo/util/background.h +++ b/src/mongo/util/background.h @@ -38,140 +38,135 @@ namespace mongo { +/** + * Background thread dispatching. + * subclass and define run() + * + * It is not possible to run the job more than once. An attempt to call 'go' while the + * task is running will fail. Calling 'go' after the task has finished are ignored and + * will not start the job again. + * + * Thread safety: Note that when the job destructs, the thread is not terminated if still + * running. Generally, if the thread could still be running, allocate the job dynamically + * and set deleteSelf to true. + * + * The overridden run() method will be executed on the background thread, so the + * BackgroundJob object must exist for as long the background thread is running. + */ + +class BackgroundJob { + MONGO_DISALLOW_COPYING(BackgroundJob); + +protected: + /** + * sub-class must instantiate the BackgroundJob + * + * @param selfDelete if set to true, object will destruct itself after the run() finished + * @note selfDelete instances cannot be wait()-ed upon + */ + explicit BackgroundJob(bool selfDelete = false); + + virtual std::string name() const = 0; + /** - * Background thread dispatching. - * subclass and define run() + * define this to do your work. + * after this returns, state is set to done. + * after this returns, deleted if deleteSelf true. * - * It is not possible to run the job more than once. An attempt to call 'go' while the - * task is running will fail. Calling 'go' after the task has finished are ignored and - * will not start the job again. + * NOTE: + * if run() throws, the exception will be caught within 'this' object and will ultimately lead to the + * BackgroundJob's thread being finished, as if run() returned. * - * Thread safety: Note that when the job destructs, the thread is not terminated if still - * running. Generally, if the thread could still be running, allocate the job dynamically - * and set deleteSelf to true. + */ + virtual void run() = 0; + +public: + enum State { NotStarted, Running, Done }; + + virtual ~BackgroundJob(); + + /** + * starts job. + * returns immediately after dispatching. * - * The overridden run() method will be executed on the background thread, so the - * BackgroundJob object must exist for as long the background thread is running. + * @note the BackgroundJob object must live for as long the thread is still running, ie + * until getState() returns Done. */ + void go(); - class BackgroundJob { - MONGO_DISALLOW_COPYING(BackgroundJob); - protected: - /** - * sub-class must instantiate the BackgroundJob - * - * @param selfDelete if set to true, object will destruct itself after the run() finished - * @note selfDelete instances cannot be wait()-ed upon - */ - explicit BackgroundJob(bool selfDelete = false); - - virtual std::string name() const = 0; - - /** - * define this to do your work. - * after this returns, state is set to done. - * after this returns, deleted if deleteSelf true. - * - * NOTE: - * if run() throws, the exception will be caught within 'this' object and will ultimately lead to the - * BackgroundJob's thread being finished, as if run() returned. - * - */ - virtual void run() = 0; - - public: - enum State { - NotStarted, - Running, - Done - }; - - virtual ~BackgroundJob(); - - /** - * starts job. - * returns immediately after dispatching. - * - * @note the BackgroundJob object must live for as long the thread is still running, ie - * until getState() returns Done. - */ - void go(); - - - /** - * If the job has not yet started, transitions the job to the 'done' state immediately, - * such that subsequent calls to 'go' are ignored, and notifies any waiters waiting in - * 'wait'. If the job has already been started, this method returns a not-ok status: it - * does not cancel running jobs. For this reason, you must still call 'wait' on a - * BackgroundJob even after calling 'cancel'. - */ - Status cancel(); - - /** - * wait for completion. - * - * @param msTimeOut maximum amount of time to wait in milliseconds - * @return true if did not time out. false otherwise. - * - * @note you can call wait() more than once if the first call times out. - * but you cannot call wait on a self-deleting job. - */ - bool wait( unsigned msTimeOut = 0 ); - - // accessors. Note that while the access to the internal state is synchronized within - // these methods, there is no guarantee that the BackgroundJob is still in the - // indicated state after returning. - State getState() const; - bool running() const; - - private: - const bool _selfDelete; - - struct JobStatus; - const std::unique_ptr<JobStatus> _status; - - void jobBody(); - }; /** - * these run "roughly" every minute - * instantiate statically - * class MyTask : public PeriodicTask { - * public: - * virtual std::string name() const { return "MyTask; " } - * virtual void doWork() { log() << "hi" << std::endl; } - * } myTask; + * If the job has not yet started, transitions the job to the 'done' state immediately, + * such that subsequent calls to 'go' are ignored, and notifies any waiters waiting in + * 'wait'. If the job has already been started, this method returns a not-ok status: it + * does not cancel running jobs. For this reason, you must still call 'wait' on a + * BackgroundJob even after calling 'cancel'. */ - class PeriodicTask { - public: - PeriodicTask(); - virtual ~PeriodicTask(); - - virtual void taskDoWork() = 0; - virtual std::string taskName() const = 0; - - /** - * Starts the BackgroundJob that runs PeriodicTasks. You may call this multiple times, - * from multiple threads, and the BackgroundJob will be started only once. Please note - * that since this method starts threads, it is not appropriate to call it from within - * a mongo initializer. Calling this method after calling 'stopRunningPeriodicTasks' - * does not re-start the background job. - */ - static void startRunningPeriodicTasks(); - - /** - * Waits 'gracePeriodMillis' for the BackgroundJob responsible for PeriodicTask - * execution to finish any running tasks, then destroys it. If the BackgroundJob was - * never started, returns Status::OK right away. If the BackgroundJob does not - * terminate within the grace period, returns an invalid status. It is safe to call - * this method repeatedly from one thread if the grace period is overshot. It is not - * safe to call this method from multiple threads, or in a way that races with - * 'startRunningPeriodicTasks'. - */ - static Status stopRunningPeriodicTasks( int gracePeriodMillis ); - }; - - - - -} // namespace mongo + Status cancel(); + + /** + * wait for completion. + * + * @param msTimeOut maximum amount of time to wait in milliseconds + * @return true if did not time out. false otherwise. + * + * @note you can call wait() more than once if the first call times out. + * but you cannot call wait on a self-deleting job. + */ + bool wait(unsigned msTimeOut = 0); + + // accessors. Note that while the access to the internal state is synchronized within + // these methods, there is no guarantee that the BackgroundJob is still in the + // indicated state after returning. + State getState() const; + bool running() const; + +private: + const bool _selfDelete; + + struct JobStatus; + const std::unique_ptr<JobStatus> _status; + + void jobBody(); +}; + +/** + * these run "roughly" every minute + * instantiate statically + * class MyTask : public PeriodicTask { + * public: + * virtual std::string name() const { return "MyTask; " } + * virtual void doWork() { log() << "hi" << std::endl; } + * } myTask; + */ +class PeriodicTask { +public: + PeriodicTask(); + virtual ~PeriodicTask(); + + virtual void taskDoWork() = 0; + virtual std::string taskName() const = 0; + + /** + * Starts the BackgroundJob that runs PeriodicTasks. You may call this multiple times, + * from multiple threads, and the BackgroundJob will be started only once. Please note + * that since this method starts threads, it is not appropriate to call it from within + * a mongo initializer. Calling this method after calling 'stopRunningPeriodicTasks' + * does not re-start the background job. + */ + static void startRunningPeriodicTasks(); + + /** + * Waits 'gracePeriodMillis' for the BackgroundJob responsible for PeriodicTask + * execution to finish any running tasks, then destroys it. If the BackgroundJob was + * never started, returns Status::OK right away. If the BackgroundJob does not + * terminate within the grace period, returns an invalid status. It is safe to call + * this method repeatedly from one thread if the grace period is overshot. It is not + * safe to call this method from multiple threads, or in a way that races with + * 'startRunningPeriodicTasks'. + */ + static Status stopRunningPeriodicTasks(int gracePeriodMillis); +}; + + +} // namespace mongo |