| Index: src/core/SkRWBuffer.cpp
|
| diff --git a/src/core/SkRWBuffer.cpp b/src/core/SkRWBuffer.cpp
|
| index f0b565edf3f685360844dace2af2997de810b5ed..8f50c25c2aafe0a4de4d19f764278e6ea7c6eab5 100644
|
| --- a/src/core/SkRWBuffer.cpp
|
| +++ b/src/core/SkRWBuffer.cpp
|
| @@ -42,6 +42,8 @@ struct SkBufferBlock {
|
| return amount;
|
| }
|
|
|
| + // Do not call in the reader thread, since the writer may be updating fUsed.
|
| + // (The assertion is still true, but TSAN still may complain about its raciness.)
|
| void validate() const {
|
| #ifdef SK_DEBUG
|
| SkASSERT(fCapacity > 0);
|
| @@ -94,7 +96,7 @@ struct SkBufferHead {
|
| }
|
| }
|
|
|
| - void validate(size_t minUsed, SkBufferBlock* tail = nullptr) const {
|
| + void validate(size_t minUsed, const SkBufferBlock* tail = nullptr) const {
|
| #ifdef SK_DEBUG
|
| SkASSERT(fRefCnt > 0);
|
| size_t totalUsed = 0;
|
| @@ -118,21 +120,21 @@ struct SkBufferHead {
|
| // The reader can only access block.fCapacity (which never changes), and cannot access
|
| // block.fUsed, which may be updated by the writer.
|
| //
|
| -SkROBuffer::SkROBuffer(const SkBufferHead* head, size_t available)
|
| - : fHead(head), fAvailable(available)
|
| +SkROBuffer::SkROBuffer(const SkBufferHead* head, size_t available, const SkBufferBlock* tail)
|
| + : fHead(head), fAvailable(available), fTail(tail)
|
| {
|
| if (head) {
|
| fHead->ref();
|
| SkASSERT(available > 0);
|
| - head->validate(available);
|
| + head->validate(available, tail);
|
| } else {
|
| SkASSERT(0 == available);
|
| + SkASSERT(!tail);
|
| }
|
| }
|
|
|
| SkROBuffer::~SkROBuffer() {
|
| if (fHead) {
|
| - fHead->validate(fAvailable);
|
| fHead->unref();
|
| }
|
| }
|
| @@ -142,7 +144,8 @@ SkROBuffer::Iter::Iter(const SkROBuffer* buffer) {
|
| }
|
|
|
| void SkROBuffer::Iter::reset(const SkROBuffer* buffer) {
|
| - if (buffer) {
|
| + fBuffer = buffer;
|
| + if (buffer && buffer->fHead) {
|
| fBlock = &buffer->fHead->fBlock;
|
| fRemaining = buffer->fAvailable;
|
| } else {
|
| @@ -165,7 +168,13 @@ size_t SkROBuffer::Iter::size() const {
|
| bool SkROBuffer::Iter::next() {
|
| if (fRemaining) {
|
| fRemaining -= this->size();
|
| - fBlock = fBlock->fNext;
|
| + if (fBuffer->fTail == fBlock) {
|
| + // There are more blocks, but fBuffer does not know about them.
|
| + SkASSERT(0 == fRemaining);
|
| + fBlock = nullptr;
|
| + } else {
|
| + fBlock = fBlock->fNext;
|
| + }
|
| }
|
| return fRemaining != 0;
|
| }
|
| @@ -224,7 +233,9 @@ void SkRWBuffer::validate() const {
|
| }
|
| #endif
|
|
|
| -SkROBuffer* SkRWBuffer::newRBufferSnapshot() const { return new SkROBuffer(fHead, fTotalUsed); }
|
| +SkROBuffer* SkRWBuffer::newRBufferSnapshot() const {
|
| + return new SkROBuffer(fHead, fTotalUsed, fTail);
|
| +}
|
|
|
| ///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|