Ion
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
resourceholder.h
Go to the documentation of this file.
1 
18 #ifndef ION_GFX_RESOURCEHOLDER_H_
19 #define ION_GFX_RESOURCEHOLDER_H_
20 
21 #include <cstring> // For NULL.
22 #include <vector>
23 
24 #include "base/macros.h"
25 #include "ion/base/invalid.h"
26 #include "ion/base/lockguards.h"
27 #include "ion/base/logging.h"
28 #include "ion/base/notifier.h"
29 #include "ion/base/readwritelock.h"
32 #include "ion/gfx/resourcebase.h"
33 #include "ion/port/atomic.h"
34 
35 namespace ion {
36 namespace gfx {
37 
52 class ION_API ResourceHolder : public base::Notifier {
53  public:
56  enum BaseChanges {
59  kNumBaseChanges
60  };
61 
64  void SetResource(size_t index, ResourceKey key, ResourceBase* resource) const;
65 
68  ResourceBase* GetResource(size_t index, ResourceKey key) const;
69 
73  int GetResourceCount() const {
74  return resource_count_;
75  }
76 
78  size_t GetGpuMemoryUsed() const {
79  base::ReadLock read_lock(&lock_);
80  base::ReadGuard guard(&read_lock);
81  size_t total = 0U;
82  for (const auto& group : resources_)
83  for (const auto& entry : group)
84  total += entry.second->GetGpuMemoryUsed();
85  return total;
86  }
87 
89  const std::string& GetLabel() const { return label_.Get(); }
90  void SetLabel(const std::string& label) { label_.Set(label); }
91 
93  using Notifier::Notify;
94 
95  protected:
97  class FieldBase {
98  public:
99  virtual ~FieldBase();
100 
102  int GetBit() const { return change_bit_; }
103 
104  protected:
106  FieldBase(const int change_bit, ResourceHolder* holder)
107  : change_bit_(change_bit),
108  holder_(holder) {
109  if (holder != NULL)
110  holder->AddField(this);
111  }
112 
113  void OnChanged() {
114  if (holder_) {
115  holder_->OnChanged(change_bit_);
116  holder_->Notify();
117  }
118  }
119 
121  void OnChanged(const int bit) {
122  if (holder_) {
123  holder_->OnChanged(bit);
124  holder_->Notify();
125  }
126  }
127 
128  private:
129  int change_bit_;
130  const ResourceHolder* holder_;
131 
132  DISALLOW_IMPLICIT_CONSTRUCTORS(FieldBase);
133  };
134 
137  template <typename T>
138  class Field : public FieldBase {
139  public:
140  Field(const int change_bit, const T& initial_value, ResourceHolder* holder)
141  : FieldBase(change_bit, holder),
142  value_(initial_value) {}
143 
144  Field(const Field& other)
145  : FieldBase(other),
146  value_(other.value_) {}
147 
148  ~Field() override {}
149 
152  virtual bool IsValid(const T& value) {
153  return true;
154  }
155 
157  const T& Get() const { return value_; }
158 
162  OnChanged();
163  return &value_;
164  }
165 
169  bool Set(const T& value) {
170  if (!IsValid(value)) {
171  LOG(ERROR) << "***ION: invalid value passed to Field::Set()";
172  } else if (value != value_) {
173  value_ = value;
174  OnChanged();
175  return true;
176  }
177  return false;
178  }
179 
180  private:
181  T value_;
182  };
183 
185  template <typename T>
186  class RangedField : public Field<T> {
187  public:
188  RangedField(const int change_bit, const T& initial_value,
189  const T& min_value, const T& max_value,
190  ResourceHolder* holder)
191  : Field<T>(change_bit, initial_value, holder),
192  min_value_(min_value),
193  max_value_(max_value) {
194  }
195 
196  ~RangedField() override {}
197 
199  bool IsValid(const T& value) override {
200  return value >= min_value_ && value <= max_value_;
201  }
202 
203  private:
204  const T min_value_;
205  const T max_value_;
206 
207  DISALLOW_IMPLICIT_CONSTRUCTORS(RangedField);
208  };
209 
215  template <typename T>
216  class VectorField : public FieldBase {
217  public:
218  VectorField(const int change_bit_start, const size_t max_entries,
219  ResourceHolder* holder)
220  : FieldBase(change_bit_start, holder),
221  max_entries_(max_entries),
222  entries_(*holder) {
223  DCHECK(holder != NULL);
224  holder->AddField(this);
225  }
226 
227  ~VectorField() override {}
228 
231  void Add(const T& value) {
232  if (entries_.size() >= max_entries_) {
233  LOG(ERROR) << "***ION: Too many entries added to VectorField"
234  << "with " << entries_.size() << " entries";
235  } else {
236  entries_.push_back(
237  Entry(GetBit() + static_cast<int>(entries_.size()), value));
239  OnChanged(entries_.back().bit);
240  }
241  }
242 
247  void Remove(size_t i) {
248  if (i < entries_.size()) {
249  entries_[i].value = entries_.back().value;
250  entries_.resize(entries_.size() - 1U);
252  if (!entries_.empty())
253  OnChanged(entries_[i].bit);
254  }
255  }
256 
259  const T& Get(const size_t i) const {
260  if (i < entries_.size()) {
261  return entries_[i].value;
262  } else {
263  LogIndexError(i);
264  return base::InvalidReference<T>();
265  }
266  }
267 
269  T* GetMutable(const size_t i) {
270  if (i < entries_.size()) {
271  OnChanged(entries_[i].bit);
272  return &entries_[i].value;
273  } else {
274  LogIndexError(i);
275  return NULL;
276  }
277  }
278 
282  bool Set(const size_t i, const T& value) {
283  if (i < entries_.size()) {
284  if (value != entries_[i].value) {
285  entries_[i].value = value;
286  OnChanged(entries_[i].bit);
287  return true;
288  }
289  } else {
290  LogIndexError(i);
291  }
292  return false;
293  }
294 
295  size_t GetCount() const { return entries_.size(); }
296 
297  private:
298  struct Entry {
299  Entry() : bit(-1) {}
300  Entry(int bit_in, const T& value_in)
301  : bit(bit_in),
302  value(value_in) {}
303  int bit;
304  T value;
305  };
306 
307  void LogIndexError(const size_t i) const {
308  LOG(ERROR) << "***ION: Invalid index " << i << " passed to VectorField "
309  << "with " << entries_.size() << " entries";
310  }
311 
312  size_t max_entries_;
313  base::AllocVector<Entry> entries_;
314 
315  DISALLOW_IMPLICIT_CONSTRUCTORS(VectorField);
316  };
317 
319  ResourceHolder();
320 
323  ~ResourceHolder() override;
324 
326  void OnChanged(int bit) const {
329  base::ReadLock read_lock(&lock_);
330  base::ReadGuard guard(&read_lock);
331  for (const auto& group : resources_)
332  for (const auto& entry : group)
333  entry.second->OnChanged(bit);
334  }
335 
336  private:
338  friend class FieldBase;
340  friend class Renderer;
341 
343  void AddField(FieldBase* field) { fields_.push_back(field); }
344 
346 
353  mutable base::ReadWriteLock lock_;
356  mutable std::atomic<int> resource_count_;
357 
360 
363  Field<std::string> label_;
364 };
365 
366 } // namespace gfx
367 } // namespace ion
368 
369 #endif // ION_GFX_RESOURCEHOLDER_H_
T * GetMutable()
Gets an editable version of the current value.
A Field that has a limited valid range of values.
This class can be used in place of std::unordered_map to allow an Ion Allocator to be used for memory...
int GetBit() const
Get the change bit.
RangedField(const int change_bit, const T &initial_value, const T &min_value, const T &max_value, ResourceHolder *holder)
void Remove(size_t i)
Removes an element from the VectorField, replacing it with the last entry in the VectorField.
#define DCHECK(expr)
Definition: logging.h:331
double value
#define LOG(severity)
Logs the streamed message unconditionally with a severity of severity.
Definition: logging.h:216
A Notifier both sends notifications to and receives notifications from other Notifiers.
Definition: notifier.h:35
A Field that holds a vector of up to some number of values.
void Add(const T &value)
Adds a value to the vector.
bool Set(const T &value)
Sets the value of the Field if it is valid and tells the resource what has changed.
std::string label
Definition: printer.cc:354
size_t GetGpuMemoryUsed() const
Returns the total amount of GPU memory used by this Holder's resource.
void OnChanged(int bit) const
Forwards OnChanged to all resources.
FieldBase(const int change_bit, ResourceHolder *holder)
The constructor is protected because this is an abstract base class.
bool IsValid(const T &value) override
Check if the proposed value falls within the correct range.
A LockGuard locks a mutex when created, and unlocks it when destroyed.
Definition: lockguards.h:90
Base class for Fields (see below).
void SetLabel(const std::string &label)
T * GetMutable(const size_t i)
Gets a non-const pointer to a value and triggers the change.
BaseChanges
All ResourceHolders derived from this should start their own change enums from kNumBaseChanges.
void OnChanged(const int bit)
Trigger a change for a specific bit.
The ReadWriteLock class defines a non-promotable lock that is very fast when only readers try to obta...
Definition: readwritelock.h:51
Copyright 2016 Google Inc.
Field(const int change_bit, const T &initial_value, ResourceHolder *holder)
InlinedAllocVectoris a similar to AllocVector, but uses inlined storage for its first N elements...
Definition: allocvector.h:99
intptr_t ResourceKey
Type of identifiers used to disambiguate between multiple resources created for the same Ion object b...
Definition: resourcebase.h:27
A generic field that represents some state in the resource.
int GetResourceCount() const
Returns the number of resources that this holder holds.
const T & Get() const
Gets a const version of the current value.
bool Set(const size_t i, const T &value)
If the index i is valid, sets the value at index i and tells the resource what has changed...
A ReadLock obtains a read lock, but has a similar interface to a Mutex and can be used with a ReadGua...
Definition: readwritelock.h:86
ResourceBase is an internal abstract base class for managed resources.
Definition: resourcebase.h:36
const std::string & GetLabel() const
Returns/sets the label of this.
virtual bool IsValid(const T &value)
Checks if a proposed value is valid.
The Renderer class handles rendering ION scene graphs using OpenGL.
Definition: renderer.h:50
ResourceHolder is an internal base class for objects that hold resources managed by an outside entity...
const T & Get(const size_t i) const
Gets a const reference to a value, if the index is valid, otherwise returns an InvalidReference.
VectorField(const int change_bit_start, const size_t max_entries, ResourceHolder *holder)
This class can be used in place of std::vector to allow an Ion Allocator to be used for memory alloca...
Definition: allocvector.h:50