blob: f0558811c00e50c5522b30bc2f19e4b3acaa9c01 [file] [log] [blame]
David Ghandeharief7f9012017-03-26 00:17:07 -07001/*
2 * Copyright 2017 Google Inc. All Rights Reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef NB_STD_ALLOCATOR_H_
18#define NB_STD_ALLOCATOR_H_
19
20#include <memory>
21
David Ghandehari00be30f2017-04-27 21:30:48 -070022#include "nb/allocator.h"
23#include "starboard/configuration.h"
David Ghandeharief7f9012017-03-26 00:17:07 -070024#include "starboard/types.h"
25
26namespace nb {
27
28// A standard container compatible allocator that delegates allocations to a
29// custom allocator. This allows standard containers like vector<> and map<> to
30// use custom allocator schemes.
31//
32// AllocatorT:
33// This is the backing allocator that implements Allocate(...) and
34// Deallocate(...).
35//
36// Example:
37// struct AllocatorImpl {
38// static void* Allocate(size_t n) {
39// return SbMemoryAllocate(n);
40// }
41// // Second argument can be used for accounting, but is otherwise optional.
42// static void Deallocate(void* ptr, size_t n) {
43// SbMemoryDeallocate(ptr);
44// }
45// };
46//
47// typedef std::vector<int, StdAllocator<T, AllocatorImpl> > MyVector;
48// MyVector vector;
49// ...
50template <typename T, typename AllocatorT>
51class StdAllocator : public std::allocator<T> {
52 public:
53 typedef typename std::allocator<T>::pointer pointer;
54 typedef typename std::allocator<T>::const_pointer const_pointer;
55 typedef typename std::allocator<T>::reference reference;
56 typedef typename std::allocator<T>::const_reference const_reference;
57 typedef typename std::allocator<T>::size_type size_type;
58 typedef typename std::allocator<T>::value_type value_type;
59 typedef typename std::allocator<T>::difference_type difference_type;
60
61 StdAllocator() {}
62
63 // Constructor used for rebinding
64 template <typename U, typename V>
David Ghandehari00be30f2017-04-27 21:30:48 -070065 StdAllocator(const StdAllocator<U, V>&) {}
David Ghandeharief7f9012017-03-26 00:17:07 -070066
67 pointer allocate(size_type n,
68 std::allocator<void>::const_pointer hint = NULL) {
69 void* ptr = AllocatorT::Allocate(n * sizeof(value_type));
70 return static_cast<pointer>(ptr);
71 }
72
73 void deallocate(pointer ptr, size_type n) {
74 AllocatorT::Deallocate(ptr, n * sizeof(value_type));
75 }
76 template <typename U>
77 struct rebind {
78 typedef StdAllocator<U, AllocatorT> other;
79 };
80};
81
David Ghandehari00be30f2017-04-27 21:30:48 -070082// A standard container compatible allocator that delegates allocations to a
83// custom allocator via a shared pointer. This differs from StdAllocator since
84// StdAllocator binds to static functions. This important difference allows
85// StdDynamicAllocator to keep memory accounting on a per-instance basis, but
86// otherwise is a tad slower, harder to instantiate and produces less readable
87// code.
88//
89// When in doubt, use StdAllocator over StdDynamicAllocator.
90//
91// Passed in nb::Allocator:
92// Even though nb::Allocator has many functions for alignment, only the two
93// are used within StdDynamicAllocator:
94// void* nb::Allocator::Allocate() -and-
95// void nb::FreeWithSize(void* ptr, size_t optional_size)
96//
97// Example of Allocator Definition:
98// class MyAllocator : public SimpleAllocator {
99// public:
Andrew Top200ce4b2018-01-29 13:43:50 -0800100// void* Allocate(size_t size) override {
David Ghandehari00be30f2017-04-27 21:30:48 -0700101// return SbMemoryAllocate(size);
102// }
103//
104// // Second argument can be used for accounting, but is otherwise optional.
Andrew Top200ce4b2018-01-29 13:43:50 -0800105// void FreeWithSize(void* ptr, size_t optional_size) override {
David Ghandehari00be30f2017-04-27 21:30:48 -0700106// SbMemoryDeallocate(ptr);
107// }
108//
109// // ... other functions
110// };
111//
112// Example of std::vector<int>:
113// typedef StdDynamicAllocator<int> IntAllocator;
114// typedef std::vector<int, IntAllocator> IntVector;
115//
116// MyAllocator my_allocator;
117// // Note that IntVector is not default constructible!
118// IntVector int_vector(IntAllocator(&my_allocator));
119//
120// Example of std::map<int, int>:
121// // Note that maps require std::less() instance to be passed in whenever
122// // a custom allocator is passed in.
123// typedef std::map<int, int, std::less<int>, MyAllocator> IntMap;
124// IntMap int_map(std::less<int>(), /* std::less<int> required pre-C++11 */
125// IntAllocator(&my_allocator));
126template <typename T>
127class StdDynamicAllocator : public std::allocator<T> {
128 public:
129 typedef typename std::allocator<T>::pointer pointer;
130 typedef typename std::allocator<T>::const_pointer const_pointer;
131 typedef typename std::allocator<T>::reference reference;
132 typedef typename std::allocator<T>::const_reference const_reference;
133 typedef typename std::allocator<T>::size_type size_type;
134 typedef typename std::allocator<T>::value_type value_type;
135 typedef typename std::allocator<T>::difference_type difference_type;
136
137 explicit StdDynamicAllocator(Allocator* allocator) : allocator_(allocator) {}
138 StdDynamicAllocator(StdDynamicAllocator& std_allocator)
139 : allocator_(std_allocator.allocator_) {}
140
141 // Constructor used for rebinding
142 template <typename U>
143 StdDynamicAllocator(const StdDynamicAllocator<U>& x)
144 : allocator_(x.allocator()) {}
145
146 pointer allocate(size_type n,
147 std::allocator<void>::const_pointer hint = NULL) {
David Ghandehari00be30f2017-04-27 21:30:48 -0700148 void* ptr = allocator_->Allocate(n * sizeof(value_type));
149 return static_cast<pointer>(ptr);
150 }
151
152 void deallocate(pointer ptr, size_type n) {
153 allocator_->FreeWithSize(ptr, n * sizeof(value_type));
154 }
155 template <typename U>
156 struct rebind {
157 typedef StdDynamicAllocator<U> other;
158 };
159
160 Allocator* allocator() const { return allocator_; }
161
162 private:
163 Allocator* allocator_;
164};
165
David Ghandeharief7f9012017-03-26 00:17:07 -0700166} // namespace nb
167
168#endif // NB_STD_ALLOCATOR_H_