• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 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 
16 #include "medialibrary_async_worker.h"
17 
18 #include <pthread.h>
19 #include "media_log.h"
20 
21 using namespace std;
22 
23 namespace OHOS {
24 namespace Media {
25 static const int32_t SUCCESS = 0;
26 static const int32_t BG_SLEEP_COUNT = 500;
27 static const int32_t FG_SLEEP_COUNT = 50;
28 static const int32_t REST_FOR_MILLISECOND = 20;
29 static const int32_t REST_FOR_LONG_SECOND = 2;
30 static const int32_t THREAD_NUM = 2;
31 shared_ptr<MediaLibraryAsyncWorker> MediaLibraryAsyncWorker::asyncWorkerInstance_{nullptr};
32 mutex MediaLibraryAsyncWorker::instanceLock_;
33 
GetInstance()34 shared_ptr<MediaLibraryAsyncWorker> MediaLibraryAsyncWorker::GetInstance()
35 {
36     if (asyncWorkerInstance_ == nullptr) {
37         lock_guard<mutex> lockGuard(instanceLock_);
38         asyncWorkerInstance_ = shared_ptr<MediaLibraryAsyncWorker>(new MediaLibraryAsyncWorker());
39         if (asyncWorkerInstance_ != nullptr) {
40             asyncWorkerInstance_->Init();
41         }
42     }
43     return asyncWorkerInstance_;
44 }
45 
MediaLibraryAsyncWorker()46 MediaLibraryAsyncWorker::MediaLibraryAsyncWorker() : isThreadRunning_(false), doneTotal_(0)
47 {}
48 
~MediaLibraryAsyncWorker()49 MediaLibraryAsyncWorker::~MediaLibraryAsyncWorker()
50 {
51     isThreadRunning_ = false;
52     bgWorkCv_.notify_all();
53     for (auto &thread : threads_) {
54         if (thread.joinable()) {
55             thread.join();
56         }
57     }
58     asyncWorkerInstance_ = nullptr;
59 }
60 
Init()61 void MediaLibraryAsyncWorker::Init()
62 {
63     isThreadRunning_ = true;
64     doneTotal_ = 0;
65     for (auto i = 0; i < THREAD_NUM; i++) {
66         threads_.emplace_back(bind(&MediaLibraryAsyncWorker::StartWorker, this, i));
67     }
68 }
69 
Interrupt()70 void MediaLibraryAsyncWorker::Interrupt()
71 {
72     ReleaseBgTask();
73 }
74 
Stop()75 void MediaLibraryAsyncWorker::Stop()
76 {
77     ReleaseBgTask();
78     ReleaseFgTask();
79 }
80 
AddTask(const shared_ptr<MediaLibraryAsyncTask> & task,bool isFg)81 int32_t MediaLibraryAsyncWorker::AddTask(const shared_ptr<MediaLibraryAsyncTask> &task, bool isFg)
82 {
83     if (isFg) {
84         lock_guard<mutex> lockGuard(fgTaskLock_);
85         fgTaskQueue_.push(task);
86     } else {
87         lock_guard<mutex> lockGuard(bgTaskLock_);
88         bgTaskQueue_.push(task);
89     }
90 
91     bgWorkCv_.notify_one();
92     return SUCCESS;
93 }
94 
GetFgTask()95 shared_ptr<MediaLibraryAsyncTask> MediaLibraryAsyncWorker::GetFgTask()
96 {
97     lock_guard<mutex> lockGuard(fgTaskLock_);
98     if (fgTaskQueue_.empty()) {
99         return nullptr;
100     }
101     shared_ptr<MediaLibraryAsyncTask> task = fgTaskQueue_.front();
102     fgTaskQueue_.pop();
103     return task;
104 }
105 
ReleaseFgTask()106 void MediaLibraryAsyncWorker::ReleaseFgTask()
107 {
108     lock_guard<mutex> lockGuard(fgTaskLock_);
109     std::queue<std::shared_ptr<MediaLibraryAsyncTask>> tmp;
110     fgTaskQueue_.swap(tmp);
111 }
112 
GetBgTask()113 shared_ptr<MediaLibraryAsyncTask> MediaLibraryAsyncWorker::GetBgTask()
114 {
115     lock_guard<mutex> lockGuard(bgTaskLock_);
116     if (bgTaskQueue_.empty()) {
117         return nullptr;
118     }
119     shared_ptr<MediaLibraryAsyncTask> task = bgTaskQueue_.front();
120     bgTaskQueue_.pop();
121     return task;
122 }
123 
ReleaseBgTask()124 void MediaLibraryAsyncWorker::ReleaseBgTask()
125 {
126     lock_guard<mutex> lockGuard(bgTaskLock_);
127     std::queue<std::shared_ptr<MediaLibraryAsyncTask>> tmp;
128     bgTaskQueue_.swap(tmp);
129 }
130 
IsFgQueueEmpty()131 bool MediaLibraryAsyncWorker::IsFgQueueEmpty()
132 {
133     lock_guard<mutex> lock_Guard(fgTaskLock_);
134     return fgTaskQueue_.empty();
135 }
136 
IsBgQueueEmpty()137 bool MediaLibraryAsyncWorker::IsBgQueueEmpty()
138 {
139     lock_guard<mutex> lock_Guard(bgTaskLock_);
140     return bgTaskQueue_.empty();
141 }
142 
WaitForTask()143 void MediaLibraryAsyncWorker::WaitForTask()
144 {
145     std::unique_lock<std::mutex> lock(bgWorkLock_);
146     bgWorkCv_.wait(lock,
147         [this]() { return !isThreadRunning_ || !IsFgQueueEmpty() || !IsBgQueueEmpty(); });
148 }
149 
SleepFgWork()150 void MediaLibraryAsyncWorker::SleepFgWork()
151 {
152     if ((doneTotal_.load() % FG_SLEEP_COUNT) == 0) {
153         this_thread::sleep_for(chrono::milliseconds(REST_FOR_MILLISECOND));
154     }
155 }
156 
SleepBgWork()157 void MediaLibraryAsyncWorker::SleepBgWork()
158 {
159     this_thread::sleep_for(chrono::milliseconds(REST_FOR_MILLISECOND));
160     if ((doneTotal_.load() % BG_SLEEP_COUNT) == 0) {
161         this_thread::sleep_for(chrono::seconds(REST_FOR_LONG_SECOND));
162     }
163 }
164 
StartWorker(int num)165 void MediaLibraryAsyncWorker::StartWorker(int num)
166 {
167     string name("MediaLibraryAsyncWorker");
168     name.append(to_string(num));
169     pthread_setname_np(pthread_self(), name.c_str());
170     while (true) {
171         WaitForTask();
172         if (!isThreadRunning_) {
173             return;
174         }
175         if (!IsFgQueueEmpty()) {
176             shared_ptr<MediaLibraryAsyncTask> fgTask = GetFgTask();
177             if (fgTask != nullptr) {
178                 fgTask->executor_(fgTask->data_);
179                 fgTask = nullptr;
180                 doneTotal_++;
181                 SleepFgWork();
182             }
183         } else if (!IsBgQueueEmpty()) {
184             shared_ptr<MediaLibraryAsyncTask> bgTask = GetBgTask();
185             if (bgTask != nullptr) {
186                 bgTask->executor_(bgTask->data_);
187                 bgTask = nullptr;
188                 doneTotal_++;
189                 SleepBgWork();
190             }
191         }
192     }
193 }
194 } // namespace Media
195 } // namespace OHOS
196