1 // Copyright 2020 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 COMPONENTS_PERFORMANCE_MANAGER_OWNED_OBJECTS_H_ 6 #define COMPONENTS_PERFORMANCE_MANAGER_OWNED_OBJECTS_H_ 7 8 #include <memory> 9 10 #include "base/check_op.h" 11 #include "base/containers/flat_set.h" 12 #include "base/containers/unique_ptr_adapters.h" 13 #include "base/stl_util.h" 14 15 namespace performance_manager { 16 17 namespace internal { 18 19 // Builds the callback type from the ObjectType and CallbackArgType. 20 template <typename ObjectType, typename CallbackArgType> 21 struct CallbackType { 22 typedef void (ObjectType::*Type)(CallbackArgType); 23 }; 24 25 // Specialization for void CallbackArgType. 26 template <typename ObjectType> 27 struct CallbackType<ObjectType, void> { 28 typedef void (ObjectType::*Type)(); 29 }; 30 31 } // namespace internal 32 33 // Helper class defining storage for a collection of "owned" objects. These 34 // are objects whose ownership has explicitly been passed to the container. 35 // The objects can be taken back from the container, or will be torn down 36 // with the container. Note that the owner of this container should 37 // explicitly call ReleaseObjects prior to the object being torn down; the 38 // container expects to be empty at destruction. 39 // TODO: Once C++17 is available, use "auto" here and simply accept the 2 40 // member function pointers, deducing all other type info. 41 template <typename OwnedType, 42 typename CallbackArgType, 43 typename internal::CallbackType<OwnedType, CallbackArgType>::Type 44 OnPassedMemberFunction, 45 typename internal::CallbackType<OwnedType, CallbackArgType>::Type 46 OnTakenMemberFunction> 47 class OwnedObjects { 48 public: 49 OwnedObjects() = default; 50 ~OwnedObjects() { DCHECK(objects_.empty()); } 51 52 OwnedObjects(const OwnedObjects&) = delete; 53 OwnedObjects& operator=(const OwnedObjects&) = delete; 54 55 // Passes an object into this container, and invokes the OnPassedFunctionPtr. 56 template <typename... ArgTypes> 57 void PassObject(std::unique_ptr<OwnedType> object, ArgTypes... args) { 58 auto* raw = object.get(); 59 DCHECK(!base::Contains(objects_, raw)); 60 objects_.insert(std::move(object)); 61 // We should stop using a flat_set at this point. 62 DCHECK_GE(100u, objects_.size()); 63 ((raw)->*(OnPassedMemberFunction))(std::forward<ArgTypes>(args)...); 64 } 65 66 // Takes an object back from this container, and invokes the 67 // OnTakenFunctionPtr (if the object is found). 68 template <typename... ArgTypes> 69 std::unique_ptr<OwnedType> TakeObject(OwnedType* raw, ArgTypes... args) { 70 std::unique_ptr<OwnedType> object; 71 auto it = objects_.find(raw); 72 if (it != objects_.end()) { 73 DCHECK_EQ(raw, it->get()); 74 // base::flat_set doesn't yet support "extract", but this is the approved 75 // way of doing this for now. 76 object = std::move(*it); 77 objects_.erase(it); 78 ((raw)->*(OnTakenMemberFunction))(std::forward<ArgTypes>(args)...); 79 } 80 return object; 81 } 82 83 // Releases all the objects owned by this container, invoking their 84 // OnTakenFunctionPtr as they are released. 85 template <typename... ArgTypes> 86 void ReleaseObjects(ArgTypes... args) { 87 // Release the last object first to be friendly with base::flat_set, which 88 // is actually a std::vector. 89 while (!objects_.empty()) 90 TakeObject(objects_.rbegin()->get(), std::forward<ArgTypes>(args)...); 91 } 92 93 // Returns the current size of this container. 94 size_t size() const { return objects_.size(); } 95 96 // Returns true if this container is empty. 97 bool empty() const { return objects_.empty(); } 98 99 private: 100 // If this ever uses an STL compliant set with "extract", then modify 101 // TakeObject to use that instead! 102 base::flat_set<std::unique_ptr<OwnedType>, base::UniquePtrComparator> 103 objects_; 104 }; 105 106 } // namespace performance_manager 107 108 #endif // COMPONENTS_PERFORMANCE_MANAGER_OWNED_OBJECTS_H_