1 // Copyright 2014 The Chromium Authors. All rights reserved.
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 MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_PTR_SET_H_
6 #define MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_PTR_SET_H_
7 
8 #include <utility>
9 #include <vector>
10 
11 #include "base/macros.h"
12 #include "base/memory/weak_ptr.h"
13 #include "mojo/public/cpp/bindings/associated_interface_ptr.h"
14 #include "mojo/public/cpp/bindings/interface_ptr.h"
15 
16 namespace mojo {
17 namespace internal {
18 
19 template <typename Interface, template <typename> class Ptr>
20 class PtrSet {
21  public:
PtrSet()22   PtrSet() {}
~PtrSet()23   ~PtrSet() { CloseAll(); }
24 
AddPtr(Ptr<Interface> ptr)25   void AddPtr(Ptr<Interface> ptr) {
26     auto weak_interface_ptr = new Element(std::move(ptr));
27     ptrs_.push_back(weak_interface_ptr->GetWeakPtr());
28     ClearNullPtrs();
29   }
30 
31   template <typename FunctionType>
ForAllPtrs(FunctionType function)32   void ForAllPtrs(FunctionType function) {
33     for (const auto& it : ptrs_) {
34       if (it)
35         function(it->get());
36     }
37     ClearNullPtrs();
38   }
39 
CloseAll()40   void CloseAll() {
41     for (const auto& it : ptrs_) {
42       if (it)
43         it->Close();
44     }
45     ptrs_.clear();
46   }
47 
48  private:
49   class Element {
50    public:
Element(Ptr<Interface> ptr)51     explicit Element(Ptr<Interface> ptr)
52         : ptr_(std::move(ptr)), weak_ptr_factory_(this) {
53       ptr_.set_connection_error_handler(base::Bind(&DeleteElement, this));
54     }
55 
~Element()56     ~Element() {}
57 
Close()58     void Close() { ptr_.reset(); }
59 
get()60     Interface* get() { return ptr_.get(); }
61 
GetWeakPtr()62     base::WeakPtr<Element> GetWeakPtr() {
63       return weak_ptr_factory_.GetWeakPtr();
64     }
65 
66    private:
DeleteElement(Element * element)67     static void DeleteElement(Element* element) { delete element; }
68 
69     Ptr<Interface> ptr_;
70     base::WeakPtrFactory<Element> weak_ptr_factory_;
71 
72     DISALLOW_COPY_AND_ASSIGN(Element);
73   };
74 
ClearNullPtrs()75   void ClearNullPtrs() {
76     ptrs_.erase(std::remove_if(ptrs_.begin(), ptrs_.end(),
77                                [](const base::WeakPtr<Element>& p) {
78                                  return p.get() == nullptr;
79                                }),
80                 ptrs_.end());
81   }
82 
83   std::vector<base::WeakPtr<Element>> ptrs_;
84 };
85 
86 }  // namespace internal
87 
88 template <typename Interface>
89 using InterfacePtrSet = internal::PtrSet<Interface, InterfacePtr>;
90 
91 template <typename Interface>
92 using AssociatedInterfacePtrSet =
93     internal::PtrSet<Interface, AssociatedInterfacePtr>;
94 
95 }  // namespace mojo
96 
97 #endif  // MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_PTR_SET_H_
98