diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..735a50c --- /dev/null +++ b/Makefile @@ -0,0 +1,48 @@ +TARGET := main + +SOURCE := \ + example.cpp + +INCS := +LIBS := -lpthread + +DEFINES := --std=c++11 + +CXXFLAGS := -O2 -fPIC -Wall -Wextra +LDFLAGS := -fPIC + +#**************************************************************************** +# Makefile code common to all platforms +#**************************************************************************** +CXXFLAGS := ${CXXFLAGS} ${DEFINES} + +OBJECT := $(addsuffix .o,$(basename ${SOURCE})) + +#**************************************************************************** +# Compile block +#**************************************************************************** +all: ${TARGET} + +${TARGET}: ${OBJECT} + ${CXX} ${LDFLAGS} -o ${TARGET} ${OBJECT} ${LIBS} + +install: + ${STRIP} ${TARGET} + install -m 755 ${TARGET} ${INSTALL_DIR}/bin + +#**************************************************************************** +# common rules +#**************************************************************************** +%.o : %.cpp + ${CXX} ${CXXFLAGS} ${INCS} -c $< -o $@ + +%.o : %.cc + ${CXX} ${CXXFLAGS} ${INCS} -c $< -o $@ + +#**************************************************************************** +# Depend block +#**************************************************************************** +depend: + +clean: + rm -f core ${OBJECT} ${TARGET} diff --git a/ThreadPool.h b/ThreadPool.h index 4183203..1ac0ae7 100644 --- a/ThreadPool.h +++ b/ThreadPool.h @@ -1,52 +1,51 @@ #ifndef THREAD_POOL_H #define THREAD_POOL_H -#include -#include -#include -#include -#include #include -#include #include +#include +#include +#include +#include #include +#include +#include class ThreadPool { public: ThreadPool(size_t); - template - auto enqueue(F&& f, Args&&... args) + template + auto enqueue(F&& f, Args&&... args) -> std::future::type>; ~ThreadPool(); + private: // need to keep track of threads so we can join them - std::vector< std::thread > workers; + std::vector workers; // the task queue - std::queue< std::function > tasks; - + std::queue> tasks; + // synchronization std::mutex queue_mutex; std::condition_variable condition; bool stop; }; - + // the constructor just launches some amount of workers inline ThreadPool::ThreadPool(size_t threads) - : stop(false) + : stop(false) { - for(size_t i = 0;i task; { std::unique_lock lock(this->queue_mutex); this->condition.wait(lock, - [this]{ return this->stop || !this->tasks.empty(); }); - if(this->stop && this->tasks.empty()) + [this] { return this->stop || !this->tasks.empty(); }); + if (this->stop && this->tasks.empty()) return; task = std::move(this->tasks.front()); this->tasks.pop(); @@ -54,30 +53,28 @@ inline ThreadPool::ThreadPool(size_t threads) task(); } - } - ); + }); } // add new work item to the pool -template -auto ThreadPool::enqueue(F&& f, Args&&... args) +template +auto ThreadPool::enqueue(F&& f, Args&&... args) -> std::future::type> { using return_type = typename std::result_of::type; - auto task = std::make_shared< std::packaged_task >( - std::bind(std::forward(f), std::forward(args)...) - ); - + auto task = std::make_shared>( + std::bind(std::forward(f), std::forward(args)...)); + std::future res = task->get_future(); { std::unique_lock lock(queue_mutex); // don't allow enqueueing after stopping the pool - if(stop) + if (stop) throw std::runtime_error("enqueue on stopped ThreadPool"); - tasks.emplace([task](){ (*task)(); }); + tasks.emplace([task]() { (*task)(); }); } condition.notify_one(); return res; @@ -91,7 +88,7 @@ inline ThreadPool::~ThreadPool() stop = true; } condition.notify_all(); - for(std::thread &worker: workers) + for (std::thread& worker : workers) worker.join(); } diff --git a/example.cpp b/example.cpp index 837277b..7756ca8 100644 --- a/example.cpp +++ b/example.cpp @@ -1,29 +1,28 @@ +#include #include #include -#include #include "ThreadPool.h" int main() { - + ThreadPool pool(4); - std::vector< std::future > results; + std::vector> results; - for(int i = 0; i < 8; ++i) { + for (int i = 0; i < 8; ++i) { results.emplace_back( pool.enqueue([i] { std::cout << "hello " << i << std::endl; std::this_thread::sleep_for(std::chrono::seconds(1)); std::cout << "world " << i << std::endl; - return i*i; - }) - ); + return i * i; + })); } - for(auto && result: results) + for (auto&& result : results) std::cout << result.get() << ' '; std::cout << std::endl; - + return 0; }