Avi Drissman | 8ba1bad | 2022-09-13 19:22:36 | [diff] [blame] | 1 | // Copyright 2020 The Chromium Authors |
Chris Hamilton | f7effeb | 2020-05-19 21:43:12 | [diff] [blame] | 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 | |
Hans Wennborg | 29c74d3f | 2020-06-24 13:46:35 | [diff] [blame] | 10 | #include "base/check_op.h" |
Jan Wilken Dörrie | 986f0a6 | 2020-12-09 23:29:12 | [diff] [blame] | 11 | #include "base/containers/contains.h" |
Chris Hamilton | f7effeb | 2020-05-19 21:43:12 | [diff] [blame] | 12 | #include "base/containers/flat_set.h" |
| 13 | #include "base/containers/unique_ptr_adapters.h" |
Chris Hamilton | f7effeb | 2020-05-19 21:43:12 | [diff] [blame] | 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; |
Joe Mason | be3fb0f0 | 2024-06-14 15:45:22 | [diff] [blame] | 50 | ~OwnedObjects() { CHECK(objects_.empty()); } |
Chris Hamilton | f7effeb | 2020-05-19 21:43:12 | [diff] [blame] | 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(); |
Joe Mason | be3fb0f0 | 2024-06-14 15:45:22 | [diff] [blame] | 59 | CHECK(!base::Contains(objects_, raw)); |
Chris Hamilton | f7effeb | 2020-05-19 21:43:12 | [diff] [blame] | 60 | objects_.insert(std::move(object)); |
| 61 | // We should stop using a flat_set at this point. |
Joe Mason | be3fb0f0 | 2024-06-14 15:45:22 | [diff] [blame] | 62 | CHECK_GE(100u, objects_.size()); |
Chris Hamilton | f7effeb | 2020-05-19 21:43:12 | [diff] [blame] | 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()) { |
Joe Mason | be3fb0f0 | 2024-06-14 15:45:22 | [diff] [blame] | 73 | CHECK_EQ(raw, it->get()); |
Chris Hamilton | f7effeb | 2020-05-19 21:43:12 | [diff] [blame] | 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_ |