1 // Copyright 2018 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #ifndef MEDIA_MOJO_SERVICES_DEFERRED_DESTROY_UNIQUE_RECEIVER_SET_H_
6 #define MEDIA_MOJO_SERVICES_DEFERRED_DESTROY_UNIQUE_RECEIVER_SET_H_
13 #include "base/functional/bind.h"
14 #include "base/logging.h"
15 #include "base/memory/ptr_util.h"
16 #include "base/memory/weak_ptr.h"
17 #include "base/task/bind_post_task.h"
18 #include "mojo/public/cpp/bindings/unique_receiver_set.h"
22 // A class that can be deferred destroyed by its owner. For example, when used
23 // in DeferredDestroyUniqueReceiverSet.
24 template <typename Interface>
25 class DeferredDestroy : public Interface {
27 // Runs the |destroy_cb| to notify that it's okay to destroy |this|. The
28 // callback can be called synchronously. |this| will always be destroyed
29 // asynchronously after running |destroy_cb| to avoid reentrance issues.
30 virtual void OnDestroyPending(base::OnceClosure destroy_cb) = 0;
33 // Similar to mojo::UniqueReceiverSet, but provide a way to defer the
34 // destruction of the interface implementation:
35 // - When disconnection happened on a receiver, the receiver is immediately
36 // destroyed and removed from the set. The interface implementation will be
37 // destroyed when the DestroyCallback is called.
38 // - When the DeferredDestroyUniqueReceiverSet is destructed, all outstanding
39 // receivers and interface implementations in the set are destroyed immediately
40 // without any deferral.
41 template <typename Interface>
42 class DeferredDestroyUniqueReceiverSet {
44 // Converts a delete callback to a deleter. If the callback is null or has
45 // been cancelled, callback bound with invalidated weak pointer, the pointer
46 // will be deleted with "delete" immediately.
49 using DeleteCallback =
50 base::RepeatingCallback<void(std::unique_ptr<Interface>)>;
53 explicit Deleter(DeleteCallback delete_cb)
54 : delete_cb_(std::move(delete_cb)) {}
56 void operator()(Interface* p) {
57 // Immediately wrap |p| into a unique_ptr to avoid any potential leak.
58 auto ptr = base::WrapUnique<Interface>(p);
60 // Can be cancelled during DeferredDestroyUniqueReceiverSet destruction.
61 if (delete_cb_ && !delete_cb_.IsCancelled())
62 delete_cb_.Run(std::move(ptr));
68 DeleteCallback delete_cb_;
71 DeferredDestroyUniqueReceiverSet() {}
73 DeferredDestroyUniqueReceiverSet(const DeferredDestroyUniqueReceiverSet&) =
75 DeferredDestroyUniqueReceiverSet& operator=(
76 const DeferredDestroyUniqueReceiverSet&) = delete;
78 void Add(std::unique_ptr<DeferredDestroy<Interface>> impl,
79 mojo::PendingReceiver<Interface> receiver) {
80 // Wrap the pointer into a unique_ptr with a deleter.
81 Deleter deleter(base::BindRepeating(
82 &DeferredDestroyUniqueReceiverSet::OnReceiverRemoved,
83 weak_factory_.GetWeakPtr()));
84 std::unique_ptr<Interface, Deleter> impl_with_deleter(impl.release(),
87 receivers_.Add(std::move(impl_with_deleter), std::move(receiver));
90 // TODO(xhwang): Add RemoveReceiver() if needed.
92 void CloseAllReceivers() {
93 weak_factory_.InvalidateWeakPtrs();
95 unbound_impls_.clear();
98 bool empty() const { return receivers_.empty(); }
100 size_t size() const { return receivers_.size(); }
102 size_t unbound_size() const { return unbound_impls_.size(); }
105 void OnReceiverRemoved(std::unique_ptr<Interface> ptr) {
106 DVLOG(1) << __func__;
110 // The cast is safe since AddReceiver() takes DeferredDestroy<Interface>.
111 auto* impl_ptr = static_cast<DeferredDestroy<Interface>*>(ptr.get());
113 // Put the |ptr| in the map before calling OnDestroyPending() because the
114 // callback could be called synchronously.
115 unbound_impls_[id_] = std::move(ptr);
117 // Use base::BindPostTaskToCurrentDefault() to force post the destroy
118 // callback. This is needed because the callback may be called directly in
119 // the same stack where the implementation is being destroyed.
120 impl_ptr->OnDestroyPending(base::BindPostTaskToCurrentDefault(
121 base::BindOnce(&DeferredDestroyUniqueReceiverSet::OnDestroyable,
122 weak_factory_.GetWeakPtr(), id_)));
125 void OnDestroyable(int id) {
126 DVLOG(1) << __func__;
127 unbound_impls_.erase(id);
131 std::map<uint32_t, std::unique_ptr<Interface>> unbound_impls_;
132 mojo::UniqueReceiverSet<Interface, void, Deleter> receivers_;
134 // Note: This should remain the last member so it'll be destroyed and
135 // invalidate its weak pointers before any other members are destroyed.
136 base::WeakPtrFactory<DeferredDestroyUniqueReceiverSet> weak_factory_{this};
141 #endif // MEDIA_MOJO_SERVICES_DEFERRED_DESTROY_UNIQUE_RECEIVER_SET_H_