Home | History | Annotate | Download | only in bindings
      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