1 /*
2  * Copyright 2019 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 
17 #pragma once
18 
19 #include "common/bind.h"
20 #include "common/callback.h"
21 
22 namespace bluetooth {
23 namespace common {
24 
25 class IPostableContext {
26  public:
~IPostableContext()27   virtual ~IPostableContext(){};
28   virtual void Post(OnceClosure closure) = 0;
29 };
30 
31 template <typename R, typename... Args>
32 class ContextualOnceCallback;
33 
34 // A callback bound to an execution context that can be invoked only once.
35 template <typename R, typename... Args>
36 class ContextualOnceCallback<R(Args...)> {
37  public:
ContextualOnceCallback(common::OnceCallback<R (Args...)> && callback,IPostableContext * context)38   ContextualOnceCallback(common::OnceCallback<R(Args...)>&& callback, IPostableContext* context)
39       : callback_(std::move(callback)), context_(context) {}
40 
41   constexpr ContextualOnceCallback() = default;
42 
43   DISALLOW_COPY_AND_ASSIGN(ContextualOnceCallback);
44 
45   ContextualOnceCallback(ContextualOnceCallback&&) noexcept = default;
46   ContextualOnceCallback& operator=(ContextualOnceCallback&&) noexcept = default;
47 
Invoke(Args...args)48   void Invoke(Args... args) {
49     context_->Post(common::BindOnce(std::move(callback_), std::forward<Args>(args)...));
50   }
51 
InvokeIfNotEmpty(Args...args)52   void InvokeIfNotEmpty(Args... args) {
53     if (context_ != nullptr) {
54       context_->Post(common::BindOnce(std::move(callback_), std::forward<Args>(args)...));
55     }
56   }
57 
IsEmpty()58   bool IsEmpty() {
59     return context_ == nullptr;
60   }
61 
62  private:
63   common::OnceCallback<R(Args...)> callback_;
64   IPostableContext* context_;
65 };
66 
67 template <typename R, typename... Args>
68 class ContextualCallback;
69 
70 // A callback bound to an execution context that can be invoked multiple times.
71 template <typename R, typename... Args>
72 class ContextualCallback<R(Args...)> {
73  public:
ContextualCallback(common::Callback<R (Args...)> && callback,IPostableContext * context)74   ContextualCallback(common::Callback<R(Args...)>&& callback, IPostableContext* context)
75       : callback_(std::move(callback)), context_(context) {}
76 
77   constexpr ContextualCallback() = default;
78 
79   ContextualCallback(const ContextualCallback&) = default;
80   ContextualCallback& operator=(const ContextualCallback&) = default;
81   ContextualCallback(ContextualCallback&&) noexcept = default;
82   ContextualCallback& operator=(ContextualCallback&&) noexcept = default;
83 
Invoke(Args...args)84   void Invoke(Args... args) {
85     context_->Post(common::BindOnce(callback_, std::forward<Args>(args)...));
86   }
87 
InvokeIfNotEmpty(Args...args)88   void InvokeIfNotEmpty(Args... args) {
89     if (context_ != nullptr) {
90       context_->Post(common::BindOnce(callback_, std::forward<Args>(args)...));
91     }
92   }
93 
IsEmpty()94   bool IsEmpty() {
95     return context_ == nullptr;
96   }
97 
98  private:
99   common::Callback<R(Args...)> callback_;
100   IPostableContext* context_;
101 };
102 
103 }  // namespace common
104 }  // namespace bluetooth
105