| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169 |
- // MIT License
- //
- // Copyright (c) 2016-2017 Simon Ninon <simon.ninon@gmail.com>
- //
- // Permission is hereby granted, free of charge, to any person obtaining a copy
- // of this software and associated documentation files (the "Software"), to deal
- // in the Software without restriction, including without limitation the rights
- // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- // copies of the Software, and to permit persons to whom the Software is
- // furnished to do so, subject to the following conditions:
- //
- // The above copyright notice and this permission notice shall be included in all
- // copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- // SOFTWARE.
- #pragma once
- #include <atomic>
- #include <condition_variable>
- #include <functional>
- #include <list>
- #include <mutex>
- #include <queue>
- #include <thread>
- #include <vector>
- namespace tacopie {
- namespace utils {
- //!
- //! basic thread pool used to push async tasks from the io_service
- //!
- class thread_pool {
- public:
- //!
- //! ctor
- //! created the worker thread that start working immediately
- //!
- //! \param nb_threads number of threads to start the thread pool
- //!
- explicit thread_pool(std::size_t nb_threads);
- //! dtor
- ~thread_pool(void);
- //! copy ctor
- thread_pool(const thread_pool&) = delete;
- //! assignment operator
- thread_pool& operator=(const thread_pool&) = delete;
- public:
- //!
- //! task typedef
- ///! simply a callable taking no parameter
- //!
- typedef std::function<void()> task_t;
- //!
- //! add tasks to thread pool
- //! task is enqueued and will be executed whenever all previously executed tasked have been executed (or are currently being executed)
- //!
- //! \param task task to be executed by the threadpool
- //!
- void add_task(const task_t& task);
- //!
- //! same as add_task
- //!
- //! \param task task to be executed by the threadpool
- //! \return current instance
- //!
- thread_pool& operator<<(const task_t& task);
- //!
- //! stop the thread pool and wait for workers completion
- //! if some tasks are pending, they won't be executed
- //!
- void stop(void);
- public:
- //!
- //! \return whether the thread_pool is running or not
- //!
- bool is_running(void) const;
- public:
- //!
- //! reset the number of threads working in the thread pool
- //! this can be safely called at runtime and can be useful if you need to adjust the number of workers
- //!
- //! this function returns immediately, but change might be applied in the background
- //! that is, increasing number of threads will spwan new threads directly from this function (but they may take a while to start)
- //! moreover, shrinking the number of threads can only be applied in the background to make sure to not stop some threads in the middle of their task
- //!
- //! changing number of workers do not affect tasks to be executed and tasks currently being executed
- //!
- //! \param nb_threads number of threads
- //!
- void set_nb_threads(std::size_t nb_threads);
- private:
- //!
- //! worker main loop
- //!
- void run(void);
- //!
- //! retrieve a new task
- //! fetch the first element in the queue, or wait if no task are available
- //!
- //! \return a pair <stopped, task>
- //! pair.first indicated whether the thread has been marked for stop and should return immediately
- //! pair.second contains the task to be executed
- //!
- std::pair<bool, task_t> fetch_task_or_stop(void);
- //!
- //! \return whether the thread should stop or not
- //!
- bool should_stop(void) const;
- private:
- //!
- //! threads
- //!
- std::list<std::thread> m_workers;
- //!
- //! number of threads allowed
- //!
- std::atomic<std::size_t> m_max_nb_threads = ATOMIC_VAR_INIT(0);
- //!
- //! current number of running threads
- //!
- std::atomic<std::size_t> m_nb_running_threads = ATOMIC_VAR_INIT(0);
- //!
- //! whether the thread_pool should stop or not
- //!
- std::atomic<bool> m_should_stop = ATOMIC_VAR_INIT(false);
- //!
- //! tasks
- //!
- std::queue<task_t> m_tasks;
- //!
- //! tasks thread safety
- //!
- std::mutex m_tasks_mtx;
- //!
- //! task condvar to sync on tasks changes
- //!
- std::condition_variable m_tasks_condvar;
- };
- } // namespace utils
- } // namespace tacopie
|