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