1// Copyright 2014 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 TESTS_NACL_IO_TEST_FAKE_RESOURCE_MANAGER_H_
6#define TESTS_NACL_IO_TEST_FAKE_RESOURCE_MANAGER_H_
7
8#include <map>
9
10#include <ppapi/c/pp_resource.h>
11
12#include "sdk_util/atomicops.h"
13#include "sdk_util/macros.h"
14#include "sdk_util/simple_lock.h"
15
16class FakeResource;
17class FakeResourceTracker;
18
19class FakeResourceManager {
20 public:
21  FakeResourceManager();
22  ~FakeResourceManager();
23
24  PP_Resource Create(FakeResource* resource,
25                     const char* classname,
26                     const char* file,
27                     int line);
28  void AddRef(PP_Resource handle);
29  void Release(PP_Resource handle);
30  template <typename T>
31  T* Get(PP_Resource handle, bool not_found_ok=false);
32
33 private:
34  FakeResourceTracker* Get(PP_Resource handle, bool not_found_ok);
35
36  typedef std::map<PP_Resource, FakeResourceTracker*> ResourceMap;
37  PP_Resource next_handle_;
38  ResourceMap resource_map_;
39  sdk_util::SimpleLock lock_;  // Protects next_handle_ and resource_map_.
40
41  DISALLOW_COPY_AND_ASSIGN(FakeResourceManager);
42};
43
44// FakeResourceTracker wraps a FakeResource to keep metadata about the
45// resource, including its refcount, the type of resource, etc.
46class FakeResourceTracker {
47 public:
48  FakeResourceTracker(FakeResource* resource,
49                      const char* classname,
50                      const char* file,
51                      int line);
52  ~FakeResourceTracker();
53
54  void AddRef() { sdk_util::AtomicAddFetch(&ref_count_, 1); }
55  void Release() { sdk_util::AtomicAddFetch(&ref_count_, -1); }
56  int32_t ref_count() const { return ref_count_; }
57
58  // Give up ownership of this resource. It is the responsibility of the caller
59  // to delete this FakeResource.
60  FakeResource* Pass() {
61    FakeResource* result = resource_;
62    resource_ = NULL;
63    return result;
64  }
65
66  template <typename T>
67  T* resource() {
68    if (!CheckType(T::classname()))
69      return NULL;
70
71    return static_cast<T*>(resource_);
72  }
73
74  FakeResource* resource() { return resource_; }
75
76  const char* classname() const { return classname_; }
77  const char* file() const { return file_; }
78  int line() const { return line_; }
79
80 private:
81  bool CheckType(const char* classname) const;
82
83  FakeResource* resource_;  // Owned.
84  const char* classname_;   // Weak reference.
85  const char* file_;        // Weak reference.
86  int line_;
87  int32_t ref_count_;
88
89  DISALLOW_COPY_AND_ASSIGN(FakeResourceTracker);
90};
91
92class FakeResource {
93 public:
94  FakeResource() {}
95  // Called when the resource is destroyed. For debugging purposes, this does
96  // not happen until the resource manager is destroyed.
97  virtual ~FakeResource() {}
98  // Called when the last reference to the resource is released.
99  virtual void Destroy() {}
100
101 private:
102  DISALLOW_COPY_AND_ASSIGN(FakeResource);
103};
104
105template <typename T>
106inline T* FakeResourceManager::Get(PP_Resource handle, bool not_found_ok) {
107  FakeResourceTracker* tracker = Get(handle, not_found_ok);
108  if (!tracker)
109    return NULL;
110  return tracker->resource<T>();
111}
112
113#define CREATE_RESOURCE(MANAGER, TYPE, RESOURCE) \
114  (MANAGER)->Create((RESOURCE), #TYPE, __FILE__, __LINE__)
115
116#endif  // TESTS_NACL_IO_TEST_FAKE_RESOURCE_MANAGER_H_
117