[med-svn] [Git][med-team/libthread-pool][upstream] New upstream version 3.0.2

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



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


Commits:
1d3149f9 by Michael R. Crusoe at 2021-01-18T16:54:41+01:00
New upstream version 3.0.2
- - - - -


9 changed files:

- .gitmodules
- .travis.yml
- CMakeLists.txt
- README.md
- + 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)..


=====================================
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/-/commit/1d3149f9fc26c1450e5a79088bc2b477f4c8eaf8

-- 
View it on GitLab: https://salsa.debian.org/med-team/libthread-pool/-/commit/1d3149f9fc26c1450e5a79088bc2b477f4c8eaf8
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/3c69f52b/attachment-0001.html>


More information about the debian-med-commit mailing list