blob: c4f847a4c83a7f8b54cc48c88114ddb776fdafba [file] [log] [blame]
Avi Drissman8ba1bad2022-09-13 19:22:361// Copyright 2020 The Chromium Authors
Leonid Baraz3e8af4b2020-11-23 19:04:472// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Leonid Barazea0c6dc2021-11-02 20:38:055#ifndef COMPONENTS_REPORTING_RESOURCES_RESOURCE_INTERFACE_H_
6#define COMPONENTS_REPORTING_RESOURCES_RESOURCE_INTERFACE_H_
Leonid Baraz3e8af4b2020-11-23 19:04:477
Leonid Baraz0be7196b2022-12-13 00:02:528#include <atomic>
Leonid Baraz3e8af4b2020-11-23 19:04:479#include <cstdint>
Leonid Baraz0be7196b2022-12-13 00:02:5210#include <queue>
11#include <utility>
Leonid Baraz3e8af4b2020-11-23 19:04:4712
Leonid Baraz0be7196b2022-12-13 00:02:5213#include "base/functional/callback_forward.h"
Leonid Baraz960ea8f2022-05-17 01:01:0614#include "base/memory/ref_counted.h"
15#include "base/memory/scoped_refptr.h"
Leonid Baraz0be7196b2022-12-13 00:02:5216#include "base/task/sequenced_task_runner.h"
17#include "base/thread_annotations.h"
Anton Bikineev1156b5f2021-05-15 22:35:3618#include "third_party/abseil-cpp/absl/types/optional.h"
Leonid Baraz3e8af4b2020-11-23 19:04:4719
20namespace reporting {
21
22// Interface to resources management by Storage module.
23// Must be implemented by the caller base on the platform limitations.
Leonid Baraz0be7196b2022-12-13 00:02:5224// All APIs are non-blocking. The class is thread-safe.
25// TODO(b/258822636): The class is no longer interface, rename it and update the
26// comments.
Leonid Baraz960ea8f2022-05-17 01:01:0627class ResourceInterface : public base::RefCountedThreadSafe<ResourceInterface> {
Leonid Baraz3e8af4b2020-11-23 19:04:4728 public:
Leonid Baraz0be7196b2022-12-13 00:02:5229 explicit ResourceInterface(uint64_t total_size);
30
Leonid Baraz3e8af4b2020-11-23 19:04:4731 // Needs to be called before attempting to allocate specified size.
32 // Returns true if requested amount can be allocated.
33 // After that the caller can actually allocate it or must call
34 // |Discard| if decided not to allocate.
Leonid Baraz0be7196b2022-12-13 00:02:5235 bool Reserve(uint64_t size);
Leonid Baraz3e8af4b2020-11-23 19:04:4736
Leonid Baraz0be7196b2022-12-13 00:02:5237 // Reverts reservation, arranges for callbacks calls as necessary.
Leonid Baraz3e8af4b2020-11-23 19:04:4738 // Must be called after the specified amount is released.
Leonid Baraz0be7196b2022-12-13 00:02:5239 void Discard(uint64_t size);
Leonid Baraz3e8af4b2020-11-23 19:04:4740
41 // Returns total amount.
Leonid Baraz0be7196b2022-12-13 00:02:5242 uint64_t GetTotal() const;
Leonid Baraz3e8af4b2020-11-23 19:04:4743
44 // Returns current used amount.
Leonid Baraz0be7196b2022-12-13 00:02:5245 uint64_t GetUsed() const;
46
47 // Registers a callback to be invoked once there is specified amount
48 // of resource available (does not reserve it, so once called back
49 // the respective code must attempt to reserve again, and if unsuccessful,
50 // may need ot re-register the callback).
51 // Callbacks will be invoked in the context of the sequenced task runner
52 // it was registered in.
53 void RegisterCallback(uint64_t size, base::OnceClosure cb);
Leonid Baraz3e8af4b2020-11-23 19:04:4754
55 // Test only: Sets non-default usage limit.
Leonid Baraz0be7196b2022-12-13 00:02:5256 void Test_SetTotal(uint64_t test_total);
Leonid Baraz3e8af4b2020-11-23 19:04:4757
Leonid Baraz0be7196b2022-12-13 00:02:5258 private:
Leonid Baraz960ea8f2022-05-17 01:01:0659 friend class base::RefCountedThreadSafe<ResourceInterface>;
60
Leonid Baraz0be7196b2022-12-13 00:02:5261 ~ResourceInterface();
62
63 // Flushes as many callbacks as possible given the current resource
64 // availability. Callbacks only signal that resource may be available,
65 // the resumed task must try to actually reserve it after that.
66 void FlushCallbacks();
67
68 uint64_t total_; // Remains constant in prod code, changes only in tests.
69 std::atomic<uint64_t> used_{0};
70
71 // Sequenced task runner for callbacks handling (not for calling callbacks!)
72 const scoped_refptr<base::SequencedTaskRunner> sequenced_task_runner_;
73 SEQUENCE_CHECKER(sequence_checker_);
74
75 // Queue of pairs [size, callback].
76 // When `Discard` leaves enough space available (even momentarily),
77 // calls as many of the callbacks as fit in that size, in the queue order.
78 // Note that in a meantime reservation may change - the called back code
79 // must attempt reservation before using it.
80 std::queue<std::pair<uint64_t, base::OnceClosure>> resource_callbacks_
81 GUARDED_BY_CONTEXT(sequence_checker_);
Leonid Baraz3e8af4b2020-11-23 19:04:4782};
83
84// Moveable RAII class used for scoped Reserve-Discard.
85//
86// Usage:
87// {
Leonid Baraz960ea8f2022-05-17 01:01:0688// ScopedReservation reservation(1024u, options.memory_resource());
Leonid Baraz3e8af4b2020-11-23 19:04:4789// if (!reservation.reserved()) {
90// // Allocation failed.
91// return;
92// }
93// // Allocation succeeded.
94// ...
95// } // Automatically discarded.
96//
Leonid Baraza2064292022-07-07 00:18:4197// Can be handed over to another owner by move-constructor or using HandOver
98// method:
99// {
100// ScopedReservation summary;
101// for (const uint64_t size : sizes) {
102// ScopedReservation single_reservation(size, resource);
103// ...
104// summary.HandOver(single_reservation);
105// }
106// }
Leonid Baraz3e8af4b2020-11-23 19:04:47107class ScopedReservation {
108 public:
Leonid Baraza2064292022-07-07 00:18:41109 // Zero-size reservation with no resource interface attached.
110 // reserved() returns false.
111 ScopedReservation() noexcept;
112 // Specified reservation, must have resource interface attached.
Leonid Barazaf0a319f2022-06-15 02:17:47113 ScopedReservation(
114 uint64_t size,
115 scoped_refptr<ResourceInterface> resource_interface) noexcept;
Leonid Barazb4553922022-07-12 23:32:53116 // New reservation on the same resource interface as |other_reservation|.
117 ScopedReservation(uint64_t size,
118 const ScopedReservation& other_reservation) noexcept;
119 // Move constructor.
Leonid Barazaf0a319f2022-06-15 02:17:47120 ScopedReservation(ScopedReservation&& other) noexcept;
Leonid Baraz3e8af4b2020-11-23 19:04:47121 ScopedReservation(const ScopedReservation& other) = delete;
Leonid Barazaf0a319f2022-06-15 02:17:47122 ScopedReservation& operator=(ScopedReservation&& other) = delete;
Leonid Baraz3e8af4b2020-11-23 19:04:47123 ScopedReservation& operator=(const ScopedReservation& other) = delete;
124 ~ScopedReservation();
125
126 bool reserved() const;
Leonid Barazaf0a319f2022-06-15 02:17:47127
128 // Reduces reservation to |new_size|.
Santiago Castano Moreno150ba5f2021-11-12 21:34:52129 bool Reduce(uint64_t new_size);
Leonid Baraz3e8af4b2020-11-23 19:04:47130
Leonid Barazaf0a319f2022-06-15 02:17:47131 // Adds |other| to |this| without assigning or releasing any reservation.
132 // Used for seamless transition from one reservation to another (more generic
133 // than std::move). Resets |other| to non-reserved state upon return from this
134 // method.
135 void HandOver(ScopedReservation& other);
136
Leonid Baraz3e8af4b2020-11-23 19:04:47137 private:
Leonid Baraza2064292022-07-07 00:18:41138 scoped_refptr<ResourceInterface> resource_interface_;
Anton Bikineev1156b5f2021-05-15 22:35:36139 absl::optional<uint64_t> size_;
Leonid Baraz3e8af4b2020-11-23 19:04:47140};
141
Leonid Baraz3e8af4b2020-11-23 19:04:47142} // namespace reporting
143
Leonid Barazea0c6dc2021-11-02 20:38:05144#endif // COMPONENTS_REPORTING_RESOURCES_RESOURCE_INTERFACE_H_