blob: b80d116e1c995ffb439c6b606e0f580ebd0c7102 [file] [log] [blame]
Andrei Homescuffa3aaa2022-04-07 05:06:33 +00001/*
2 * Copyright (C) 2022 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#pragma once
17
18#include <pthread.h>
19
20#include <android-base/threads.h>
21
Hao Chenf1c47772023-05-31 14:12:33 -070022#include <condition_variable>
Andrei Homescuffa3aaa2022-04-07 05:06:33 +000023#include <functional>
24#include <memory>
25#include <thread>
26
27namespace android {
28
29#ifdef BINDER_RPC_SINGLE_THREADED
30class RpcMutex {
31public:
32 void lock() {}
33 void unlock() {}
34};
35
36class RpcMutexUniqueLock {
37public:
38 RpcMutexUniqueLock(RpcMutex&) {}
39 void unlock() {}
40};
41
42class RpcMutexLockGuard {
43public:
44 RpcMutexLockGuard(RpcMutex&) {}
45};
46
47class RpcConditionVariable {
48public:
49 void notify_one() {}
50 void notify_all() {}
51
52 void wait(RpcMutexUniqueLock&) {}
53
54 template <typename Predicate>
55 void wait(RpcMutexUniqueLock&, Predicate stop_waiting) {
56 LOG_ALWAYS_FATAL_IF(!stop_waiting(), "RpcConditionVariable::wait condition not met");
57 }
58
59 template <typename Duration>
60 std::cv_status wait_for(RpcMutexUniqueLock&, const Duration&) {
61 return std::cv_status::no_timeout;
62 }
63
64 template <typename Duration, typename Predicate>
65 bool wait_for(RpcMutexUniqueLock&, const Duration&, Predicate stop_waiting) {
66 return stop_waiting();
67 }
68};
69
70class RpcMaybeThread {
71public:
72 RpcMaybeThread() = default;
73
74 template <typename Function, typename... Args>
75 RpcMaybeThread(Function&& f, Args&&... args) {
76 // std::function requires a copy-constructible closure,
77 // so we need to wrap both the function and its arguments
78 // in a shared pointer that std::function can copy internally
79 struct Vars {
80 std::decay_t<Function> f;
81 std::tuple<std::decay_t<Args>...> args;
82
83 explicit Vars(Function&& f, Args&&... args)
84 : f(std::move(f)), args(std::move(args)...) {}
85 };
86 auto vars = std::make_shared<Vars>(std::forward<Function>(f), std::forward<Args>(args)...);
87 mFunc = [vars]() { std::apply(std::move(vars->f), std::move(vars->args)); };
88 }
89
90 void join() {
91 if (mFunc) {
92 // Move mFunc into a temporary so we can clear mFunc before
93 // executing the callback. This avoids infinite recursion if
94 // the callee then calls join() again directly or indirectly.
95 decltype(mFunc) func = nullptr;
96 mFunc.swap(func);
97 func();
98 }
99 }
100 void detach() { join(); }
101
102 class id {
103 public:
104 bool operator==(const id&) const { return true; }
105 bool operator!=(const id&) const { return false; }
106 bool operator<(const id&) const { return false; }
107 bool operator<=(const id&) const { return true; }
108 bool operator>(const id&) const { return false; }
109 bool operator>=(const id&) const { return true; }
110 };
111
112 id get_id() const { return id(); }
113
114private:
115 std::function<void(void)> mFunc;
116};
117
118namespace rpc_this_thread {
119static inline RpcMaybeThread::id get_id() {
120 return RpcMaybeThread::id();
121}
122} // namespace rpc_this_thread
123
124static inline uint64_t rpcGetThreadId() {
125 return 0;
126}
127
128static inline void rpcJoinIfSingleThreaded(RpcMaybeThread& t) {
129 t.join();
130}
131#else // BINDER_RPC_SINGLE_THREADED
132using RpcMutex = std::mutex;
133using RpcMutexUniqueLock = std::unique_lock<std::mutex>;
134using RpcMutexLockGuard = std::lock_guard<std::mutex>;
135using RpcConditionVariable = std::condition_variable;
136using RpcMaybeThread = std::thread;
137namespace rpc_this_thread = std::this_thread;
138
139static inline uint64_t rpcGetThreadId() {
140 return base::GetThreadId();
141}
142
143static inline void rpcJoinIfSingleThreaded(RpcMaybeThread&) {}
144#endif // BINDER_RPC_SINGLE_THREADED
145
146} // namespace android