DiscordCoreAPI
A Discord bot library written in C++, with custom asynchronous coroutines.
Loading...
Searching...
No Matches
ThreadPool.hpp
Go to the documentation of this file.
1/*
2 DiscordCoreAPI, A bot library for Discord, written in C++, and featuring explicit multithreading through the usage of custom, asynchronous C++ CoRoutines.
3
4 Copyright 2021, 2022 Chris M. (RealTimeChris)
5
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
10
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public
17 License along with this library; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
19 USA
20*/
21/// ThreadPool.hpp - Header for the "Thread-Pool" related stuff.
22/// Dec 18, 2021
23/// https://discordcoreapi.com
24/// \file ThreadPool.hpp
25
26#pragma once
27
30#include <coroutine>
31
32namespace DiscordCoreAPI {
33 /**
34 * \addtogroup utilities
35 * @{
36 */
37
38 template<typename... ArgTypes> using TimeElapsedHandler = std::function<void(ArgTypes...)>;
39
40 using TimeElapsedHandlerNoArgs = std::function<void(void)>;
41
42 const double percentage{ 10.0f / 100.0f };
43
44 class DiscordCoreAPI_Dll ThreadPool {
45 public:
46 ThreadPool& operator=(const ThreadPool&) = delete;
47
48 ThreadPool(const ThreadPool&) = delete;
49
50 ThreadPool() noexcept = default;
51
52 static std::string storeThread(TimeElapsedHandlerNoArgs timeElapsedHandler, int64_t timeInterval);
53
54 template<typename... ArgTypes> static void executeFunctionAfterTimePeriod(TimeElapsedHandler<ArgTypes...> timeElapsedHandler,
55 int64_t timeDelay, bool blockForCompletion, ArgTypes... args) {
56 std::jthread thread = std::jthread([=](std::stop_token token) {
57 StopWatch stopWatch{ Milliseconds{ timeDelay } };
58 stopWatch.resetTimer();
59 if (static_cast<int64_t>(std::ceil(static_cast<double>(timeDelay) * percentage)) <= timeDelay &&
60 static_cast<int64_t>(std::ceil(static_cast<double>(timeDelay) * percentage)) > 0) {
61 std::this_thread::sleep_for(Milliseconds{ static_cast<int64_t>(std::ceil(static_cast<double>(timeDelay) * percentage)) });
62 }
63 while (!stopWatch.hasTimePassed() && !token.stop_requested()) {
64 std::this_thread::sleep_for(1ms);
65 }
66 if (token.stop_requested()) {
67 return;
68 }
69 timeElapsedHandler(args...);
70 if (token.stop_requested()) {
71 return;
72 }
73 });
74 if (blockForCompletion) {
75 if (thread.joinable()) {
76 thread.join();
77 }
78 } else if (thread.joinable()) {
79 thread.detach();
80 }
81 }
82
83 void stopThread(const std::string& key);
84
85 ~ThreadPool() noexcept = default;
86
87 protected:
88 static std::unordered_map<std::string, std::jthread> threads;
89 };
90}
91
92namespace DiscordCoreInternal {
93
94 struct DiscordCoreAPI_Dll WorkerThread {
95 WorkerThread& operator=(WorkerThread&& other) noexcept;
96
97 WorkerThread() noexcept = default;
98
99 ~WorkerThread() noexcept = default;
100
101 std::atomic_bool areWeCurrentlyWorking{};
102 std::jthread thread{};
103 };
104
105 class DiscordCoreAPI_Dll CoRoutineThreadPool {
106 public:
108
109 CoRoutineThreadPool();
110
111 void submitTask(std::coroutine_handle<> coro) noexcept;
112
113 protected:
114 std::unordered_map<int64_t, WorkerThread> workerThreads{};
115 std::deque<std::coroutine_handle<>> coroutineHandles{};
116 const std::atomic_int64_t threadCount{};
117 std::atomic_int64_t coroHandleCount{};
118 std::shared_mutex workerAccessMutex{};
119 std::atomic_int64_t currentCount{};
120 std::atomic_int64_t currentIndex{};
121 std::mutex coroHandleAccessMutex{};
122
123 void threadFunction(std::stop_token token, int64_t index);
124 };
125 /**@}*/
126}
The main namespace for this library.
DiscordCoreClient - The main class for this library.