diff options
author | Eliot Horowitz <eliot@10gen.com> | 2011-12-24 15:33:26 -0500 |
---|---|---|
committer | Eliot Horowitz <eliot@10gen.com> | 2011-12-24 15:33:45 -0500 |
commit | ae1ecd9c786911f9f1f0242f0f7d702b3e5dfeba (patch) | |
tree | 92f8e1649e6f080b251ff5f1763679a72eb59b34 /src/mongo/util/background.h | |
parent | dfa4cd7e2cf109b072440155fabc08a93c8045a0 (diff) | |
download | mongo-ae1ecd9c786911f9f1f0242f0f7d702b3e5dfeba.tar.gz |
bulk move of code to src/ SERVER-4551
Diffstat (limited to 'src/mongo/util/background.h')
-rw-r--r-- | src/mongo/util/background.h | 155 |
1 files changed, 155 insertions, 0 deletions
diff --git a/src/mongo/util/background.h b/src/mongo/util/background.h new file mode 100644 index 00000000000..496a1f44f88 --- /dev/null +++ b/src/mongo/util/background.h @@ -0,0 +1,155 @@ +// @file background.h + +/* Copyright 2009 10gen Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include "concurrency/spin_lock.h" + +namespace mongo { + + /** + * Background thread dispatching. + * subclass and define run() + * + * It is ok to call go(), that is, run the job, more than once -- if the + * previous invocation has finished. Thus one pattern of use is to embed + * a backgroundjob in your object and reuse it (or same thing with + * inheritance). Each go() call spawns a new thread. + * + * Thread safety: + * note when 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. + * + * go() and wait() are not thread safe + * run() will be executed on the background thread + * BackgroundJob object must exist for as long the background thread is running + */ + + class BackgroundJob : boost::noncopyable { + protected: + /** + * sub-class must intantiate the BackgrounJob + * + * @param selfDelete if set to true, object will destruct itself after the run() finished + * @note selfDelete instantes cannot be wait()-ed upon + */ + explicit BackgroundJob(bool selfDelete = false); + + virtual 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 immediatelly after dispatching. + * + * @note the BackgroundJob object must live for as long the thread is still running, ie + * until getState() returns Done. + */ + BackgroundJob& go(); + + /** + * wait for completion. + * + * @param msTimeOut maximum amount of time to wait in millisecons + * @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 + State getState() const; + bool running() const; + + private: + struct JobStatus; + boost::shared_ptr<JobStatus> _status; // shared between 'this' and body() thread + + void jobBody( boost::shared_ptr<JobStatus> status ); + + }; + + /** + * these run "roughly" every minute + * instantiate statically + * class MyTask : public PeriodicTask { + * public: + * virtual string name() const { return "MyTask; " } + * virtual void doWork() { log() << "hi" << endl; } + * } myTask; + */ + class PeriodicTask { + public: + PeriodicTask(); + virtual ~PeriodicTask(); + + virtual void taskDoWork() = 0; + virtual string taskName() const = 0; + + class Runner : public BackgroundJob { + public: + virtual ~Runner(){} + + virtual string name() const { return "PeriodicTask::Runner"; } + + virtual void run(); + + void add( PeriodicTask* task ); + void remove( PeriodicTask* task ); + + private: + + SpinLock _lock; + + // these are NOT owned by Runner + // Runner will not delete these + // this never gets smaller + // only fields replaced with nulls + vector<PeriodicTask*> _tasks; + + }; + + static Runner* theRunner; + + }; + + + + +} // namespace mongo |