Flutter Engine
The Flutter Engine
SkDeque.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2006 The Android Open Source Project
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
11
12#include <cstddef>
13
17 char* fBegin; // start of used section in this chunk
18 char* fEnd; // end of used section in this chunk
19 char* fStop; // end of the allocated chunk
20
21 char* start() { return (char*)(this + 1); }
22 const char* start() const { return (const char*)(this + 1); }
23
24 void init(size_t size) {
25 fNext = fPrev = nullptr;
26 fBegin = fEnd = nullptr;
27 fStop = (char*)this + size;
28 }
29};
30
31SkDeque::SkDeque(size_t elemSize, int allocCount)
32 : fElemSize(elemSize)
33 , fInitialStorage(nullptr)
34 , fCount(0)
35 , fAllocCount(allocCount) {
36 SkASSERT(allocCount >= 1);
37 fFrontBlock = fBackBlock = nullptr;
38 fFront = fBack = nullptr;
39}
40
41SkDeque::SkDeque(size_t elemSize, void* storage, size_t storageSize, int allocCount)
42 : fElemSize(elemSize)
43 , fInitialStorage(storage)
44 , fCount(0)
45 , fAllocCount(allocCount) {
46 SkASSERT(storageSize == 0 || storage != nullptr);
47 SkASSERT(allocCount >= 1);
48
49 if (storageSize >= sizeof(Block) + elemSize) {
50 fFrontBlock = (Block*)storage;
51 fFrontBlock->init(storageSize);
52 } else {
53 fFrontBlock = nullptr;
54 }
55 fBackBlock = fFrontBlock;
56 fFront = fBack = nullptr;
57}
58
60 Block* head = fFrontBlock;
61 Block* initialHead = (Block*)fInitialStorage;
62
63 while (head) {
64 Block* next = head->fNext;
65 if (head != initialHead) {
66 this->freeBlock(head);
67 }
68 head = next;
69 }
70}
71
73 fCount += 1;
74
75 if (nullptr == fFrontBlock) {
76 fFrontBlock = this->allocateBlock(fAllocCount);
77 fBackBlock = fFrontBlock; // update our linklist
78 }
79
80 Block* first = fFrontBlock;
81 char* begin;
82
83 if (nullptr == first->fBegin) {
84 INIT_CHUNK:
85 first->fEnd = first->fStop;
86 begin = first->fStop - fElemSize;
87 } else {
88 begin = first->fBegin - fElemSize;
89 if (begin < first->start()) { // no more room in this chunk
90 // should we alloc more as we accumulate more elements?
91 first = this->allocateBlock(fAllocCount);
92 first->fNext = fFrontBlock;
93 fFrontBlock->fPrev = first;
94 fFrontBlock = first;
95 goto INIT_CHUNK;
96 }
97 }
98
99 first->fBegin = begin;
100
101 if (nullptr == fFront) {
102 SkASSERT(nullptr == fBack);
103 fFront = fBack = begin;
104 } else {
105 SkASSERT(fBack);
106 fFront = begin;
107 }
108
109 return begin;
110}
111
113 fCount += 1;
114
115 if (nullptr == fBackBlock) {
116 fBackBlock = this->allocateBlock(fAllocCount);
117 fFrontBlock = fBackBlock; // update our linklist
118 }
119
120 Block* last = fBackBlock;
121 char* end;
122
123 if (nullptr == last->fBegin) {
124 INIT_CHUNK:
125 last->fBegin = last->start();
126 end = last->fBegin + fElemSize;
127 } else {
128 end = last->fEnd + fElemSize;
129 if (end > last->fStop) { // no more room in this chunk
130 // should we alloc more as we accumulate more elements?
131 last = this->allocateBlock(fAllocCount);
132 last->fPrev = fBackBlock;
133 fBackBlock->fNext = last;
134 fBackBlock = last;
135 goto INIT_CHUNK;
136 }
137 }
138
139 last->fEnd = end;
140 end -= fElemSize;
141
142 if (nullptr == fBack) {
143 SkASSERT(nullptr == fFront);
144 fFront = fBack = end;
145 } else {
146 SkASSERT(fFront);
147 fBack = end;
148 }
149
150 return end;
151}
152
154 SkASSERT(fCount > 0);
155 fCount -= 1;
156
157 Block* first = fFrontBlock;
158
159 SkASSERT(first != nullptr);
160
161 if (first->fBegin == nullptr) { // we were marked empty from before
162 first = first->fNext;
163 SkASSERT(first != nullptr); // else we popped too far
164 first->fPrev = nullptr;
165 this->freeBlock(fFrontBlock);
166 fFrontBlock = first;
167 }
168
169 char* begin = first->fBegin + fElemSize;
170 SkASSERT(begin <= first->fEnd);
171
172 if (begin < fFrontBlock->fEnd) {
173 first->fBegin = begin;
174 SkASSERT(first->fBegin);
175 fFront = first->fBegin;
176 } else {
177 first->fBegin = first->fEnd = nullptr; // mark as empty
178 if (nullptr == first->fNext) {
179 fFront = fBack = nullptr;
180 } else {
181 SkASSERT(first->fNext->fBegin);
182 fFront = first->fNext->fBegin;
183 }
184 }
185}
186
188 SkASSERT(fCount > 0);
189 fCount -= 1;
190
191 Block* last = fBackBlock;
192
193 SkASSERT(last != nullptr);
194
195 if (last->fEnd == nullptr) { // we were marked empty from before
196 last = last->fPrev;
197 SkASSERT(last != nullptr); // else we popped too far
198 last->fNext = nullptr;
199 this->freeBlock(fBackBlock);
200 fBackBlock = last;
201 }
202
203 char* end = last->fEnd - fElemSize;
204 SkASSERT(end >= last->fBegin);
205
206 if (end > last->fBegin) {
207 last->fEnd = end;
208 SkASSERT(last->fEnd);
209 fBack = last->fEnd - fElemSize;
210 } else {
211 last->fBegin = last->fEnd = nullptr; // mark as empty
212 if (nullptr == last->fPrev) {
213 fFront = fBack = nullptr;
214 } else {
215 SkASSERT(last->fPrev->fEnd);
216 fBack = last->fPrev->fEnd - fElemSize;
217 }
218 }
219}
220
221int SkDeque::numBlocksAllocated() const {
222 int numBlocks = 0;
223
224 for (const Block* temp = fFrontBlock; temp; temp = temp->fNext) {
225 ++numBlocks;
226 }
227
228 return numBlocks;
229}
230
231SkDeque::Block* SkDeque::allocateBlock(int allocCount) {
232 Block* newBlock = (Block*)sk_malloc_throw(sizeof(Block) + allocCount * fElemSize);
233 newBlock->init(sizeof(Block) + allocCount * fElemSize);
234 return newBlock;
235}
236
237void SkDeque::freeBlock(Block* block) {
238 sk_free(block);
239}
240
241///////////////////////////////////////////////////////////////////////////////
242
243SkDeque::Iter::Iter() : fCurBlock(nullptr), fPos(nullptr), fElemSize(0) {}
244
246 this->reset(d, startLoc);
247}
248
249// Due to how reset and next work, next actually returns the current element
250// pointed to by fPos and then updates fPos to point to the next one.
252 char* pos = fPos;
253
254 if (pos) { // if we were valid, try to move to the next setting
255 char* next = pos + fElemSize;
256 SkASSERT(next <= fCurBlock->fEnd);
257 if (next == fCurBlock->fEnd) { // exhausted this chunk, move to next
258 do {
259 fCurBlock = fCurBlock->fNext;
260 } while (fCurBlock != nullptr && fCurBlock->fBegin == nullptr);
261 next = fCurBlock ? fCurBlock->fBegin : nullptr;
262 }
263 fPos = next;
264 }
265 return pos;
266}
267
268// Like next, prev actually returns the current element pointed to by fPos and
269// then makes fPos point to the previous element.
271 char* pos = fPos;
272
273 if (pos) { // if we were valid, try to move to the prior setting
274 char* prev = pos - fElemSize;
275 SkASSERT(prev >= fCurBlock->fBegin - fElemSize);
276 if (prev < fCurBlock->fBegin) { // exhausted this chunk, move to prior
277 do {
278 fCurBlock = fCurBlock->fPrev;
279 } while (fCurBlock != nullptr && fCurBlock->fEnd == nullptr);
280 prev = fCurBlock ? fCurBlock->fEnd - fElemSize : nullptr;
281 }
282 fPos = prev;
283 }
284 return pos;
285}
286
287// reset works by skipping through the spare blocks at the start (or end)
288// of the doubly linked list until a non-empty one is found. The fPos
289// member is then set to the first (or last) element in the block. If
290// there are no elements in the deque both fCurBlock and fPos will come
291// out of this routine nullptr.
292void SkDeque::Iter::reset(const SkDeque& d, IterStart startLoc) {
293 fElemSize = d.fElemSize;
294
295 if (kFront_IterStart == startLoc) {
296 // initialize the iterator to start at the front
297 fCurBlock = d.fFrontBlock;
298 while (fCurBlock && nullptr == fCurBlock->fBegin) {
299 fCurBlock = fCurBlock->fNext;
300 }
301 fPos = fCurBlock ? fCurBlock->fBegin : nullptr;
302 } else {
303 // initialize the iterator to start at the back
304 fCurBlock = d.fBackBlock;
305 while (fCurBlock && nullptr == fCurBlock->fEnd) {
306 fCurBlock = fCurBlock->fPrev;
307 }
308 fPos = fCurBlock ? fCurBlock->fEnd - fElemSize : nullptr;
309 }
310}
m reset()
SkPoint pos
static float next(float f)
static float prev(float f)
#define SkASSERT(cond)
Definition: SkAssert.h:116
SK_API void sk_free(void *)
static void * sk_malloc_throw(size_t size)
Definition: SkMalloc.h:67
void * next()
Definition: SkDeque.cpp:251
void * prev()
Definition: SkDeque.cpp:270
void reset(const SkDeque &d, IterStart startLoc)
Definition: SkDeque.cpp:292
void * push_back()
Definition: SkDeque.cpp:112
~SkDeque()
Definition: SkDeque.cpp:59
void pop_front()
Definition: SkDeque.cpp:153
void pop_back()
Definition: SkDeque.cpp:187
void * push_front()
Definition: SkDeque.cpp:72
SkDeque(size_t elemSize, int allocCount=1)
Definition: SkDeque.cpp:31
size_t elemSize() const
Definition: SkDeque.h:40
static const char * begin(const StringSlice &s)
Definition: editor.cpp:252
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE auto & d
Definition: main.cc:19
glong glong end
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition: switches.h:259
const char * start() const
Definition: SkDeque.cpp:22
char * start()
Definition: SkDeque.cpp:21
char * fEnd
Definition: SkDeque.cpp:18
void init(size_t size)
Definition: SkDeque.cpp:24
Block * fPrev
Definition: SkDeque.cpp:16
Block * fNext
Definition: SkDeque.cpp:15
char * fBegin
Definition: SkDeque.cpp:17
char * fStop
Definition: SkDeque.cpp:19