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