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 // TODO(blundell): This class should be rewritten to be structured 20 // similarly to BindingSet if possible, with PtrSet owning its 21 // Elements and those Elements calling back into PtrSet on connection 22 // error. 23 template <typename Interface, template <typename> class Ptr> 24 class PtrSet { 25 public: 26 PtrSet() {} 27 ~PtrSet() { CloseAll(); } 28 29 void AddPtr(Ptr<Interface> ptr) { 30 auto weak_interface_ptr = new Element(std::move(ptr)); 31 ptrs_.push_back(weak_interface_ptr->GetWeakPtr()); 32 ClearNullPtrs(); 33 } 34 35 template <typename FunctionType> 36 void ForAllPtrs(FunctionType function) { 37 for (const auto& it : ptrs_) { 38 if (it) 39 function(it->get()); 40 } 41 ClearNullPtrs(); 42 } 43 44 void CloseAll() { 45 for (const auto& it : ptrs_) { 46 if (it) 47 it->Close(); 48 } 49 ptrs_.clear(); 50 } 51 52 private: 53 class Element { 54 public: 55 explicit Element(Ptr<Interface> ptr) 56 : ptr_(std::move(ptr)), weak_ptr_factory_(this) { 57 ptr_.set_connection_error_handler(base::Bind(&DeleteElement, this)); 58 } 59 60 ~Element() {} 61 62 void Close() { 63 ptr_.reset(); 64 65 // Resetting the interface ptr means that it won't call this object back 66 // on connection error anymore, so this object must delete itself now. 67 DeleteElement(this); 68 } 69 70 Interface* get() { return ptr_.get(); } 71 72 base::WeakPtr<Element> GetWeakPtr() { 73 return weak_ptr_factory_.GetWeakPtr(); 74 } 75 76 private: 77 static void DeleteElement(Element* element) { delete element; } 78 79 Ptr<Interface> ptr_; 80 base::WeakPtrFactory<Element> weak_ptr_factory_; 81 82 DISALLOW_COPY_AND_ASSIGN(Element); 83 }; 84 85 void ClearNullPtrs() { 86 ptrs_.erase(std::remove_if(ptrs_.begin(), ptrs_.end(), 87 [](const base::WeakPtr<Element>& p) { 88 return p.get() == nullptr; 89 }), 90 ptrs_.end()); 91 } 92 93 std::vector<base::WeakPtr<Element>> ptrs_; 94 }; 95 96 } // namespace internal 97 98 template <typename Interface> 99 using InterfacePtrSet = internal::PtrSet<Interface, InterfacePtr>; 100 101 template <typename Interface> 102 using AssociatedInterfacePtrSet = 103 internal::PtrSet<Interface, AssociatedInterfacePtr>; 104 105 } // namespace mojo 106 107 #endif // MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_PTR_SET_H_ 108