1 /* Thread pool
2 
3    Copyright (C) 2019-2021 Free Software Foundation, Inc.
4 
5    This file is part of GDB.
6 
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11 
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16 
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
19 
20 #ifndef GDBSUPPORT_THREAD_POOL_H
21 #define GDBSUPPORT_THREAD_POOL_H
22 
23 #include <queue>
24 #include <thread>
25 #include <vector>
26 #include <functional>
27 #include <mutex>
28 #include <condition_variable>
29 #include <future>
30 #include "gdbsupport/gdb_optional.h"
31 
32 namespace gdb
33 {
34 
35 /* A thread pool.
36 
37    There is a single global thread pool, see g_thread_pool.  Tasks can
38    be submitted to the thread pool.  They will be processed in worker
39    threads as time allows.  */
40 class thread_pool
41 {
42 public:
43   /* The sole global thread pool.  */
44   static thread_pool *g_thread_pool;
45 
46   ~thread_pool ();
47   DISABLE_COPY_AND_ASSIGN (thread_pool);
48 
49   /* Set the thread count of this thread pool.  By default, no threads
50      are created -- the thread count must be set first.  */
51   void set_thread_count (size_t num_threads);
52 
53   /* Return the number of executing threads.  */
thread_count()54   size_t thread_count () const
55   {
56     return m_thread_count;
57   }
58 
59   /* Post a task to the thread pool.  A future is returned, which can
60      be used to wait for the result.  */
61   std::future<void> post_task (std::function<void ()> &&func);
62 
63 private:
64 
65   thread_pool () = default;
66 
67   /* The callback for each worker thread.  */
68   void thread_function ();
69 
70   /* The current thread count.  */
71   size_t m_thread_count = 0;
72 
73   /* A convenience typedef for the type of a task.  */
74   typedef std::packaged_task<void ()> task;
75 
76   /* The tasks that have not been processed yet.  An optional is used
77      to represent a task.  If the optional is empty, then this means
78      that the receiving thread should terminate.  If the optional is
79      non-empty, then it is an actual task to evaluate.  */
80   std::queue<optional<task>> m_tasks;
81 
82   /* A condition variable and mutex that are used for communication
83      between the main thread and the worker threads.  */
84   std::condition_variable m_tasks_cv;
85   std::mutex m_tasks_mutex;
86 };
87 
88 }
89 
90 #endif /* GDBSUPPORT_THREAD_POOL_H */
91