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