File: resource_manager.h

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (141 lines) | stat: -rw-r--r-- 5,069 bytes parent folder | download | duplicates (9)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef COMPONENTS_REPORTING_RESOURCES_RESOURCE_MANAGER_H_
#define COMPONENTS_REPORTING_RESOURCES_RESOURCE_MANAGER_H_

#include <atomic>
#include <cstdint>
#include <optional>
#include <queue>
#include <utility>

#include "base/functional/callback_forward.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_refptr.h"
#include "base/task/sequenced_task_runner.h"
#include "base/thread_annotations.h"

namespace reporting {

// Resource management class. The class is thread-safe.
// Each resource instance is created with its own total size; the rest of the
// functionality is identical. All APIs are non-blocking.
class ResourceManager : public base::RefCountedThreadSafe<ResourceManager> {
 public:
  explicit ResourceManager(uint64_t total_size);

  // Needs to be called before attempting to allocate specified size.
  // Returns true if requested amount can be allocated.
  // After that the caller can actually allocate it or must call
  // |Discard| if decided not to allocate.
  bool Reserve(uint64_t size);

  // Reverts reservation, arranges for callbacks calls as necessary.
  // Must be called after the specified amount is released.
  void Discard(uint64_t size);

  // Returns total amount.
  uint64_t GetTotal() const;

  // Returns current used amount.
  uint64_t GetUsed() const;

  // Registers a callback to be invoked once there is specified amount
  // of resource available (does not reserve it, so once called back
  // the respective code must attempt to reserve again, and if unsuccessful,
  // may need ot re-register the callback).
  // Callbacks will be invoked in the context of the sequenced task runner
  // it was registered in.
  void RegisterCallback(uint64_t size, base::OnceClosure cb);

  // Test only: Sets non-default usage limit.
  void Test_SetTotal(uint64_t test_total);

 private:
  friend class base::RefCountedThreadSafe<ResourceManager>;

  ~ResourceManager();

  // Flushes as many callbacks as possible given the current resource
  // availability. Callbacks only signal that resource may be available,
  // the resumed task must try to actually reserve it after that.
  void FlushCallbacks();

  uint64_t total_;  // Remains constant in prod code, changes only in tests.
  std::atomic<uint64_t> used_{0};

  // Sequenced task runner for callbacks handling (not for calling callbacks!)
  const scoped_refptr<base::SequencedTaskRunner> sequenced_task_runner_;
  SEQUENCE_CHECKER(sequence_checker_);

  // Queue of pairs [size, callback].
  // When `Discard` leaves enough space available (even momentarily),
  // calls as many of the callbacks as fit in that size, in the queue order.
  // Note that in a meantime reservation may change - the called back code
  // must attempt reservation before using it.
  std::queue<std::pair<uint64_t, base::OnceClosure>> resource_callbacks_
      GUARDED_BY_CONTEXT(sequence_checker_);
};

// Moveable RAII class used for scoped Reserve-Discard.
//
// Usage:
//  {
//    ScopedReservation reservation(1024u, options.memory_resource());
//    if (!reservation.reserved()) {
//      // Allocation failed.
//      return;
//    }
//    // Allocation succeeded.
//    ...
//  }   // Automatically discarded.
//
// Can be handed over to another owner by move-constructor or using HandOver
// method:
// {
//   ScopedReservation summary;
//   for (const uint64_t size : sizes) {
//     ScopedReservation single_reservation(size, resource);
//     ...
//     summary.HandOver(single_reservation);
//   }
// }
class ScopedReservation {
 public:
  // Zero-size reservation with no resource interface attached.
  // reserved() returns false.
  ScopedReservation() noexcept;
  // Specified reservation, must have resource interface attached.
  ScopedReservation(uint64_t size,
                    scoped_refptr<ResourceManager> resource_manager) noexcept;
  // New reservation on the same resource interface as |other_reservation|.
  ScopedReservation(uint64_t size,
                    const ScopedReservation& other_reservation) noexcept;
  // Move constructor.
  ScopedReservation(ScopedReservation&& other) noexcept;
  ScopedReservation(const ScopedReservation& other) = delete;
  ScopedReservation& operator=(ScopedReservation&& other) = delete;
  ScopedReservation& operator=(const ScopedReservation& other) = delete;
  ~ScopedReservation();

  bool reserved() const;

  // Reduces reservation to |new_size|.
  bool Reduce(uint64_t new_size);

  // Adds |other| to |this| without assigning or releasing any reservation.
  // Used for seamless transition from one reservation to another (more generic
  // than std::move). Resets |other| to non-reserved state upon return from this
  // method.
  void HandOver(ScopedReservation& other);

 private:
  scoped_refptr<ResourceManager> resource_manager_;
  std::optional<uint64_t> size_;
};

}  // namespace reporting

#endif  // COMPONENTS_REPORTING_RESOURCES_RESOURCE_MANAGER_H_