Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(52)

Side by Side Diff: src/core/SkRWBuffer.cpp

Issue 1871953002: Fixes for SkRWBuffer (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright 2015 Google Inc. 2 * Copyright 2015 Google Inc.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 7
8 #include "SkRWBuffer.h" 8 #include "SkRWBuffer.h"
9 #include "SkStream.h" 9 #include "SkStream.h"
10 10
(...skipping 22 matching lines...) Expand all
33 // Return number of bytes actually appended 33 // Return number of bytes actually appended
34 size_t append(const void* src, size_t length) { 34 size_t append(const void* src, size_t length) {
35 this->validate(); 35 this->validate();
36 size_t amount = SkTMin(this->avail(), length); 36 size_t amount = SkTMin(this->avail(), length);
37 memcpy(this->availData(), src, amount); 37 memcpy(this->availData(), src, amount);
38 fUsed += amount; 38 fUsed += amount;
39 this->validate(); 39 this->validate();
40 return amount; 40 return amount;
41 } 41 }
42 42
43 // Do not call in the reader thread, since the writer may be updating fUsed.
44 // (The assertion is still true, but TSAN still may complain about its racin ess.)
43 void validate() const { 45 void validate() const {
44 #ifdef SK_DEBUG 46 #ifdef SK_DEBUG
45 SkASSERT(fCapacity > 0); 47 SkASSERT(fCapacity > 0);
46 SkASSERT(fUsed <= fCapacity); 48 SkASSERT(fUsed <= fCapacity);
47 #endif 49 #endif
48 } 50 }
49 51
50 private: 52 private:
51 static size_t LengthToCapacity(size_t length) { 53 static size_t LengthToCapacity(size_t length) {
52 const size_t minSize = kMinAllocSize - sizeof(SkBufferBlock); 54 const size_t minSize = kMinAllocSize - sizeof(SkBufferBlock);
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
87 SkBufferBlock* block = fBlock.fNext; 89 SkBufferBlock* block = fBlock.fNext;
88 sk_free((void*)this); 90 sk_free((void*)this);
89 while (block) { 91 while (block) {
90 SkBufferBlock* next = block->fNext; 92 SkBufferBlock* next = block->fNext;
91 sk_free(block); 93 sk_free(block);
92 block = next; 94 block = next;
93 } 95 }
94 } 96 }
95 } 97 }
96 98
97 void validate(size_t minUsed, SkBufferBlock* tail = nullptr) const { 99 void validate(size_t minUsed, const SkBufferBlock* tail = nullptr) const {
98 #ifdef SK_DEBUG 100 #ifdef SK_DEBUG
99 SkASSERT(fRefCnt > 0); 101 SkASSERT(fRefCnt > 0);
100 size_t totalUsed = 0; 102 size_t totalUsed = 0;
101 const SkBufferBlock* block = &fBlock; 103 const SkBufferBlock* block = &fBlock;
102 const SkBufferBlock* lastBlock = block; 104 const SkBufferBlock* lastBlock = block;
103 while (block) { 105 while (block) {
104 block->validate(); 106 block->validate();
105 totalUsed += block->fUsed; 107 totalUsed += block->fUsed;
106 lastBlock = block; 108 lastBlock = block;
107 block = block->fNext; 109 block = block->fNext;
108 } 110 }
109 SkASSERT(minUsed <= totalUsed); 111 SkASSERT(minUsed <= totalUsed);
110 if (tail) { 112 if (tail) {
111 SkASSERT(tail == lastBlock); 113 SkASSERT(tail == lastBlock);
112 } 114 }
113 #endif 115 #endif
114 } 116 }
115 }; 117 };
116 118
117 SkROBuffer::SkROBuffer(const SkBufferHead* head, size_t used) : fHead(head), fUs ed(used) { 119 SkROBuffer::SkROBuffer(const SkBufferHead* head, size_t used, const SkBufferBloc k* tail)
120 : fHead(head)
121 , fUsed(used)
122 , fTail(tail)
123 , fTailUsed(tail ? tail->fUsed : 0)
124 {
118 if (head) { 125 if (head) {
119 fHead->ref(); 126 fHead->ref();
120 SkASSERT(used > 0); 127 SkASSERT(used > 0);
121 head->validate(used); 128 SkASSERT(tail);
129 head->validate(used, tail);
122 } else { 130 } else {
123 SkASSERT(0 == used); 131 SkASSERT(0 == used);
132 SkASSERT(!tail);
133 SkASSERT(0 == fTailUsed);
124 } 134 }
125 } 135 }
126 136
127 SkROBuffer::~SkROBuffer() { 137 SkROBuffer::~SkROBuffer() {
128 if (fHead) { 138 if (fHead) {
129 fHead->validate(fUsed);
130 fHead->unref(); 139 fHead->unref();
131 } 140 }
132 } 141 }
133 142
134 SkROBuffer::Iter::Iter(const SkROBuffer* buffer) { 143 SkROBuffer::Iter::Iter(const SkROBuffer* buffer) {
135 this->reset(buffer); 144 this->reset(buffer);
136 } 145 }
137 146
138 void SkROBuffer::Iter::reset(const SkROBuffer* buffer) { 147 void SkROBuffer::Iter::reset(const SkROBuffer* buffer) {
148 if (!buffer->fUsed) {
149 SkASSERT(!buffer->fHead);
150 buffer = nullptr;
151 }
152 fBuffer = buffer;
139 if (buffer) { 153 if (buffer) {
154 SkASSERT(buffer->fHead);
140 fBlock = &buffer->fHead->fBlock; 155 fBlock = &buffer->fHead->fBlock;
141 fRemaining = buffer->fUsed; 156 fRemaining = buffer->fUsed;
142 } else { 157 } else {
143 fBlock = nullptr; 158 fBlock = nullptr;
144 fRemaining = 0; 159 fRemaining = 0;
145 } 160 }
146 } 161 }
147 162
148 const void* SkROBuffer::Iter::data() const { 163 const void* SkROBuffer::Iter::data() const {
149 return fRemaining ? fBlock->startData() : nullptr; 164 return fRemaining ? fBlock->startData() : nullptr;
150 } 165 }
151 166
152 size_t SkROBuffer::Iter::size() const { 167 size_t SkROBuffer::Iter::size() const {
153 if (!fBlock) { 168 if (!fBlock) {
154 return 0; 169 return 0;
155 } 170 }
156 return SkTMin(fBlock->fUsed, fRemaining); 171
172 if (fBuffer->fTail == fBlock) {
173 return fBuffer->fTailUsed;
174 }
175
176 // There is another block that this object knows about, with data that is
177 // accounted for in fRemaining.
178 // Further, since there are more blocks, it is safe to read fUsed, which wil l
179 // not be updated anymore.
180 SkASSERT(fRemaining > fBlock->fUsed);
181 return fBlock->fUsed;
157 } 182 }
158 183
159 bool SkROBuffer::Iter::next() { 184 bool SkROBuffer::Iter::next() {
160 if (fRemaining) { 185 if (fRemaining) {
161 fRemaining -= this->size(); 186 fRemaining -= this->size();
162 fBlock = fBlock->fNext; 187 if (fBuffer->fTail == fBlock) {
188 // There are more blocks, but fBuffer does not know about them.
189 SkASSERT(fRemaining == 0);
190 fBlock = nullptr;
191 } else {
192 fBlock = fBlock->fNext;
193 }
163 } 194 }
164 return fRemaining != 0; 195 return fRemaining != 0;
165 } 196 }
166 197
167 SkRWBuffer::SkRWBuffer(size_t initialCapacity) : fHead(nullptr), fTail(nullptr), fTotalUsed(0) {} 198 SkRWBuffer::SkRWBuffer(size_t initialCapacity) : fHead(nullptr), fTail(nullptr), fTotalUsed(0) {}
168 199
169 SkRWBuffer::~SkRWBuffer() { 200 SkRWBuffer::~SkRWBuffer() {
170 this->validate(); 201 this->validate();
171 if (fHead) { 202 if (fHead) {
172 fHead->unref(); 203 fHead->unref();
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
227 void SkRWBuffer::validate() const { 258 void SkRWBuffer::validate() const {
228 if (fHead) { 259 if (fHead) {
229 fHead->validate(fTotalUsed, fTail); 260 fHead->validate(fTotalUsed, fTail);
230 } else { 261 } else {
231 SkASSERT(nullptr == fTail); 262 SkASSERT(nullptr == fTail);
232 SkASSERT(0 == fTotalUsed); 263 SkASSERT(0 == fTotalUsed);
233 } 264 }
234 } 265 }
235 #endif 266 #endif
236 267
237 SkROBuffer* SkRWBuffer::newRBufferSnapshot() const { return new SkROBuffer(fHead , fTotalUsed); } 268 SkROBuffer* SkRWBuffer::newRBufferSnapshot() const {
269 return new SkROBuffer(fHead, fTotalUsed, fTail);
270 }
238 271
239 //////////////////////////////////////////////////////////////////////////////// /////////////////// 272 //////////////////////////////////////////////////////////////////////////////// ///////////////////
240 273
241 class SkROBufferStreamAsset : public SkStreamAsset { 274 class SkROBufferStreamAsset : public SkStreamAsset {
242 void validate() const { 275 void validate() const {
243 #ifdef SK_DEBUG 276 #ifdef SK_DEBUG
244 SkASSERT(fGlobalOffset <= fBuffer->size()); 277 SkASSERT(fGlobalOffset <= fBuffer->size());
245 SkASSERT(fLocalOffset <= fIter.size()); 278 SkASSERT(fLocalOffset <= fIter.size());
246 SkASSERT(fLocalOffset <= fGlobalOffset); 279 SkASSERT(fLocalOffset <= fGlobalOffset);
247 #endif 280 #endif
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
345 const SkROBuffer* fBuffer; 378 const SkROBuffer* fBuffer;
346 SkROBuffer::Iter fIter; 379 SkROBuffer::Iter fIter;
347 size_t fLocalOffset; 380 size_t fLocalOffset;
348 size_t fGlobalOffset; 381 size_t fGlobalOffset;
349 }; 382 };
350 383
351 SkStreamAsset* SkRWBuffer::newStreamSnapshot() const { 384 SkStreamAsset* SkRWBuffer::newStreamSnapshot() const {
352 SkAutoTUnref<SkROBuffer> buffer(this->newRBufferSnapshot()); 385 SkAutoTUnref<SkROBuffer> buffer(this->newRBufferSnapshot());
353 return new SkROBufferStreamAsset(buffer); 386 return new SkROBufferStreamAsset(buffer);
354 } 387 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698