• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <thread>
24 
25 #include <binder/Common.h>
26 
27 namespace android {
28 
29 #ifdef BINDER_RPC_SINGLE_THREADED
30 class LIBBINDER_EXPORTED RpcMutex {
31 public:
lock()32     void lock() {}
unlock()33     void unlock() {}
34 };
35 
36 class LIBBINDER_EXPORTED RpcMutexUniqueLock {
37 public:
RpcMutexUniqueLock(RpcMutex &)38     RpcMutexUniqueLock(RpcMutex&) {}
unlock()39     void unlock() {}
40 };
41 
42 class LIBBINDER_EXPORTED RpcMutexLockGuard {
43 public:
RpcMutexLockGuard(RpcMutex &)44     RpcMutexLockGuard(RpcMutex&) {}
45 };
46 
47 class LIBBINDER_EXPORTED RpcConditionVariable {
48 public:
notify_one()49     void notify_one() {}
notify_all()50     void notify_all() {}
51 
wait(RpcMutexUniqueLock &)52     void wait(RpcMutexUniqueLock&) {}
53 
54     template <typename Predicate>
wait(RpcMutexUniqueLock &,Predicate stop_waiting)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>
wait_for(RpcMutexUniqueLock &,const 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>
wait_for(RpcMutexUniqueLock &,const Duration &,Predicate stop_waiting)65     bool wait_for(RpcMutexUniqueLock&, const Duration&, Predicate stop_waiting) {
66         return stop_waiting();
67     }
68 };
69 
70 class LIBBINDER_EXPORTED RpcMaybeThread {
71 public:
72     RpcMaybeThread() = default;
73 
74     template <typename Function, typename... Args>
RpcMaybeThread(Function && f,Args &&...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 
join()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     }
detach()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 
get_id()112     id get_id() const { return id(); }
113 
114 private:
115     std::function<void(void)> mFunc;
116 };
117 
118 namespace rpc_this_thread {
get_id()119 static inline RpcMaybeThread::id get_id() {
120     return RpcMaybeThread::id();
121 }
122 } // namespace rpc_this_thread
123 
rpcJoinIfSingleThreaded(RpcMaybeThread & t)124 static inline void rpcJoinIfSingleThreaded(RpcMaybeThread& t) {
125     t.join();
126 }
127 #else  // BINDER_RPC_SINGLE_THREADED
128 using RpcMutex = std::mutex;
129 using RpcMutexUniqueLock = std::unique_lock<std::mutex>;
130 using RpcMutexLockGuard = std::lock_guard<std::mutex>;
131 using RpcConditionVariable = std::condition_variable;
132 using RpcMaybeThread = std::thread;
133 namespace rpc_this_thread = std::this_thread;
134 
135 static inline void rpcJoinIfSingleThreaded(RpcMaybeThread&) {}
136 #endif // BINDER_RPC_SINGLE_THREADED
137 
138 } // namespace android
139