blob: 001c3d67906b052f9deb1e8297fc2430b3b412a8 [file] [log] [blame]
Yifan Honge2dadf02017-02-14 15:43:31 -08001/*
2 * Copyright (C) 2016 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 <condition_variable>
18#include <chrono>
19#include <functional>
20#include <mutex>
21#include <thread>
22
23#include <hidl/Status.h>
24
25namespace android {
26namespace lshal {
27
28static constexpr std::chrono::milliseconds IPC_CALL_WAIT{500};
29
30class BackgroundTaskState {
31public:
32 BackgroundTaskState(){}
33 void notify() {
34 std::unique_lock<std::mutex> lock(mMutex);
35 mFinished = true;
36 lock.unlock();
37 mCondVar.notify_all();
38 }
39 template<class C, class D>
40 bool wait(std::chrono::time_point<C, D> end) {
41 std::unique_lock<std::mutex> lock(mMutex);
42 mCondVar.wait_until(lock, end, [this](){ return this->mFinished; });
43 return mFinished;
44 }
45private:
46 std::mutex mMutex;
47 std::condition_variable mCondVar;
48 bool mFinished = false;
49};
50
51template<class R, class P>
52bool timeout(std::chrono::duration<R, P> delay, const std::function<void(void)> &func) {
53 auto now = std::chrono::system_clock::now();
54 BackgroundTaskState state{};
55 std::thread t([&state, &func] {
56 func();
57 state.notify();
58 });
59 t.detach();
60 bool success = state.wait(now + delay);
61 return success;
62}
63
64template<class Function, class I, class... Args>
65typename std::result_of<Function(I *, Args...)>::type
66timeoutIPC(const sp<I> &interfaceObject, Function &&func, Args &&... args) {
67 using ::android::hardware::Status;
68 typename std::result_of<Function(I *, Args...)>::type ret{Status::ok()};
69 auto boundFunc = std::bind(std::forward<Function>(func),
70 interfaceObject.get(), std::forward<Args>(args)...);
71 bool success = timeout(IPC_CALL_WAIT, [&ret, &boundFunc] {
Yifan Hong38903c02017-02-17 13:38:47 -080072 ret = std::move(boundFunc());
Yifan Honge2dadf02017-02-14 15:43:31 -080073 });
74 if (!success) {
75 return Status::fromStatusT(TIMED_OUT);
76 }
77 return ret;
78}
79
80} // namespace lshal
81} // namespace android