Timeout.h revision a57dffb151145529e71b22a8d7f985bc1de105f4
1e2dadf0c4f132d3a39309f4e274f1a35f7caaaedYifan Hong/* 2e2dadf0c4f132d3a39309f4e274f1a35f7caaaedYifan Hong * Copyright (C) 2016 The Android Open Source Project 3e2dadf0c4f132d3a39309f4e274f1a35f7caaaedYifan Hong * 4e2dadf0c4f132d3a39309f4e274f1a35f7caaaedYifan Hong * Licensed under the Apache License, Version 2.0 (the "License"); 5e2dadf0c4f132d3a39309f4e274f1a35f7caaaedYifan Hong * you may not use this file except in compliance with the License. 6e2dadf0c4f132d3a39309f4e274f1a35f7caaaedYifan Hong * You may obtain a copy of the License at 7e2dadf0c4f132d3a39309f4e274f1a35f7caaaedYifan Hong * 8e2dadf0c4f132d3a39309f4e274f1a35f7caaaedYifan Hong * http://www.apache.org/licenses/LICENSE-2.0 9e2dadf0c4f132d3a39309f4e274f1a35f7caaaedYifan Hong * 10e2dadf0c4f132d3a39309f4e274f1a35f7caaaedYifan Hong * Unless required by applicable law or agreed to in writing, software 11e2dadf0c4f132d3a39309f4e274f1a35f7caaaedYifan Hong * distributed under the License is distributed on an "AS IS" BASIS, 12e2dadf0c4f132d3a39309f4e274f1a35f7caaaedYifan Hong * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13e2dadf0c4f132d3a39309f4e274f1a35f7caaaedYifan Hong * See the License for the specific language governing permissions and 14e2dadf0c4f132d3a39309f4e274f1a35f7caaaedYifan Hong * limitations under the License. 15e2dadf0c4f132d3a39309f4e274f1a35f7caaaedYifan Hong */ 16e2dadf0c4f132d3a39309f4e274f1a35f7caaaedYifan Hong 17e2dadf0c4f132d3a39309f4e274f1a35f7caaaedYifan Hong#include <condition_variable> 18e2dadf0c4f132d3a39309f4e274f1a35f7caaaedYifan Hong#include <chrono> 19e2dadf0c4f132d3a39309f4e274f1a35f7caaaedYifan Hong#include <functional> 20e2dadf0c4f132d3a39309f4e274f1a35f7caaaedYifan Hong#include <mutex> 21e2dadf0c4f132d3a39309f4e274f1a35f7caaaedYifan Hong#include <thread> 22e2dadf0c4f132d3a39309f4e274f1a35f7caaaedYifan Hong 23e2dadf0c4f132d3a39309f4e274f1a35f7caaaedYifan Hong#include <hidl/Status.h> 24e2dadf0c4f132d3a39309f4e274f1a35f7caaaedYifan Hong 25e2dadf0c4f132d3a39309f4e274f1a35f7caaaedYifan Hongnamespace android { 26e2dadf0c4f132d3a39309f4e274f1a35f7caaaedYifan Hongnamespace lshal { 27e2dadf0c4f132d3a39309f4e274f1a35f7caaaedYifan Hong 28e2dadf0c4f132d3a39309f4e274f1a35f7caaaedYifan Hongstatic constexpr std::chrono::milliseconds IPC_CALL_WAIT{500}; 29e2dadf0c4f132d3a39309f4e274f1a35f7caaaedYifan Hong 30e2dadf0c4f132d3a39309f4e274f1a35f7caaaedYifan Hongclass BackgroundTaskState { 31e2dadf0c4f132d3a39309f4e274f1a35f7caaaedYifan Hongpublic: 32a57dffb151145529e71b22a8d7f985bc1de105f4Yifan Hong BackgroundTaskState(std::function<void(void)> &&func) 33a57dffb151145529e71b22a8d7f985bc1de105f4Yifan Hong : mFunc(std::forward<decltype(func)>(func)) {} 34e2dadf0c4f132d3a39309f4e274f1a35f7caaaedYifan Hong void notify() { 35e2dadf0c4f132d3a39309f4e274f1a35f7caaaedYifan Hong std::unique_lock<std::mutex> lock(mMutex); 36e2dadf0c4f132d3a39309f4e274f1a35f7caaaedYifan Hong mFinished = true; 37e2dadf0c4f132d3a39309f4e274f1a35f7caaaedYifan Hong lock.unlock(); 38e2dadf0c4f132d3a39309f4e274f1a35f7caaaedYifan Hong mCondVar.notify_all(); 39e2dadf0c4f132d3a39309f4e274f1a35f7caaaedYifan Hong } 40e2dadf0c4f132d3a39309f4e274f1a35f7caaaedYifan Hong template<class C, class D> 41e2dadf0c4f132d3a39309f4e274f1a35f7caaaedYifan Hong bool wait(std::chrono::time_point<C, D> end) { 42e2dadf0c4f132d3a39309f4e274f1a35f7caaaedYifan Hong std::unique_lock<std::mutex> lock(mMutex); 43e2dadf0c4f132d3a39309f4e274f1a35f7caaaedYifan Hong mCondVar.wait_until(lock, end, [this](){ return this->mFinished; }); 44e2dadf0c4f132d3a39309f4e274f1a35f7caaaedYifan Hong return mFinished; 45e2dadf0c4f132d3a39309f4e274f1a35f7caaaedYifan Hong } 46a57dffb151145529e71b22a8d7f985bc1de105f4Yifan Hong void operator()() { 47a57dffb151145529e71b22a8d7f985bc1de105f4Yifan Hong mFunc(); 48a57dffb151145529e71b22a8d7f985bc1de105f4Yifan Hong } 49e2dadf0c4f132d3a39309f4e274f1a35f7caaaedYifan Hongprivate: 50e2dadf0c4f132d3a39309f4e274f1a35f7caaaedYifan Hong std::mutex mMutex; 51e2dadf0c4f132d3a39309f4e274f1a35f7caaaedYifan Hong std::condition_variable mCondVar; 52e2dadf0c4f132d3a39309f4e274f1a35f7caaaedYifan Hong bool mFinished = false; 53a57dffb151145529e71b22a8d7f985bc1de105f4Yifan Hong std::function<void(void)> mFunc; 54e2dadf0c4f132d3a39309f4e274f1a35f7caaaedYifan Hong}; 55e2dadf0c4f132d3a39309f4e274f1a35f7caaaedYifan Hong 56a57dffb151145529e71b22a8d7f985bc1de105f4Yifan Hongvoid *callAndNotify(void *data) { 57a57dffb151145529e71b22a8d7f985bc1de105f4Yifan Hong BackgroundTaskState &state = *static_cast<BackgroundTaskState *>(data); 58a57dffb151145529e71b22a8d7f985bc1de105f4Yifan Hong state(); 59a57dffb151145529e71b22a8d7f985bc1de105f4Yifan Hong state.notify(); 60a57dffb151145529e71b22a8d7f985bc1de105f4Yifan Hong return NULL; 61a57dffb151145529e71b22a8d7f985bc1de105f4Yifan Hong} 62a57dffb151145529e71b22a8d7f985bc1de105f4Yifan Hong 63e2dadf0c4f132d3a39309f4e274f1a35f7caaaedYifan Hongtemplate<class R, class P> 64a57dffb151145529e71b22a8d7f985bc1de105f4Yifan Hongbool timeout(std::chrono::duration<R, P> delay, std::function<void(void)> &&func) { 65e2dadf0c4f132d3a39309f4e274f1a35f7caaaedYifan Hong auto now = std::chrono::system_clock::now(); 66a57dffb151145529e71b22a8d7f985bc1de105f4Yifan Hong BackgroundTaskState state{std::forward<decltype(func)>(func)}; 67a57dffb151145529e71b22a8d7f985bc1de105f4Yifan Hong pthread_t thread; 68a57dffb151145529e71b22a8d7f985bc1de105f4Yifan Hong if (pthread_create(&thread, NULL, callAndNotify, &state)) { 69a57dffb151145529e71b22a8d7f985bc1de105f4Yifan Hong std::cerr << "FATAL: could not create background thread." << std::endl; 70a57dffb151145529e71b22a8d7f985bc1de105f4Yifan Hong return false; 71a57dffb151145529e71b22a8d7f985bc1de105f4Yifan Hong } 72e2dadf0c4f132d3a39309f4e274f1a35f7caaaedYifan Hong bool success = state.wait(now + delay); 73a57dffb151145529e71b22a8d7f985bc1de105f4Yifan Hong if (!success) { 74a57dffb151145529e71b22a8d7f985bc1de105f4Yifan Hong pthread_kill(thread, SIGINT); 75a57dffb151145529e71b22a8d7f985bc1de105f4Yifan Hong } 76a57dffb151145529e71b22a8d7f985bc1de105f4Yifan Hong pthread_join(thread, NULL); 77e2dadf0c4f132d3a39309f4e274f1a35f7caaaedYifan Hong return success; 78e2dadf0c4f132d3a39309f4e274f1a35f7caaaedYifan Hong} 79e2dadf0c4f132d3a39309f4e274f1a35f7caaaedYifan Hong 80e2dadf0c4f132d3a39309f4e274f1a35f7caaaedYifan Hongtemplate<class Function, class I, class... Args> 81e2dadf0c4f132d3a39309f4e274f1a35f7caaaedYifan Hongtypename std::result_of<Function(I *, Args...)>::type 82e2dadf0c4f132d3a39309f4e274f1a35f7caaaedYifan HongtimeoutIPC(const sp<I> &interfaceObject, Function &&func, Args &&... args) { 83e2dadf0c4f132d3a39309f4e274f1a35f7caaaedYifan Hong using ::android::hardware::Status; 84e2dadf0c4f132d3a39309f4e274f1a35f7caaaedYifan Hong typename std::result_of<Function(I *, Args...)>::type ret{Status::ok()}; 85e2dadf0c4f132d3a39309f4e274f1a35f7caaaedYifan Hong auto boundFunc = std::bind(std::forward<Function>(func), 86e2dadf0c4f132d3a39309f4e274f1a35f7caaaedYifan Hong interfaceObject.get(), std::forward<Args>(args)...); 87e2dadf0c4f132d3a39309f4e274f1a35f7caaaedYifan Hong bool success = timeout(IPC_CALL_WAIT, [&ret, &boundFunc] { 8838903c0f88efefec3573d9ff3a8e28131da2f3b5Yifan Hong ret = std::move(boundFunc()); 89e2dadf0c4f132d3a39309f4e274f1a35f7caaaedYifan Hong }); 90e2dadf0c4f132d3a39309f4e274f1a35f7caaaedYifan Hong if (!success) { 91e2dadf0c4f132d3a39309f4e274f1a35f7caaaedYifan Hong return Status::fromStatusT(TIMED_OUT); 92e2dadf0c4f132d3a39309f4e274f1a35f7caaaedYifan Hong } 93e2dadf0c4f132d3a39309f4e274f1a35f7caaaedYifan Hong return ret; 94e2dadf0c4f132d3a39309f4e274f1a35f7caaaedYifan Hong} 95e2dadf0c4f132d3a39309f4e274f1a35f7caaaedYifan Hong 96e2dadf0c4f132d3a39309f4e274f1a35f7caaaedYifan Hong} // namespace lshal 97e2dadf0c4f132d3a39309f4e274f1a35f7caaaedYifan Hong} // namespace android 98