• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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 #include "group_impl.h"
16 #include "app_log_wrapper.h"
17 namespace OHOS {
18 namespace AppExecFwk {
GroupImpl()19 GroupImpl::GroupImpl()
20 {
21     count_.store(0);
22 }
23 
24 /**
25  * Wait all tasks associated to this group to be done.
26  *
27  * @param timeout is the max waiting time for jobs in group execute, in ms.
28  *
29  * @return true if successfully wait.
30  */
AwaitAllTasks(long timeout)31 bool GroupImpl::AwaitAllTasks(long timeout)
32 {
33     APP_LOGI("GroupImpl::AwaitAllTasks start");
34     if (count_.load() == 0) {
35         APP_LOGI("GroupImpl::AwaitAllTasks number of count_ is zero");
36         return true;
37     }
38     if (timeout <= 0L) {
39         APP_LOGW("GroupImpl::AwaitAllTasks timeout<=0");
40         return false;
41     }
42     bool success = true;
43     std::unique_lock<std::mutex> lock(dataMutex_);
44     while (count_.load() > 0) {
45         if (condition_.wait_for(lock, std::chrono::milliseconds(timeout)) == std::cv_status::timeout) {
46             success = false;
47             APP_LOGI("GroupImpl::awaitAllTasks timeout");
48             break;
49         }
50         APP_LOGI("GroupImpl::awaitAllTasks success");
51     }
52     APP_LOGI("GroupImpl::AwaitAllTasks end");
53     return success;
54 }
55 
56 /**
57  * @brief Associates a task to this group.
58  *
59  */
Associate()60 void GroupImpl::Associate()
61 {
62     APP_LOGI("GroupImpl::Associate called  add a task");
63     count_.fetch_add(1);
64 }
65 /**
66  * @brief Notify group that a task is done or canceled.
67  *
68  */
NotifyTaskDone()69 void GroupImpl::NotifyTaskDone()
70 {
71     APP_LOGI("GroupImpl::NotifyTaskDone start. Called notify a task to complete");
72     count_.fetch_sub(1);
73     int newValue = count_.load();
74     if (newValue > 0) {
75         return;
76     }
77     std::unique_lock<std::mutex> lock(dataMutex_);
78     condition_.notify_all();
79     DrainNotifications();
80 
81     APP_LOGI("GroupImpl::NotifyTaskDone end");
82 }
83 /**
84  * @brief Adds the |notification| to notification list.
85  * If all tasks are already done, |notification| will immediately be called on current thread.
86  * Attention: If tasks are added just this time, it may not be considered.
87  *
88  * @param notification Called when all tasks done.
89  *
90  */
AddNotification(const std::shared_ptr<Runnable> & notification)91 bool GroupImpl::AddNotification(const std::shared_ptr<Runnable> &notification)
92 {
93     APP_LOGI("GroupImpl::AddNotification start");
94     if (count_.load() != 0) {
95         std::unique_lock<std::mutex> lock(dataMutex_);
96         if (notifications_.size() == MAX_TASK) {
97             APP_LOGW("GroupImpl::AddNotification called maximun number of tasks exceeded");
98             return false;
99         }
100         if (count_.load() != 0) {
101             APP_LOGI("GroupImpl::AddNotification called add task");
102             notifications_.push_back(notification);
103             return true;
104         }
105     }
106     if (notification) {
107         APP_LOGI("GroupImpl::AddNotification notification execute");
108         (*notification)();
109     }
110     APP_LOGI("GroupImpl::AddNotification end");
111     return true;
112 }
113 /**
114  * @brief Notify all tasks and remove from queue.
115  * Attention: Notifications added after all tasks done is not guaranteed.
116  */
DrainNotifications()117 void GroupImpl::DrainNotifications()
118 {
119     APP_LOGI("GroupImpl::DrainNotifications start");
120     while (notifications_.size() > 0) {
121         std::shared_ptr<Runnable> notification = notifications_.front();
122         notifications_.pop_front();
123         APP_LOGI("GroupImpl::DrainNotifications execute notification");
124         (*notification)();
125     }
126     APP_LOGI("GroupImpl::DrainNotifications end");
127 }
128 
129 }  // namespace AppExecFwk
130 }  // namespace OHOS
131