• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 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 AUDIO_TASK_LOOP_H
16 #define AUDIO_TASK_LOOP_H
17 
18 #include <atomic>
19 #include <thread>
20 #include <functional>
21 #include <condition_variable>
22 #include <memory>
23 #include <mutex>
24 #include <string>
25 #include <string_view>
26 #include <queue>
27 namespace OHOS {
28 namespace AudioStandard {
29 class AudioTaskLoop {
30 public:
31     friend class AudioLoopThread;
32 
33     AudioTaskLoop() = default;
34 
35     ~AudioTaskLoop() = default;
36 
37     AudioTaskLoop(const AudioTaskLoop&) = delete;
38     AudioTaskLoop(AudioTaskLoop&&) = delete;
39     AudioTaskLoop& operator=(const AudioTaskLoop&) = delete;
40     AudioTaskLoop& operator=(AudioTaskLoop&&) = delete;
41 
AsyncExit()42     void AsyncExit()
43     {
44         std::lock_guard lock(mutex_);
45         isExited_ = true;
46         cV_.notify_all();
47     }
48 
PostTask(const std::function<void ()> & task)49     void PostTask(const std::function<void()> &task)
50     {
51         std::lock_guard lock(mutex_);
52         tasks_.push(task);
53         cV_.notify_all();
54     }
55 
PostTask(std::function<void ()> && task)56     void PostTask(std::function<void()> &&task)
57     {
58         std::lock_guard lock(mutex_);
59         tasks_.push(std::move(task));
60         cV_.notify_all();
61     }
62 private:
Wait()63     void Wait()
64     {
65         std::unique_lock lock(mutex_);
66         cV_.wait(lock, [this] () {
67             return (isExited_ || !tasks_.empty());
68         });
69     }
70 
ProcessTasks(std::queue<std::function<void ()>> & tasks)71     static void ProcessTasks(std::queue<std::function<void()>> &tasks)
72     {
73         while (!tasks.empty()) {
74             auto &&task = tasks.front();
75             if (task) {
76                 task();
77             }
78             tasks.pop();
79         }
80     }
81 
ProcessTasks()82     void ProcessTasks()
83     {
84         std::queue<std::function<void()>> tasks;
85         {
86             std::lock_guard lock(mutex_);
87             tasks.swap(tasks_);
88         }
89         ProcessTasks(tasks);
90     }
91 
Loop()92     void Loop()
93     {
94         while (true) {
95             Wait();
96             ProcessTasks();
97 
98             std::lock_guard lock(mutex_);
99             if (isExited_ && tasks_.empty()) { return; }
100         }
101     }
102 
103     std::queue<std::function<void()>> tasks_;
104     std::mutex mutex_;
105     std::condition_variable cV_;
106     bool isExited_ = false;
107 };
108 
109 class AudioLoopThread {
110 public:
AudioLoopThread(const std::string & threadName)111     AudioLoopThread(const std::string &threadName)
112     {
113         if (loop_ != nullptr) {
114             auto strongRef = loop_;
115             std::thread loopThread([strongRef] () {
116                 strongRef->Loop();
117             });
118             pthread_setname_np(loopThread.native_handle(), threadName.c_str());
119             loopThread.detach();
120         }
121     }
122 
123     AudioLoopThread(const AudioLoopThread&) = delete;
124     AudioLoopThread(AudioLoopThread&&) = delete;
125     AudioLoopThread& operator=(const AudioLoopThread&) = delete;
126     AudioLoopThread& operator=(AudioLoopThread&&) = delete;
127 
PostTask(const std::function<void ()> & task)128     void PostTask(const std::function<void()> &task)
129     {
130         if (loop_ != nullptr) {
131             loop_->PostTask(task);
132         }
133     }
134 
PostTask(std::function<void ()> && task)135     void PostTask(std::function<void()> &&task)
136     {
137         if (loop_ != nullptr) {
138             loop_->PostTask(std::move(task));
139         }
140     }
141 
~AudioLoopThread()142     ~AudioLoopThread()
143     {
144         if (loop_ != nullptr) {
145             loop_->AsyncExit();
146         }
147     }
148 
149 private:
150     std::shared_ptr<AudioTaskLoop> loop_ = std::make_shared<AudioTaskLoop>();
151 };
152 } // namespace AudioStandard
153 } // namespace OHOS
154 #endif
155