[med-svn] [Git][med-team/libthread-pool][master] 14 commits: debian/watch: Uniquely rename the archives download from GitHub.

Michael R. Crusoe gitlab at salsa.debian.org
Tue Jan 19 07:51:03 GMT 2021



Michael R. Crusoe pushed to branch master at Debian Med / libthread-pool


Commits:
f348a87d by Michael R. Crusoe at 2021-01-18T16:52:42+01:00
debian/watch: Uniquely rename the archives download from GitHub.

- - - - -
5af18253 by Michael R. Crusoe at 2021-01-18T16:52:42+01:00
routine-update: Standards-Version: 4.5.1

- - - - -
90f33712 by Michael R. Crusoe at 2021-01-18T16:52:42+01:00
routine-update: debhelper-compat 13

- - - - -
4d6784bb by Michael R. Crusoe at 2021-01-18T16:54:39+01:00
routine-update: New upstream version

- - - - -
1d3149f9 by Michael R. Crusoe at 2021-01-18T16:54:41+01:00
New upstream version 3.0.2
- - - - -
e94e96a9 by Michael R. Crusoe at 2021-01-18T16:54:42+01:00
Update upstream source from tag 'upstream/3.0.2'

Update to upstream version '3.0.2'
with Debian dir 7c88db588f2a0bb5948722275ca00c1c086e48a3
- - - - -
e80d9611 by Michael R. Crusoe at 2021-01-18T16:57:59+01:00
Library is header-only now.

- - - - -
ede8f169 by Michael R. Crusoe at 2021-01-18T16:58:35+01:00
routine-update: Add salsa-ci file

- - - - -
33e2fb87 by Michael R. Crusoe at 2021-01-18T16:58:36+01:00
routine-update: Rules-Requires-Root: no

- - - - -
c34c3859 by Michael R. Crusoe at 2021-01-18T16:58:37+01:00
Set upstream metadata fields: Bug-Database, Bug-Submit, Repository-Browse..

Changes-By: lintian-brush
Fixes: lintian: upstream-metadata-missing-bug-tracking
See-also: https://lintian.debian.org/tags/upstream-metadata-missing-bug-tracking.html
Fixes: lintian: upstream-metadata-missing-repository
See-also: https://lintian.debian.org/tags/upstream-metadata-missing-repository.html

- - - - -
5753e9a4 by Michael R. Crusoe at 2021-01-19T08:39:03+01:00
debian/rules: no more vendor directory

- - - - -
95b26361 by Michael R. Crusoe at 2021-01-19T08:39:03+01:00
build-dep on libgtest-dev so that cmake can find it

- - - - -
188cc9c8 by Michael R. Crusoe at 2021-01-19T08:50:09+01:00
more header-only changes

- - - - -
797a99f2 by Michael R. Crusoe at 2021-01-19T08:50:09+01:00
routine-update: Ready to upload to unstable

- - - - -


20 changed files:

- .gitmodules
- .travis.yml
- CMakeLists.txt
- README.md
- debian/changelog
- debian/control
- + debian/install
- − debian/patches/series
- − debian/patches/shared_and_static.patch
- − debian/patches/soversion.patch
- debian/rules
- + debian/salsa-ci.yml
- debian/tests/CMakeLists.txt
- debian/upstream/metadata
- debian/watch
- + include/thread_pool/semaphore.hpp
- include/thread_pool/thread_pool.hpp
- − src/thread_pool.cpp
- + test/semaphore_test.cpp
- test/thread_pool_test.cpp


Changes:

=====================================
.gitmodules
=====================================
@@ -1,3 +1 @@
-[submodule "vendor/googletest"]
-	path = vendor/googletest
-	url = https://github.com/google/googletest
+


=====================================
.travis.yml
=====================================
@@ -2,42 +2,49 @@ dist: trusty
 
 language: cpp
 
-compiler:
-    - clang
-    - gcc
+matrix:
+  include:
+    - name: "GCC 4.8 (Linux)"  # GCC 4.8.5 & CMake 3.9.2
+      os: linux
+      addons:
+        apt:
+          sources:
+            - ubuntu-toolchain-r-test
+          packages:
+            - g++-4.8
+            - cmake
+      env:
+        - SET_COMPILER="export CC=gcc-4.8 && export CXX=g++-4.8"
+
+    - name: "Clang 3.5 (Linux)"  # Clang 3.5.0 & CMake 3.9.2
+      os: linux
+      addons:
+        apt:
+          sources:
+            - llvm-toolchain-trusty-3.5
+          packages:
+            - clang-3.5
+            - cmake
+      env:
+        - SET_COMPILER="export CC=clang-3.5 && export CXX=clang++-3.5"
+
+    - name: "Clang Xcode 9.0 (OSX)"  # Clang 9.0.0 & CMake 3.9.2
+      os: osx
+      osx_image: xcode9
 
 before_install:
-    # cmake 3.2
-    - sudo add-apt-repository ppa:george-edison55/cmake-3.x -y
-
-    # g++4.8.1
-    - sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
-
-    # clang 3.4
-    - if [ "$CXX" == "clang++" ]; then sudo add-apt-repository -y ppa:h-rayflood/llvm; fi
-
-    - sudo apt-get update -qq
+  - eval "${SET_COMPILER}"
+  - git clone https://github.com/google/googletest && cd googletest && mkdir build && cd build && git checkout 703bd9c
+  - cmake -DCMAKE_CXX_FLAGS="-std=c++11" .. && make && sudo make install
+  - cd ../../
 
 install:
-    # cmake 3.2
-    - sudo apt-get install cmake cmake-data
-
-    # g++4.8.1
-    - sudo apt-get install -qq g++-4.8
-    - if [ "$CXX" == "g++" ]; then export CXX="g++-4.8"; fi
-
-    # clang 3.4
-    - if [ "$CXX" == "clang++" ]; then sudo apt-get install --allow-unauthenticated -qq clang-3.4; fi
-    - if [ "$CXX" == "clang++" ]; then export CXX="clang++-3.4"; fi
+  - mkdir build && cd build
+  - cmake -Dthread_pool_build_tests=ON -DCMAKE_BUILD_TYPE=Release .. && make
 
 script:
-    - mkdir build
-    - cd build
-    - cmake -DCMAKE_BUILD_TYPE=Release -Dthread_pool_build_tests=ON ..
-    - make
-    - ./bin/thread_pool_test
+  - ./bin/thread_pool_test
 
 notifications:
-    email:
-        on_success: change
-        on_failure: always
+  email:
+    on_failure: always


=====================================
CMakeLists.txt
=====================================
@@ -1,11 +1,8 @@
-cmake_minimum_required(VERSION 3.2)
-project(thread_pool)
+cmake_minimum_required(VERSION 3.9)
 
-include(GNUInstallDirs)
-
-set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib)
-set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib)
-set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin)
+project(thread_pool VERSION 3.0.2
+                    LANGUAGES CXX
+                    DESCRIPTION "ThreadPool is a c++ header only library modifying and extending https://github.com/progschj/ThreadPool.")
 
 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -pedantic")
 set(CMAKE_CXX_STANDARD 11)
@@ -13,28 +10,25 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
 set(CMAKE_CXX_EXTENSIONS OFF)
 set(THREADS_PREFER_PTHREAD_FLAG ON)
 
-find_package(Threads REQUIRED)
-
-option(thread_pool_build_tests "Build thread_pool unit tests" OFF)
-
-add_library(thread_pool STATIC
-    src/thread_pool.cpp)
-
-target_link_libraries(thread_pool Threads::Threads)
+set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib)
+set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib)
+set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin)
 
-target_include_directories(thread_pool PUBLIC
-    $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
-    $<INSTALL_INTERFACE:include>)
+find_package(Threads REQUIRED)
+add_library(${PROJECT_NAME} INTERFACE)
+target_link_libraries(${PROJECT_NAME} INTERFACE
+  Threads::Threads)
 
-install(TARGETS thread_pool DESTINATION ${CMAKE_INSTALL_LIBDIR})
-install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include/thread_pool DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
+target_include_directories(${PROJECT_NAME} INTERFACE
+  $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>)
 
+option(thread_pool_build_tests "Build thread_pool unit tests" OFF)
 if (thread_pool_build_tests)
-    add_executable(thread_pool_test test/thread_pool_test.cpp)
-
-    if (NOT TARGET gtest_main)
-        add_subdirectory(vendor/googletest/googletest EXCLUDE_FROM_ALL)
-    endif()
-
-    target_link_libraries(thread_pool_test thread_pool gtest_main)
-endif()
+  find_package(GTest REQUIRED)
+  add_executable(${PROJECT_NAME}_test
+    test/semaphore_test.cpp
+    test/thread_pool_test.cpp)
+  target_link_libraries(${PROJECT_NAME}_test
+    ${PROJECT_NAME}
+    GTest::Main)
+endif ()


=====================================
README.md
=====================================
@@ -1,79 +1,78 @@
 # Thread pool
 
 [![Latest GitHub release](https://img.shields.io/github/release/rvaser/thread_pool.svg)](https://github.com/rvaser/thread_pool/releases/latest)
-![image](https://travis-ci.org/rvaser/thread_pool.svg?branch=master)
+[![Build status for c++/clang++](https://travis-ci.com/rvaser/thread_pool.svg?branch=master)](https://travis-ci.com/rvaser/thread_pool)
 
-A c++ thread pool implementation inspired by https://github.com/progschj/ThreadPool.
+ThreadPool is a c++ header only library modifying and extending https://github.com/progschj/ThreadPool.
 
-## Dependencies
-
-### Linux
-
-Application uses following software:
-
-1. gcc 4.8+ or clang 3.4+
-2. cmake 3.2+
-
-## Instalation
-
-By running the following commands:
+## Usage
 
-```bash
-git clone https://github.com/rvaser/thread_pool.git thread_pool
-cd thread_pool
-mkdir build
-cd build
-cmake -DCMAKE_BUILD_TYPE=Release ..
-make
+If you would like to add thread_pool to your project via CMake, add the following:
+```cmake
+if (NOT TARGET thread_pool)
+  add_subdirectory(<path_to_submodules>/thread_pool EXCLUDE_FROM_ALL)
+endif ()
+target_link_libraries(<your_exe> thread_pool)
 ```
 
-a library named `libthread_pool.a` will appear in `build/lib` directory. Optionally, you can run `sudo make install` to install thread_pool library to your machine.
-
-Alternatively, add the project to your `CMakeLists.txt` file with `add_subdirectory(vendor/thread_pool EXCLUDE_FROM_ALL)` and `target_link_libraries(your_exe thread_pool)` commands.
+If you are not using CMake, include the appropriate header file directly to your project and link with pthread.
 
-To build unit tests run `git submodule update --init` and add `-Dthread_pool_build_tests=ON` while running `cmake`. After installation, an executable named `thread_pool_test` will be created in `build/bin`.
+#### Dependencies
 
-## Usage
+- gcc 4.8+ or clang 3.5+
+- (optional) cmake 3.9+
 
-For details on how to use the thread pool, please look at the example bellow:
+## Examples
 
 ```cpp
-// define some functions you want to execute in parallel
-int function1(std::vector<int>& data, int index, ...) {
-    ...
+#include "thread_pool/thread_pool.hpp"
+
+int function1(const T& t, ...) {
+  ...
 }
-int function2(float a, float b) {
-    ...
+int function2(...) {
+  ...
 }
-void function3(void) {
-    ...
+...
+auto lambda1 = [...] (...) -> void {
+  ...
+};
+
+ThreadPool thread_pool{};
+
+std::vector<std::future<int>> futures;
+for (...) {
+  // be sure to used std::ref() or std::cref() for references
+  futures.emplace_back(thread_pool.Submit(function1, std::cref(t), ...));
+  futures.emplace_back(thread_pool.Submit(function2, ...));
 }
-
-// create thread pool
-std::shared_ptr<thread_pool::ThreadPool> thread_pool =
-    thread_pool::createThreadPool(); // or pass number of threads you desire
-// or std::unique_ptr<thread_pool::ThreadPool> ...
-
-// create storage for return values of function1 and function2
-std::vector<std::future<int>> thread_futures;
-for (std::uint32_t i = 0; i < num_tasks; ++i) {
-    // be sure to use std::ref() when passing references!
-    thread_futures.emplace_back(thread_pool->submit(function1, std::ref(data), index, ...));
-    thread_futures.emplace_back(thread_pool->submit(function2, a, b));
+for (auto& it : futures) {
+  ... = it.get();
 }
 
-// wait for threads to finish
-for (auto& it: thread_futures) {
-    it.wait();
-    // get return value with it.get();
+std::vector<std::future<void>> void_futures;
+for (...) {
+  void_futures.emplace_back(thread_pool.Submit(lambda1, ...));
 }
-
-// new set of tasks running function3
-std::vector<std::future<void>> thread_futures2;
-for (std::uint32_t i = 0; i < num_tasks2; ++i) {
-    thread_futures2.emplace_back(thread_pool->submit(function3));
-}
-for (auto& it2: thread_futures2) {
-    it.wait();
+for (const auto& it : void_futures) {
+  it.wait();
 }
 ```
+
+## Unit tests
+
+To build and run thread_pool unit tests run the following commands:
+
+```bash
+git clone https://github.com/rvaser/thread_pool.git thread_pool
+cd thread_pool && mkdir build && cd build
+cmake -Dthread_pool_build_tests=ON -DCMAKE_BUILD_TYPE=Release .. && make
+./bin/thread_pool_test
+```
+
+#### Dependencies
+- gtest
+
+## Acknowledgement
+
+This work has been supported in part by the Croatian Science Foundation under the project Single genome and metagenome assembly (IP-2018-01-5886)..


=====================================
debian/changelog
=====================================
@@ -1,3 +1,18 @@
+libthread-pool (3.0.2-1) unstable; urgency=medium
+
+  * Team upload.
+  * debian/watch: Uniquely rename the archives download from GitHub.
+  * Standards-Version: 4.5.1 (routine-update)
+  * debhelper-compat 13 (routine-update)
+  * Library is header-only now.
+  * Add salsa-ci file (routine-update)
+  * Rules-Requires-Root: no (routine-update)
+  * Set upstream metadata fields: Bug-Database, Bug-Submit, Repository-Browse.
+  * debian/rules: no more vendor directory
+  * build-dep on libgtest-dev so that cmake can find it
+
+ -- Michael R. Crusoe <crusoe at debian.org>  Mon, 18 Jan 2021 16:58:37 +0100
+
 libthread-pool (2.0.2-1) unstable; urgency=medium
 
   * Team upload.


=====================================
debian/control
=====================================
@@ -3,41 +3,24 @@ Maintainer: Debian Med Packaging Team <debian-med-packaging at lists.alioth.debian.
 Uploaders: Andreas Tille <tille at debian.org>
 Section: science
 Priority: optional
-Build-Depends: debhelper-compat (= 12),
+Build-Depends: debhelper-compat (= 13),
                cmake,
                d-shlibs,
                rename,
-               googletest
-Standards-Version: 4.5.0
+               libgtest-dev
+Standards-Version: 4.5.1
 Vcs-Browser: https://salsa.debian.org/med-team/libthread-pool
 Vcs-Git: https://salsa.debian.org/med-team/libthread-pool.git
 Homepage: https://github.com/rvaser/thread_pool
-
-Package: libthread-pool0
-Architecture: any
-Section: libs
-Depends: ${shlibs:Depends},
-         ${misc:Depends}
-Description: C++ thread pool library
- A thread pool is a software design pattern for achieving concurrency of
- execution in a computer program. Often also called a replicated workers
- or worker-crew model,[1] a thread pool maintains multiple threads
- waiting for tasks to be allocated for concurrent execution by the
- supervising program.
- .
- This package contains a shared library with a thread pool
- implementation.
+Rules-Requires-Root: no
 
 Package: libthread-pool-dev
-Architecture: any
+Architecture: all
 Section: libdevel
-Depends: ${misc:Depends},
-         libthread-pool0 (= ${binary:Version})
-Description: C++ thread pool library (devel)
+Depends: ${misc:Depends}
+Description: C++ header-only thread pool library (devel)
  A thread pool is a software design pattern for achieving concurrency of
  execution in a computer program. Often also called a replicated workers
  or worker-crew model,[1] a thread pool maintains multiple threads
  waiting for tasks to be allocated for concurrent execution by the
  supervising program.
- .
- This package contains the static library and the header files.


=====================================
debian/install
=====================================
@@ -0,0 +1 @@
+include/thread_pool /usr/include/


=====================================
debian/patches/series deleted
=====================================
@@ -1,2 +0,0 @@
-shared_and_static.patch
-soversion.patch


=====================================
debian/patches/shared_and_static.patch deleted
=====================================
@@ -1,31 +0,0 @@
-Author: Andreas Tille <tille at debian.org>
-Last-Update:  Fri, 08 Jun 2018 13:20:51 +0200
-Description: Build shared and static lib
-
---- a/CMakeLists.txt
-+++ b/CMakeLists.txt
-@@ -17,7 +17,10 @@ find_package(Threads REQUIRED)
- 
- option(thread_pool_build_tests "Build thread_pool unit tests" OFF)
- 
--add_library(thread_pool STATIC
-+add_library(thread_pool SHARED
-+    src/thread_pool.cpp)
-+
-+add_library(thread_pool_static STATIC
-     src/thread_pool.cpp)
- 
- target_link_libraries(thread_pool Threads::Threads)
-@@ -26,7 +29,12 @@ target_include_directories(thread_pool P
-     $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
-     $<INSTALL_INTERFACE:include>)
- 
-+target_include_directories(thread_pool_static PUBLIC
-+    $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
-+    $<INSTALL_INTERFACE:include>)
-+
- install(TARGETS thread_pool DESTINATION ${CMAKE_INSTALL_LIBDIR})
-+install(TARGETS thread_pool_static DESTINATION lib)
- install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include/thread_pool DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
- 
- if (thread_pool_build_tests)


=====================================
debian/patches/soversion.patch deleted
=====================================
@@ -1,25 +0,0 @@
-Author: Andreas Tille <tille at debian.org>
-Last-Update:  Fri, 08 Jun 2018 13:20:51 +0200
-Description: Add soversion
-
---- a/CMakeLists.txt
-+++ b/CMakeLists.txt
-@@ -1,5 +1,5 @@
- cmake_minimum_required(VERSION 3.2)
--project(thread_pool)
-+project(thread_pool LANGUAGES CXX VERSION 1.0.0)
- 
- include(GNUInstallDirs)
- 
-@@ -25,6 +25,11 @@ add_library(thread_pool_static STATIC
- 
- target_link_libraries(thread_pool Threads::Threads)
- 
-+set_target_properties(thread_pool
-+    PROPERTIES
-+    VERSION ${thread_pool_VERSION}
-+    SOVERSION 0)
-+
- target_include_directories(thread_pool PUBLIC
-     $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
-     $<INSTALL_INTERFACE:include>)


=====================================
debian/rules
=====================================
@@ -9,22 +9,9 @@ export DEB_LDFLAGS_MAINT_APPEND+=-pthread
 	dh $@
 
 override_dh_auto_configure:
-	rm -Rf vendor/*
-	ln -s /usr/src/googletest ./vendor/
 	dh_auto_configure -- -Dthread_pool_build_tests=ON
 
 override_dh_auto_test:
 ifeq (,$(filter nocheck,$(DEB_BUILD_OPTIONS)))
 	./obj-*/bin/thread_pool_test
 endif
-
-override_dh_install:
-	dh_install
-	file-rename 's/_static\.a/.a/' `find debian -name "lib*_static.a"`
-	mv debian/tmp/usr/lib/*.a debian/tmp/usr/lib/`dpkg-architecture -qDEB_HOST_MULTIARCH` # this somehow inserts i686-linux-gnu which is wrong: $(DEB_HOST_MULTIARCH)
-	d-shlibmove --commit \
-		    --multiarch \
-		    --devunversioned \
-		    --exclude-la \
-		    --movedev debian/tmp/usr/include/* usr/include \
-		    debian/tmp/usr/lib/*/*.so


=====================================
debian/salsa-ci.yml
=====================================
@@ -0,0 +1,4 @@
+---
+include:
+  - https://salsa.debian.org/salsa-ci-team/pipeline/raw/master/salsa-ci.yml
+  - https://salsa.debian.org/salsa-ci-team/pipeline/raw/master/pipeline-jobs.yml


=====================================
debian/tests/CMakeLists.txt
=====================================
@@ -7,4 +7,4 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
 
 add_executable(thread_pool_test thread_pool_test.cpp)
 add_subdirectory(/usr/src/googletest .. EXCLUDE_FROM_ALL)
-target_link_libraries(thread_pool_test thread_pool gtest_main)
+target_link_libraries(thread_pool_test gtest_main)


=====================================
debian/upstream/metadata
=====================================
@@ -1 +1,4 @@
+Bug-Database: https://github.com/rvaser/thread_pool/issues
+Bug-Submit: https://github.com/rvaser/thread_pool/issues/new
 Repository: https://github.com/rvaser/thread_pool.git
+Repository-Browse: https://github.com/rvaser/thread_pool


=====================================
debian/watch
=====================================
@@ -1,3 +1,4 @@
 version=4
 
-https://github.com/rvaser/thread_pool/releases .*/archive/@ANY_VERSION@@ARCHIVE_EXT@
+opts="filenamemangle=s%(?:.*?)?(\d[\d.]*)\.tar\.gz%@PACKAGE at -$1.tar.gz%" \
+  https://github.com/rvaser/thread_pool/releases .*/@ANY_VERSION@\.tar\.gz


=====================================
include/thread_pool/semaphore.hpp
=====================================
@@ -0,0 +1,46 @@
+// Copyright (c) 2020 Robert Vaser
+
+#ifndef THREAD_POOL_SEMAPHORE_HPP_
+#define THREAD_POOL_SEMAPHORE_HPP_
+
+#include <condition_variable>  // NOLINT
+#include <cstdint>
+#include <memory>
+#include <mutex>  // NOLINT
+
+namespace thread_pool {
+
+class Semaphore {
+ public:
+  explicit Semaphore(std::uint32_t count)
+      : count_(count) {}
+
+  Semaphore(const Semaphore&) = delete;
+  Semaphore& operator=(const Semaphore&) = delete;
+
+  Semaphore(Semaphore&&) = delete;
+  Semaphore& operator=(Semaphore&&) = delete;
+
+  ~Semaphore() = default;
+
+  void Wait() {
+    std::unique_lock<std::mutex> lock(mutex_);
+    condition_.wait(lock, [&] () { return count_; });
+    --count_;
+  }
+
+  void Signal() {
+    std::unique_lock<std::mutex> lock(mutex_);
+    ++count_;
+    condition_.notify_one();
+  }
+
+ private:
+  std::uint32_t count_;
+  std::mutex mutex_;
+  std::condition_variable condition_;
+};
+
+}  // namespace thread_pool
+
+#endif  // THREAD_POOL_SEMAPHORE_HPP_


=====================================
include/thread_pool/thread_pool.hpp
=====================================
@@ -1,107 +1,113 @@
-/*!
- * @file thread_pool.hpp
- *
- * @brief ThreadPool class header file
- */
+// Copyright (c) 2020 Robert Vaser
 
-#pragma once
+#ifndef THREAD_POOL_THREAD_POOL_HPP_
+#define THREAD_POOL_THREAD_POOL_HPP_
 
+#include <algorithm>
+#include <atomic>
 #include <cstdint>
+#include <functional>
+#include <future>  // NOLINT
 #include <memory>
-#include <vector>
-#include <string>
 #include <queue>
-#include <mutex>
-#include <thread>
-#include <future>
-#include <atomic>
-#include <functional>
-#include <condition_variable>
-
-namespace thread_pool {
-
-static const std::string version = "v2.0.2";
-
-class Semaphore;
-std::unique_ptr<Semaphore> createSemaphore(std::uint32_t value);
+#include <string>
+#include <thread>  // NOLINT
+#include <unordered_map>
+#include <utility>
+#include <vector>
 
-class ThreadPool;
-std::unique_ptr<ThreadPool> createThreadPool(std::uint32_t num_threads =
-    std::thread::hardware_concurrency() / 2);
+#include "thread_pool/semaphore.hpp"
 
-class Semaphore {
-public:
-    ~Semaphore() = default;
+namespace thread_pool {
 
-    std::uint32_t value() const {
-        return value_;
+class ThreadPool {
+ public:
+  ThreadPool(std::uint32_t num_threads = std::thread::hardware_concurrency() / 2)  // NOLINT
+      : threads_(),
+        thread_ids_(),
+        thread_semaphore_(0),
+        queue_(),
+        queue_semaphore_(1),
+        terminate_(false) {
+    num_threads = std::max(1U, num_threads);
+    while (num_threads-- != 0) {
+      threads_.emplace_back(ThreadPool::Task, this);
+      thread_ids_.emplace(threads_.back().get_id(), threads_.size() - 1);
     }
+  }
 
-    void wait();
-    void post();
-
-    friend std::unique_ptr<Semaphore> createSemaphore(std::uint32_t value);
-private:
-    Semaphore(std::uint32_t value);
-    Semaphore(const Semaphore&) = delete;
-    const Semaphore& operator=(const Semaphore&) = delete;
-
-    std::mutex mutex_;
-    std::condition_variable condition_;
-    std::uint32_t value_;
-};
+  ThreadPool(const ThreadPool&) = delete;
+  ThreadPool& operator=(const ThreadPool&) = delete;
 
-class ThreadPool {
-public:
-    ~ThreadPool();
+  ThreadPool(ThreadPool&&) = delete;
+  ThreadPool& operator=(ThreadPool&&) = delete;
 
-    std::uint32_t num_threads() const {
-        return threads_.size();
+  ~ThreadPool() {
+    terminate_ = true;
+    for (std::uint32_t i = 0; i < threads_.size(); ++i) {
+      thread_semaphore_.Signal();
     }
-
-    const std::vector<std::thread::id>& thread_identifiers() const {
-        return thread_identifiers_;
+    for (auto& it : threads_) {
+      it.join();
     }
-
-    template<typename T, typename... Ts>
-    auto submit(T&& routine, Ts&&... params)
-        -> std::future<typename std::result_of<T(Ts...)>::type> {
-
-        auto task = std::make_shared<std::packaged_task<typename std::result_of<T(Ts...)>::type()>>(
-            std::bind(std::forward<T>(routine), std::forward<Ts>(params)...)
-        );
-        auto task_result = task->get_future();
-        auto task_wrapper = [task]() {
-            (*task)();
-        };
-
-        queue_sem_->wait();
-
-        task_queue_.emplace(task_wrapper);
-
-        queue_sem_->post();
-        active_sem_->post();
-
-        return task_result;
+  }
+
+  std::uint32_t num_threads() const {
+    return threads_.size();
+  }
+
+  const std::unordered_map<std::thread::id, std::uint32_t>& thread_ids() const {
+    return thread_ids_;
+  }
+
+  template<typename T, typename... Ts>
+  auto Submit(T&& routine, Ts&&... params)
+      -> std::future<typename std::result_of<T(Ts...)>::type> {
+    auto task = std::make_shared<std::packaged_task<typename std::result_of<T(Ts...)>::type()>>(  // NOLINT
+        std::bind(std::forward<T>(routine), std::forward<Ts>(params)...));
+    auto task_result = task->get_future();
+    auto task_wrapper = [task] () {
+      (*task)();
+    };
+
+    queue_semaphore_.Wait();
+    queue_.emplace(task_wrapper);
+    queue_semaphore_.Signal();
+
+    thread_semaphore_.Signal();
+    return task_result;
+  }
+
+ private:
+  static void Task(ThreadPool* thread_pool) {
+    while (true) {
+      thread_pool->thread_semaphore_.Wait();
+
+      if (thread_pool->terminate_) {
+        break;
+      }
+
+      thread_pool->queue_semaphore_.Wait();
+      auto task = std::move(thread_pool->queue_.front());
+      thread_pool->queue_.pop();
+      thread_pool->queue_semaphore_.Signal();
+
+      if (thread_pool->terminate_) {
+        break;
+      }
+
+      task();
     }
-
-    friend std::unique_ptr<ThreadPool> createThreadPool(std::uint32_t num_threads);
-private:
-    ThreadPool(std::uint32_t num_threads);
-    ThreadPool(const ThreadPool&) = delete;
-    const ThreadPool& operator=(const ThreadPool&) = delete;
-
-    static void worker_thread(ThreadPool* thread_pool);
-
-    std::vector<std::thread> threads_;
-    std::vector<std::thread::id> thread_identifiers_;
-
-    std::queue<std::function<void()>> task_queue_;
-
-    std::unique_ptr<Semaphore> queue_sem_;
-    std::unique_ptr<Semaphore> active_sem_;
-
-    std::atomic<bool> terminate_;
+  }
+
+  std::vector<std::thread> threads_;
+  std::unordered_map<std::thread::id, std::uint32_t> thread_ids_;
+  Semaphore thread_semaphore_;
+  std::queue<std::function<void()>> queue_;
+  Semaphore queue_semaphore_;
+  std::atomic<bool> terminate_;
 };
 
-}
+}  // namespace thread_pool
+
+#endif  // THREAD_POOL_THREAD_POOL_HPP_


=====================================
src/thread_pool.cpp deleted
=====================================
@@ -1,88 +0,0 @@
-/*!
- * @file thread_pool.cpp
- *
- * @brief ThreadPool class source file
- */
-
-#include <exception>
-
-#include "thread_pool/thread_pool.hpp"
-
-namespace thread_pool {
-
-std::unique_ptr<Semaphore> createSemaphore(std::uint32_t value) {
-    return std::unique_ptr<Semaphore>(new Semaphore(value));
-}
-
-std::unique_ptr<ThreadPool> createThreadPool(std::uint32_t num_threads) {
-    if (num_threads == 0) {
-        throw std::invalid_argument("[thread_pool::createThreadPool] error: "
-            "invalid number of threads!");
-    }
-    return std::unique_ptr<ThreadPool>(new ThreadPool(num_threads));
-}
-
-Semaphore::Semaphore(std::uint32_t value)
-        : value_(value) {
-}
-
-void Semaphore::post() {
-    std::unique_lock<std::mutex> lock(mutex_);
-    ++value_;
-    condition_.notify_one();
-}
-
-void Semaphore::wait() {
-    std::unique_lock<std::mutex> lock(mutex_);
-    condition_.wait(lock, [&](){ return value_; });
-    --value_;
-}
-
-ThreadPool::ThreadPool(std::uint32_t num_threads) {
-
-    queue_sem_ = createSemaphore(1);
-    active_sem_ = createSemaphore(0);
-
-    terminate_ = false;
-    for (std::uint32_t i = 0; i < num_threads; ++i) {
-        threads_.emplace_back(ThreadPool::worker_thread, this);
-        thread_identifiers_.emplace_back(threads_.back().get_id());
-    }
-}
-
-ThreadPool::~ThreadPool() {
-
-    terminate_ = true;
-    for (std::uint32_t i = 0; i < threads_.size(); ++i) {
-        active_sem_->post();
-    }
-    for (auto& it: threads_) {
-        it.join();
-    }
-}
-
-void ThreadPool::worker_thread(ThreadPool* thread_pool) {
-
-    while (true) {
-        thread_pool->active_sem_->wait();
-
-        if (thread_pool->terminate_) {
-            break;
-        }
-
-        thread_pool->queue_sem_->wait();
-
-        auto task = std::move(thread_pool->task_queue_.front());
-        thread_pool->task_queue_.pop();
-
-        thread_pool->queue_sem_->post();
-
-        if (thread_pool->terminate_) {
-            break;
-        }
-
-        task();
-    }
-}
-
-}


=====================================
test/semaphore_test.cpp
=====================================
@@ -0,0 +1,37 @@
+// Copyright (c) 2020 Robert Vaser
+
+#include "thread_pool/semaphore.hpp"
+
+#include <thread>  // NOLINT
+
+#include "gtest/gtest.h"
+
+namespace thread_pool {
+namespace test {
+
+TEST(ThreadPoolSemaphoreTest, Barrier) {
+  Semaphore s{0}, b{0};
+  auto check = [&] () -> void {
+    s.Signal();
+    b.Wait();
+  };
+
+  std::thread t1{check};
+  std::thread t2{check};
+  std::thread t3{check};
+
+  s.Wait();
+  s.Wait();
+  s.Wait();
+  // Release barrier
+  b.Signal();
+  b.Signal();
+  b.Signal();
+
+  t1.join();
+  t2.join();
+  t3.join();
+}
+
+}  // namespace test
+}  // namespace thread_pool


=====================================
test/thread_pool_test.cpp
=====================================
@@ -1,108 +1,66 @@
-/*!
- * @file thread_pool_test.cpp
- *
- * @brief Thread_pool unit test source file
- */
+// Copyright (c) 2020 Robert Vaser
 
+#include "thread_pool/thread_pool.hpp"
+
+#include <numeric>
 #include <unordered_map>
 #include <unordered_set>
 
-#include "thread_pool/thread_pool.hpp"
 #include "gtest/gtest.h"
 
-class ThreadPoolTest: public ::testing::Test {
-public:
-    void SetUp() {
-        thread_pool = thread_pool::createThreadPool();
-    }
-
-    void TearDown() {}
-
-    std::unique_ptr<thread_pool::ThreadPool> thread_pool;
-};
+namespace thread_pool {
+namespace test {
 
-TEST(ThreadPoolTest_, CreateThreadPoolError) {
-    try {
-        auto thread_pool = thread_pool::createThreadPool(0);
-    } catch (std::invalid_argument& exception) {
-        EXPECT_STREQ(exception.what(), "[thread_pool::createThreadPool] error: "
-            "invalid number of threads!");
+TEST(ThreadPoolThreadPoolTest, Submit) {
+  std::function<std::uint32_t(std::uint32_t)> fibonacci =
+      [&fibonacci] (std::uint32_t i) -> std::uint32_t {
+    if (i == 1 || i == 2) {
+      return 1;
     }
+    return fibonacci(i - 1) + fibonacci(i - 2);
+  };
+
+  ThreadPool tp{};
+
+  std::vector<std::future<std::uint32_t>> f;
+  for (std::uint32_t i = 0; i < tp.num_threads(); ++i) {
+    f.emplace_back(tp.Submit(fibonacci, 42));
+  }
+  for (auto& it : f) {
+    EXPECT_EQ(267914296, it.get());
+  }
 }
 
-TEST_F(ThreadPoolTest, ParallelCalculation) {
-
-    std::vector<std::vector<std::uint32_t>> data(10);
-    for (auto& it: data) {
-        it.reserve(100000);
-        for (std::uint32_t i = 0; i < 100000; ++i) {
-            it.push_back(i);
-        }
-    }
-
-    auto do_some_calculation = [](std::vector<std::uint32_t>& src) -> void {
-        for (std::uint32_t i = 0; i < src.size() - 1; ++i) {
-            src[i] = (src[i] * src[i + 1]) / (src[i] - src[i + 1] * 3);
-        }
-    };
-
-    std::vector<std::future<void>> thread_futures;
-    for (std::uint32_t i = 0; i < data.size(); ++i) {
-        thread_futures.emplace_back(thread_pool->submit(do_some_calculation,
-            std::ref(data[i])));
-    }
-
-    for (const auto& it: thread_futures) {
-        it.wait();
-    }
+TEST(ThreadPoolThreadPoolTest, ThreadIds) {
+  ThreadPool tp{};
+  EXPECT_EQ(tp.num_threads(), tp.thread_ids().size());
+
+  Semaphore s{0}, b{0};
+  auto check = [&] () -> std::uint32_t {
+    EXPECT_EQ(1, tp.thread_ids().count(std::this_thread::get_id()));
+    s.Signal();
+    b.Wait();
+    return tp.thread_ids().at(std::this_thread::get_id());
+  };
+
+  std::vector<std::future<std::uint32_t>> f;
+  for (std::uint32_t i = 0; i < tp.num_threads(); ++i) {
+    f.emplace_back(tp.Submit(check));
+  }
+
+  for (std::uint32_t i = 0; i < tp.num_threads(); ++i) {
+    s.Wait();
+  }
+  for (std::uint32_t i = 0; i < tp.num_threads(); ++i) {
+    b.Signal();
+  }
+
+  std::unordered_set<std::uint32_t> ts;
+  for (auto& it : f) {
+    ts.emplace(it.get());
+  }
+  EXPECT_EQ(tp.num_threads(), ts.size());
 }
 
-TEST_F(ThreadPoolTest, ThreadIdentifiers) {
-
-    const auto& identifiers = thread_pool->thread_identifiers();
-    std::unordered_map<std::thread::id, std::uint32_t> thread_map;
-    std::uint32_t thread_id = 0;
-    for (const auto& it: identifiers) {
-        thread_map[it] = thread_id++;
-    }
-
-    EXPECT_EQ(thread_id, thread_map.size());
-
-    auto barrier = thread_pool::createSemaphore(0);
-    auto checkpoint = thread_pool::createSemaphore(0);
-    auto check_thread_id = [&barrier, &checkpoint](
-        std::unordered_map<std::thread::id, std::uint32_t>& thread_map) -> std::int32_t {
-
-        checkpoint->post();
-        barrier->wait();
-
-        if (thread_map.count(std::this_thread::get_id()) != 0) {
-            return thread_map[std::this_thread::get_id()];
-        }
-        return -1;
-    };
-
-    std::vector<std::future<std::int32_t>> thread_futures;
-    for (std::uint32_t i = 0; i < thread_id; ++i) {
-        thread_futures.emplace_back(thread_pool->submit(check_thread_id,
-            std::ref(thread_map)));
-    }
-
-    for (std::uint32_t i = 0; i < thread_id; ++i) {
-        checkpoint->wait();
-    }
-    for (std::uint32_t i = 0; i < thread_id; ++i) {
-        barrier->post();
-    }
-
-    std::unordered_set<std::int32_t> thread_identifiers;
-    for (auto& it: thread_futures) {
-        it.wait();
-        thread_identifiers.emplace(it.get());
-    }
-
-    EXPECT_EQ(thread_id, thread_identifiers.size());
-    for (std::uint32_t i = 0; i < thread_id; ++i) {
-        EXPECT_EQ(1U, thread_identifiers.count(i));
-    }
-}
+}  // namespace test
+}  // namespace thread_pool



View it on GitLab: https://salsa.debian.org/med-team/libthread-pool/-/compare/135cd22841082e6b3872c7d4d3d899944abbb73e...797a99f27912ee47043887ff45679e1bcd38b233

-- 
View it on GitLab: https://salsa.debian.org/med-team/libthread-pool/-/compare/135cd22841082e6b3872c7d4d3d899944abbb73e...797a99f27912ee47043887ff45679e1bcd38b233
You're receiving this email because of your account on salsa.debian.org.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/debian-med-commit/attachments/20210119/24d2574c/attachment-0001.html>


More information about the debian-med-commit mailing list