xref: /aosp_15_r20/external/perfetto/src/base/threading/thread_pool.cc (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
1 /*
2  * Copyright (C) 2023 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "perfetto/ext/base/threading/thread_pool.h"
18 #include <mutex>
19 #include <thread>
20 
21 namespace perfetto {
22 namespace base {
23 
ThreadPool(uint32_t thread_count)24 ThreadPool::ThreadPool(uint32_t thread_count) {
25   for (uint32_t i = 0; i < thread_count; ++i) {
26     threads_.emplace_back(std::bind(&ThreadPool::RunThreadLoop, this));
27   }
28 }
29 
~ThreadPool()30 ThreadPool::~ThreadPool() {
31   {
32     std::lock_guard<std::mutex> guard(mutex_);
33     quit_ = true;
34   }
35   thread_waiter_.notify_all();
36   for (auto& thread : threads_) {
37     thread.join();
38   }
39 }
40 
PostTask(std::function<void ()> fn)41 void ThreadPool::PostTask(std::function<void()> fn) {
42   std::lock_guard<std::mutex> guard(mutex_);
43   pending_tasks_.emplace_back(std::move(fn));
44   if (thread_waiting_count_ == 0) {
45     return;
46   }
47   thread_waiter_.notify_one();
48 }
49 
RunThreadLoop()50 void ThreadPool::RunThreadLoop() PERFETTO_NO_THREAD_SAFETY_ANALYSIS {
51   // 'std::unique_lock' lock doesn't work well with thread annotations
52   // (see https://github.com/llvm/llvm-project/issues/63239),
53   // so we suppress thread safety static analysis for this method.
54   for (;;) {
55     std::function<void()> fn;
56     {
57       std::unique_lock<std::mutex> guard(mutex_);
58       if (quit_) {
59         return;
60       }
61       if (pending_tasks_.empty()) {
62         thread_waiting_count_++;
63         thread_waiter_.wait(guard,
64                             [this]() PERFETTO_EXCLUSIVE_LOCKS_REQUIRED(mutex_) {
65                               return quit_ || !pending_tasks_.empty();
66                             });
67         thread_waiting_count_--;
68         continue;
69       }
70       fn = std::move(pending_tasks_.front());
71       pending_tasks_.pop_front();
72     }
73     fn();
74   }
75 }
76 
77 }  // namespace base
78 }  // namespace perfetto
79