1/*
2 * Copyright (c) 2021-2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15#ifndef THREAD_POOL_H
16#define THREAD_POOL_H
17
18#include "nocopyable.h"
19
20#include <thread>
21#include <mutex>
22#include <functional>
23#include <string>
24#include <condition_variable>
25#include <deque>
26#include <vector>
27
28namespace OHOS {
29/**
30 * @brief Provides interfaces for thread-safe thread pool operations.
31 *
32 * The thread-safe is for the thread pool, but not for the threads in the pool.
33 * A task queue and a thread group are under control. Users add tasks to the
34 * task queue, and the thread group executes the tasks in the task queue.
35 */
36class ThreadPool : public NoCopyable {
37public:
38    typedef std::function<void()> Task;
39
40    /**
41     * @brief Creates a thread pool and names the threads in the pool.
42     *
43     * @param name Indicates the prefix of the names of the threads in pool.
44     * The names of threads in the pool are in the <b>name</b> + No format.
45     * The thread name is a meaningful C language string, whose length is
46     * restricted to 16 characters including the terminating null byte ('\0').
47     * Pay attention to the name length when setting this parameter.
48     * For example, if the number of threads in the pool is less than 10,
49     * the name length cannot exceed 14 characters.
50     */
51    explicit ThreadPool(const std::string &name = std::string());
52    ~ThreadPool() override;
53
54    /**
55     * @brief Starts a given number of threads, which will execute
56     * the tasks in a task queue.
57     *
58     * @param threadsNum Indicates the number of threads to start.
59     */
60    uint32_t Start(int threadsNum);
61    /**
62     * @brief Stops the thread pool.
63     */
64    void Stop();
65    /**
66     * @brief Adds a task to the task queue.
67     *
68     * If <b>Start()</b> has never been called, the task will be executed
69     * immediately.
70     *
71     * @param f Indicates the task to add.
72     */
73    void AddTask(const Task& f);
74    /**
75     * @brief Sets the maximum number of tasks in the task queue.
76     *
77     * @param maxSize Indicates the maximum number of tasks to set.
78     */
79    void SetMaxTaskNum(size_t maxSize) { maxTaskNum_ = maxSize; }
80
81    // for testability
82    /**
83     * @brief Obtains the maximum number of tasks in the task queue.
84     */
85    size_t GetMaxTaskNum() const { return maxTaskNum_; }
86    /**
87     * @brief Obtains the number of tasks in the task queue.
88     */
89    size_t GetCurTaskNum();
90    /**
91     * @brief Obtains the number of threads in the pool.
92     */
93    size_t GetThreadsNum() const { return threads_.size(); }
94    /**
95     * @brief Obtains the name of the thread pool.
96     */
97    std::string GetName() const { return myName_; }
98
99private:
100    // If the number of tasks in the queue reaches the maximum set by maxQueueSize, the thread pool is full load.
101    bool Overloaded() const;
102    void WorkInThread(); // main function in each thread.
103    Task ScheduleTask(); // fetch a task from the queue and execute it
104
105private:
106    std::string myName_;
107    std::mutex mutex_;
108    std::condition_variable hasTaskToDo_;
109    std::condition_variable acceptNewTask_;
110    std::vector<std::thread> threads_;
111    std::deque<Task> tasks_;
112    size_t maxTaskNum_;
113    bool running_;
114};
115
116} // namespace OHOS
117
118#endif
119
120