Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make library easy to install, put everything into tp namespace, add optional boost::future support #5

Merged
merged 10 commits into from
Jan 6, 2017
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
boost*
build*
thread_pool-build*
*.pro.user
*.pro.user
*.user
23 changes: 16 additions & 7 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,14 +1,23 @@
# thread-poll-cpp build script
cmake_minimum_required(VERSION 3.0)

project(thread-pool-cpp)
list(APPEND CMAKE_MODULE_PATH
"${CMAKE_CURRENT_SOURCE_DIR}/cmake"
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules")

cmake_minimum_required(VERSION 2.8)
project(thread-pool-cpp)
add_definitions(-std=c++14 -Wall -Werror -O3)

ADD_DEFINITIONS(
-std=c++1y -Wall -Werror -O3
)

include_directories(${CMAKE_CURRENT_SOURCE_DIR}/thread_pool)
# Get all include files
set(THREAD_POOL_CPP_INC_DIR "${CMAKE_CURRENT_SOURCE_DIR}/include/")
include_directories("${THREAD_POOL_CPP_INC_DIR}")
file(GLOB_RECURSE INSTALL_FILES_LIST "${THREAD_POOL_CPP_INC_DIR}/*")

add_subdirectory(tests)
add_subdirectory(benchmark)

# Install as header-only library
set_source_files_properties(${INSTALL_FILES_LIST} PROPERTIES HEADER_FILE_ONLY 1)
add_library(HEADER_ONLY_TARGET STATIC ${INSTALL_FILES_LIST})
set_target_properties(HEADER_ONLY_TARGET PROPERTIES LINKER_LANGUAGE CXX)
install(DIRECTORY ${THREAD_POOL_CPP_INC_DIR} DESTINATION "include")
2 changes: 2 additions & 0 deletions benchmark/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#benchmark

include_directories("${THREAD_POOL_CPP_INC_DIR}")

find_package(Boost REQUIRED COMPONENTS system)

include_directories(${CMAKE_CURRENT_SOURCE_DIR})
Expand Down
123 changes: 73 additions & 50 deletions benchmark/benchmark.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,141 +12,161 @@
#include <vector>
#include <future>

using namespace tp;

using ThreadPoolStd = ThreadPool<>;

static const size_t CONCURRENCY = 16;
static const size_t REPOST_COUNT = 1000000;

struct Heavy {
struct Heavy
{
bool verbose;
std::vector<char> resource;

Heavy(bool verbose = false)
: verbose(verbose)
, resource(100*1024*1024)
Heavy(bool verbose = false) : verbose(verbose), resource(100 * 1024 * 1024)
{
if (verbose) {
if(verbose)
{
std::cout << "heavy default constructor" << std::endl;
}
}

Heavy(const Heavy &o)
: verbose(o.verbose)
, resource(o.resource)
Heavy(const Heavy& o) : verbose(o.verbose), resource(o.resource)
{
if (verbose) {
if(verbose)
{
std::cout << "heavy copy constructor" << std::endl;
}
}

Heavy(Heavy &&o)
: verbose(o.verbose)
, resource(std::move(o.resource))
Heavy(Heavy&& o) : verbose(o.verbose), resource(std::move(o.resource))
{
if (verbose) {
if(verbose)
{
std::cout << "heavy move constructor" << std::endl;
}
}

Heavy & operator==(const Heavy &o)
Heavy& operator==(const Heavy& o)
{
verbose = o.verbose;
resource = o.resource;
if (verbose) {
if(verbose)
{
std::cout << "heavy copy operator" << std::endl;
}
return *this;
}

Heavy & operator==(const Heavy &&o)
Heavy& operator==(const Heavy&& o)
{
verbose = o.verbose;
resource = std::move(o.resource);
if (verbose) {
if(verbose)
{
std::cout << "heavy move operator" << std::endl;
}
return *this;
}

~Heavy()
{
if (verbose) {
std::cout << "heavy destructor. " << (resource.size() ? "Owns resource" : "Doesn't own resource") << std::endl;
if(verbose)
{
std::cout << "heavy destructor. "
<< (resource.size() ? "Owns resource"
: "Doesn't own resource")
<< std::endl;
}
}
};


struct RepostJob {
//Heavy heavy;
struct RepostJob
{
// Heavy heavy;

ThreadPool *thread_pool;
ThreadPoolStd* thread_pool;
#ifndef WITHOUT_ASIO
AsioThreadPool *asio_thread_pool;
AsioThreadPool* asio_thread_pool;
#endif

volatile size_t counter;
long long int begin_count;
std::promise<void> *waiter;
std::promise<void>* waiter;

RepostJob(ThreadPool *thread_pool, std::promise<void> *waiter)
RepostJob(ThreadPoolStd* thread_pool, std::promise<void>* waiter)
: thread_pool(thread_pool)
#ifndef WITHOUT_ASIO
, asio_thread_pool(0)
,
asio_thread_pool(0)
#endif
, counter(0)
, waiter(waiter)
,
counter(0), waiter(waiter)
{
begin_count = std::chrono::high_resolution_clock::now().time_since_epoch().count();
begin_count = std::chrono::high_resolution_clock::now()
.time_since_epoch()
.count();
}

#ifndef WITHOUT_ASIO
RepostJob(AsioThreadPool *asio_thread_pool, std::promise<void> *waiter)
: thread_pool(0)
, asio_thread_pool(asio_thread_pool)
, counter(0)
, waiter(waiter)
RepostJob(AsioThreadPool* asio_thread_pool, std::promise<void>* waiter)
: thread_pool(0), asio_thread_pool(asio_thread_pool), counter(0),
waiter(waiter)
{
begin_count = std::chrono::high_resolution_clock::now().time_since_epoch().count();
begin_count = std::chrono::high_resolution_clock::now()
.time_since_epoch()
.count();
}
#endif

void operator()()
{
if (counter++ < REPOST_COUNT) {
if(counter++ < REPOST_COUNT)
{
#ifndef WITHOUT_ASIO
if (asio_thread_pool) {
if(asio_thread_pool)
{
asio_thread_pool->post(*this);
return;
}
#endif
if (thread_pool) {
if(thread_pool)
{
thread_pool->post(*this);
return;
}
}
else {
long long int end_count = std::chrono::high_resolution_clock::now().time_since_epoch().count();
std::cout << "reposted " << counter
<< " in " << (double)(end_count - begin_count)/(double)1000000 << " ms"
<< std::endl;
else
{
long long int end_count = std::chrono::high_resolution_clock::now()
.time_since_epoch()
.count();
std::cout << "reposted " << counter << " in "
<< (double)(end_count - begin_count) / (double)1000000
<< " ms" << std::endl;
waiter->set_value();
}
}
};

int main(int, const char *[])
int main(int, const char* [])
{
std::cout << "Benchmark job reposting" << std::endl;

{
std::cout << "***thread pool cpp***" << std::endl;

std::promise<void> waiters[CONCURRENCY];
ThreadPool thread_pool;
for (auto &waiter : waiters) {
ThreadPoolStd thread_pool;
for(auto& waiter : waiters)
{
thread_pool.post(RepostJob(&thread_pool, &waiter));
}

for (auto &waiter : waiters) {
for(auto& waiter : waiters)
{
waiter.get_future().wait();
}
}
Expand All @@ -156,18 +176,21 @@ int main(int, const char *[])
std::cout << "***asio thread pool***" << std::endl;

size_t workers_count = std::thread::hardware_concurrency();
if (0 == workers_count) {
if(0 == workers_count)
{
workers_count = 1;
}

AsioThreadPool asio_thread_pool(workers_count);

std::promise<void> waiters[CONCURRENCY];
for (auto &waiter : waiters) {
for(auto& waiter : waiters)
{
asio_thread_pool.post(RepostJob(&asio_thread_pool, &waiter));
}

for (auto &waiter : waiters) {
for(auto& waiter : waiters)
{
waiter.get_future().wait();
}
}
Expand Down
86 changes: 86 additions & 0 deletions cmake/Findthread-pool-cpp.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# Copyright (c) 2015-2016 Vittorio Romeo
# License: Academic Free License ("AFL") v. 3.0
# AFL License page: http://opensource.org/licenses/AFL-3.0
# http://vittorioromeo.info | [email protected]

# Adapted from Louise Dionne's FindHana.cmake file

# Copyright Louis Dionne 2015
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)

# TODO: document variables:
# THREAD_POOL_CPP_FOUND
# THREAD_POOL_CPP_INCLUDE_DIR
# THREAD_POOL_CPP_CLONE_DIR
# THREAD_POOL_CPP_ENABLE_TESTS

find_path(
THREAD_POOL_CPP_INCLUDE_DIR

NAMES vrm/core.hpp
DOC "Include directory for the thread-pool-cpp library"

PATH_SUFFIXES include/

PATHS
"${PROJECT_SOURCE_DIR}/../thread-pool-cpp/"
"${PROJECT_SOURCE_DIR}/../thread_pool_cpp/"
${THREAD_POOL_CPP_ROOT}
$ENV{THREAD_POOL_CPP_ROOT}
/usr/local/
/usr/
/sw/
/opt/local/
/opt/csw/
/opt/
"${PROJECT_SOURCE_DIR}/extlibs/thread-pool-cpp/"
"${PROJECT_SOURCE_DIR}/extlibs/thread_pool_cpp/"
"${CMAKE_CURRENT_LIST_DIR}/../../"

NO_DEFAULT_PATH
)

if (NOT EXISTS "${THREAD_POOL_CPP_INCLUDE_DIR}" AND DEFINED THREAD_POOL_CPP_CLONE_DIR)
set(_build_dir "${CMAKE_CURRENT_BINARY_DIR}/thread-pool-cpp")

if (DEFINED THREAD_POOL_CPP_ENABLE_TESTS)
set(_test_cmd ${CMAKE_COMMAND} --build ${_build_dir} --target check)
else()
set(_test_cmd "")
endif()

include(ExternalProject)
ExternalProject_Add(thread_pool_cpp
PREFIX ${_build_dir}
STAMP_DIR ${_build_dir}/_stamps
TMP_DIR ${_build_dir}/_tmp

# Since we don't have any files to download, we set the DOWNLOAD_DIR
# to TMP_DIR to avoid creating a useless empty directory.
DOWNLOAD_DIR ${_build_dir}/_tmp

# Download step
GIT_REPOSITORY https://github.com/SuperV1234/thread-pool-cpp
GIT_TAG master
TIMEOUT 20

# Configure step
SOURCE_DIR "${THREAD_POOL_CPP_CLONE_DIR}"
CMAKE_ARGS -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} -DCMAKE_CXX_FLAGS=${CMAKE_CXX_FLAGS}

BINARY_DIR "${_build_dir}"
BUILD_COMMAND ""

# Install step (nothing to be done)
INSTALL_COMMAND ""

# Test step
TEST_COMMAND ${_test_cmd}
)

set(THREAD_POOL_CPP_INCLUDE_DIR "${THREAD_POOL_CPP_CLONE_DIR}/include")
endif()

include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(THREAD_POOL_CPP DEFAULT_MSG THREAD_POOL_CPP_INCLUDE_DIR)
3 changes: 3 additions & 0 deletions include/thread_pool.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#pragma once

#include "./thread_pool/thread_pool.hpp"
Loading