1 /*
2  * Copyright (C) 2017 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 #include "perfetto/ext/ipc/deferred.h"
18 
19 #include "perfetto/base/logging.h"
20 #include "perfetto/ext/base/utils.h"
21 
22 namespace perfetto {
23 namespace ipc {
24 
DeferredBase(std::function<void (AsyncResult<ProtoMessage>)> callback)25 DeferredBase::DeferredBase(
26     std::function<void(AsyncResult<ProtoMessage>)> callback)
27     : callback_(std::move(callback)) {}
28 
~DeferredBase()29 DeferredBase::~DeferredBase() {
30   if (callback_)
31     Reject();
32 }
33 
34 // Can't just use "= default" here because the default move operator for
35 // std::function doesn't necessarily swap and hence can leave a copy of the
36 // bind state around, which is undesirable.
DeferredBase(DeferredBase && other)37 DeferredBase::DeferredBase(DeferredBase&& other) noexcept {
38   Move(other);
39 }
40 
operator =(DeferredBase && other)41 DeferredBase& DeferredBase::operator=(DeferredBase&& other) {
42   if (callback_)
43     Reject();
44   Move(other);
45   return *this;
46 }
47 
Move(DeferredBase & other)48 void DeferredBase::Move(DeferredBase& other) {
49   callback_ = std::move(other.callback_);
50   other.callback_ = nullptr;
51 }
52 
Bind(std::function<void (AsyncResult<ProtoMessage>)> callback)53 void DeferredBase::Bind(
54     std::function<void(AsyncResult<ProtoMessage>)> callback) {
55   callback_ = std::move(callback);
56 }
57 
IsBound() const58 bool DeferredBase::IsBound() const {
59   return !!callback_;
60 }
61 
Resolve(AsyncResult<ProtoMessage> async_result)62 void DeferredBase::Resolve(AsyncResult<ProtoMessage> async_result) {
63   if (!callback_) {
64     PERFETTO_DFATAL("No callback set.");
65     return;
66   }
67   bool has_more = async_result.has_more();
68   callback_(std::move(async_result));
69   if (!has_more)
70     callback_ = nullptr;
71 }
72 
73 // Resolves with a nullptr |msg_|, signalling failure to |callback_|.
Reject()74 void DeferredBase::Reject() {
75   Resolve(AsyncResult<ProtoMessage>());
76 }
77 
78 }  // namespace ipc
79 }  // namespace perfetto
80