[M120 Migration][MM][CAPI] Fix the logic for media using capi player.
[platform/framework/web/chromium-efl.git] / media / mojo / services / deferred_destroy_unique_receiver_set.h
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.
4
5 #ifndef MEDIA_MOJO_SERVICES_DEFERRED_DESTROY_UNIQUE_RECEIVER_SET_H_
6 #define MEDIA_MOJO_SERVICES_DEFERRED_DESTROY_UNIQUE_RECEIVER_SET_H_
7
8 #include <stdint.h>
9
10 #include <map>
11 #include <memory>
12
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"
19
20 namespace media {
21
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 {
26  public:
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;
31 };
32
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 {
43  public:
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.
47   class Deleter {
48    public:
49     using DeleteCallback =
50         base::RepeatingCallback<void(std::unique_ptr<Interface>)>;
51
52     Deleter() = default;
53     explicit Deleter(DeleteCallback delete_cb)
54         : delete_cb_(std::move(delete_cb)) {}
55
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);
59
60       // Can be cancelled during DeferredDestroyUniqueReceiverSet destruction.
61       if (delete_cb_ && !delete_cb_.IsCancelled())
62         delete_cb_.Run(std::move(ptr));
63       else
64         ptr.reset();
65     }
66
67    private:
68     DeleteCallback delete_cb_;
69   };
70
71   DeferredDestroyUniqueReceiverSet() {}
72
73   DeferredDestroyUniqueReceiverSet(const DeferredDestroyUniqueReceiverSet&) =
74       delete;
75   DeferredDestroyUniqueReceiverSet& operator=(
76       const DeferredDestroyUniqueReceiverSet&) = delete;
77
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(),
85                                                           deleter);
86
87     receivers_.Add(std::move(impl_with_deleter), std::move(receiver));
88   }
89
90   // TODO(xhwang): Add RemoveReceiver() if needed.
91
92   void CloseAllReceivers() {
93     weak_factory_.InvalidateWeakPtrs();
94     receivers_.Clear();
95     unbound_impls_.clear();
96   }
97
98   bool empty() const { return receivers_.empty(); }
99
100   size_t size() const { return receivers_.size(); }
101
102   size_t unbound_size() const { return unbound_impls_.size(); }
103
104  private:
105   void OnReceiverRemoved(std::unique_ptr<Interface> ptr) {
106     DVLOG(1) << __func__;
107
108     id_++;
109
110     // The cast is safe since AddReceiver() takes DeferredDestroy<Interface>.
111     auto* impl_ptr = static_cast<DeferredDestroy<Interface>*>(ptr.get());
112
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);
116
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_)));
123   }
124
125   void OnDestroyable(int id) {
126     DVLOG(1) << __func__;
127     unbound_impls_.erase(id);
128   }
129
130   uint32_t id_ = 0;
131   std::map<uint32_t, std::unique_ptr<Interface>> unbound_impls_;
132   mojo::UniqueReceiverSet<Interface, void, Deleter> receivers_;
133
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};
137 };
138
139 }  // namespace media
140
141 #endif  // MEDIA_MOJO_SERVICES_DEFERRED_DESTROY_UNIQUE_RECEIVER_SET_H_