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
|
// thread_pool.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 <boost/function.hpp>
#include <boost/bind.hpp>
#undef assert
#define assert MONGO_assert
namespace mongo {
namespace threadpool {
class Worker;
typedef boost::function<void(void)> Task; //nullary function or functor
// exported to the mongo namespace
class ThreadPool : boost::noncopyable {
public:
explicit ThreadPool(int nThreads=8);
// blocks until all tasks are complete (tasks_remaining() == 0)
// You should not call schedule while in the destructor
~ThreadPool();
// blocks until all tasks are complete (tasks_remaining() == 0)
// does not prevent new tasks from being scheduled so could wait forever.
// Also, new tasks could be scheduled after this returns.
void join();
// task will be copied a few times so make sure it's relatively cheap
void schedule(Task task);
// Helpers that wrap schedule and boost::bind.
// Functor and args will be copied a few times so make sure it's relatively cheap
template<typename F, typename A>
void schedule(F f, A a) { schedule(boost::bind(f,a)); }
template<typename F, typename A, typename B>
void schedule(F f, A a, B b) { schedule(boost::bind(f,a,b)); }
template<typename F, typename A, typename B, typename C>
void schedule(F f, A a, B b, C c) { schedule(boost::bind(f,a,b,c)); }
template<typename F, typename A, typename B, typename C, typename D>
void schedule(F f, A a, B b, C c, D d) { schedule(boost::bind(f,a,b,c,d)); }
template<typename F, typename A, typename B, typename C, typename D, typename E>
void schedule(F f, A a, B b, C c, D d, E e) { schedule(boost::bind(f,a,b,c,d,e)); }
int tasks_remaining() { return _tasksRemaining; }
private:
mongo::mutex _mutex;
boost::condition _condition;
list<Worker*> _freeWorkers; //used as LIFO stack (always front)
list<Task> _tasks; //used as FIFO queue (push_back, pop_front)
int _tasksRemaining; // in queue + currently processing
int _nThreads; // only used for sanity checking. could be removed in the future.
// should only be called by a worker from the worker's thread
void task_done(Worker* worker);
friend class Worker;
};
} //namespace threadpool
using threadpool::ThreadPool;
} //namespace mongo
|