allocators.h
1 /*************************************************************************/
2 /* allocators.h */
3 /*************************************************************************/
4 /* This file is part of: */
5 /* GODOT ENGINE */
6 /* http://www.godotengine.org */
7 /*************************************************************************/
8 /* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
9 /* */
10 /* Permission is hereby granted, free of charge, to any person obtaining */
11 /* a copy of this software and associated documentation files (the */
12 /* "Software"), to deal in the Software without restriction, including */
13 /* without limitation the rights to use, copy, modify, merge, publish, */
14 /* distribute, sublicense, and/or sell copies of the Software, and to */
15 /* permit persons to whom the Software is furnished to do so, subject to */
16 /* the following conditions: */
17 /* */
18 /* The above copyright notice and this permission notice shall be */
19 /* included in all copies or substantial portions of the Software. */
20 /* */
21 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
22 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
23 /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
24 /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
25 /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
26 /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
27 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
28 /*************************************************************************/
29 #ifndef ALLOCATORS_H
30 #define ALLOCATORS_H
31 
32 #include "os/memory.h"
33 template<int PREALLOC_COUNT=64, int MAX_HANDS=8>
35 
36  enum {
37 
38  USED_FLAG=(1<<30),
39  USED_MASK=USED_FLAG-1
40  };
41 
42  struct Balloon {
43 
44  Balloon *next;
45  Balloon *prev;
46  uint32_t hand;
47  };
48 
49 
50  struct Hand {
51 
52  int used;
53  int allocated;
54  Balloon *first;
55  Balloon *last;
56  };
57 
58 
59  Hand hands[MAX_HANDS];
60 
61 
62 
63 public:
64 
65  void* alloc(size_t p_size) {
66 
67  size_t max=(1<<MAX_HANDS);
68  ERR_FAIL_COND_V( p_size>max, NULL );
69 
70  unsigned int hand=0;
71 
72  while(p_size>(size_t)(1<<hand)) ++hand;
73 
74  Hand &h=hands[hand];
75 
76  if (h.used==h.allocated) {
77 
78  for(int i=0;i<PREALLOC_COUNT;i++) {
79 
80  Balloon *b = (Balloon*)memalloc(sizeof(Balloon)+(1<<hand));
81  b->hand=hand;
82  if (h.last) {
83 
84  b->prev=h.last;
85  h.last->next=b;
86  h.last=b;
87  } else {
88 
89  b->prev=NULL;
90  h.last=b;
91  h.first=b;
92  }
93  }
94 
95  h.last->next=NULL;
96  h.allocated+=PREALLOC_COUNT;
97  }
98 
99  Balloon *pick=h.last;
100 
101  ERR_FAIL_COND_V( (pick->hand&USED_FLAG), NULL );
102 
103  // remove last
104  h.last=h.last->prev;
105  h.last->next=NULL;
106 
107  pick->next=h.first;
108  h.first->prev=pick;
109  pick->prev=NULL;
110  h.first=pick;
111  h.used++;
112  pick->hand|=USED_FLAG;
113 
114  return (void*)(pick+1);
115  }
116 
117  void free(void* p_ptr) {
118 
119  Balloon *b=(Balloon*)p_ptr;
120  b-=1;
121 
122  ERR_FAIL_COND(!(b->hand&USED_FLAG) );
123 
124  b->hand=b->hand&USED_MASK; // not used
125  int hand=b->hand;
126 
127  Hand &h=hands[hand];
128 
129  if (b==h.first)
130  h.first=b->next;
131 
132  if (b->prev)
133  b->prev->next=b->next;
134  if (b->next)
135  b->next->prev=b->prev;
136 
137  if (h.last!=b) {
138  h.last->next=b;
139  b->prev=h.last;
140  b->next=NULL;
141  h.last=b;
142  }
143 
144  h.used--;
145 
146  if (h.used<=(h.allocated-(PREALLOC_COUNT*2))) { // this is done to ensure no alloc/free is done constantly
147 
148  for(int i=0;i<PREALLOC_COUNT;i++) {
149  ERR_CONTINUE( h.last->hand& USED_FLAG );
150 
151  Balloon *new_last=h.last->prev;
152  if (new_last)
153  new_last->next=NULL;
154  memfree( h.last );
155  h.last=new_last;
156  }
157  h.allocated-=PREALLOC_COUNT;
158  }
159  }
160 
161  BalloonAllocator() {
162 
163  for(int i=0;i<MAX_HANDS;i++) {
164 
165  hands[i].allocated=0;
166  hands[i].used=0;
167  hands[i].first=NULL;
168  hands[i].last=NULL;
169  }
170 
171  }
172 
173  void clear() {
174 
175  for(int i=0;i<MAX_HANDS;i++) {
176 
177  while(hands[i].first) {
178 
179  Balloon *b=hands[i].first;
180  hands[i].first=b->next;
181  memfree(b);
182  }
183 
184  hands[i].allocated=0;
185  hands[i].used=0;
186  hands[i].first=NULL;
187  hands[i].last=NULL;
188  }
189  }
190 
191  ~BalloonAllocator() {
192 
193  clear();
194  }
195 };
196 
197 
198 #endif // ALLOCATORS_H
Definition: allocators.h:34