LCOV - code coverage report
Current view: top level - gfx/skia/skia/src/core - SkRWBuffer.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 198 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 43 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright 2015 Google Inc.
       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             : 
       8             : #include "SkRWBuffer.h"
       9             : 
      10             : #include "SkAtomics.h"
      11             : #include "SkMalloc.h"
      12             : #include "SkStream.h"
      13             : 
      14             : // Force small chunks to be a page's worth
      15             : static const size_t kMinAllocSize = 4096;
      16             : 
      17             : struct SkBufferBlock {
      18             :     SkBufferBlock*  fNext;      // updated by the writer
      19             :     size_t          fUsed;      // updated by the writer
      20             :     const size_t    fCapacity;
      21             : 
      22           0 :     SkBufferBlock(size_t capacity) : fNext(nullptr), fUsed(0), fCapacity(capacity) {}
      23             : 
      24           0 :     const void* startData() const { return this + 1; }
      25             : 
      26           0 :     size_t avail() const { return fCapacity - fUsed; }
      27           0 :     void* availData() { return (char*)this->startData() + fUsed; }
      28             : 
      29           0 :     static SkBufferBlock* Alloc(size_t length) {
      30           0 :         size_t capacity = LengthToCapacity(length);
      31           0 :         void* buffer = sk_malloc_throw(sizeof(SkBufferBlock) + capacity);
      32           0 :         return new (buffer) SkBufferBlock(capacity);
      33             :     }
      34             : 
      35             :     // Return number of bytes actually appended. Important that we always completely this block
      36             :     // before spilling into the next, since the reader uses fCapacity to know how many it can read.
      37             :     //
      38           0 :     size_t append(const void* src, size_t length) {
      39           0 :         this->validate();
      40           0 :         size_t amount = SkTMin(this->avail(), length);
      41           0 :         memcpy(this->availData(), src, amount);
      42           0 :         fUsed += amount;
      43           0 :         this->validate();
      44           0 :         return amount;
      45             :     }
      46             : 
      47             :     // Do not call in the reader thread, since the writer may be updating fUsed.
      48             :     // (The assertion is still true, but TSAN still may complain about its raciness.)
      49           0 :     void validate() const {
      50             : #ifdef SK_DEBUG
      51           0 :         SkASSERT(fCapacity > 0);
      52           0 :         SkASSERT(fUsed <= fCapacity);
      53             : #endif
      54           0 :     }
      55             : 
      56             : private:
      57           0 :     static size_t LengthToCapacity(size_t length) {
      58           0 :         const size_t minSize = kMinAllocSize - sizeof(SkBufferBlock);
      59           0 :         return SkTMax(length, minSize);
      60             :     }
      61             : };
      62             : 
      63             : struct SkBufferHead {
      64             :     mutable int32_t fRefCnt;
      65             :     SkBufferBlock   fBlock;
      66             : 
      67           0 :     SkBufferHead(size_t capacity) : fRefCnt(1), fBlock(capacity) {}
      68             : 
      69           0 :     static size_t LengthToCapacity(size_t length) {
      70           0 :         const size_t minSize = kMinAllocSize - sizeof(SkBufferHead);
      71           0 :         return SkTMax(length, minSize);
      72             :     }
      73             : 
      74           0 :     static SkBufferHead* Alloc(size_t length) {
      75           0 :         size_t capacity = LengthToCapacity(length);
      76           0 :         size_t size = sizeof(SkBufferHead) + capacity;
      77           0 :         void* buffer = sk_malloc_throw(size);
      78           0 :         return new (buffer) SkBufferHead(capacity);
      79             :     }
      80             : 
      81           0 :     void ref() const {
      82           0 :         SkASSERT(fRefCnt > 0);
      83           0 :         sk_atomic_inc(&fRefCnt);
      84           0 :     }
      85             : 
      86           0 :     void unref() const {
      87           0 :         SkASSERT(fRefCnt > 0);
      88             :         // A release here acts in place of all releases we "should" have been doing in ref().
      89           0 :         if (1 == sk_atomic_fetch_add(&fRefCnt, -1, sk_memory_order_acq_rel)) {
      90             :             // Like unique(), the acquire is only needed on success.
      91           0 :             SkBufferBlock* block = fBlock.fNext;
      92           0 :             sk_free((void*)this);
      93           0 :             while (block) {
      94           0 :                 SkBufferBlock* next = block->fNext;
      95           0 :                 sk_free(block);
      96           0 :                 block = next;
      97             :             }
      98             :         }
      99           0 :     }
     100             : 
     101           0 :     void validate(size_t minUsed, const SkBufferBlock* tail = nullptr) const {
     102             : #ifdef SK_DEBUG
     103           0 :         SkASSERT(fRefCnt > 0);
     104           0 :         size_t totalUsed = 0;
     105           0 :         const SkBufferBlock* block = &fBlock;
     106           0 :         const SkBufferBlock* lastBlock = block;
     107           0 :         while (block) {
     108           0 :             block->validate();
     109           0 :             totalUsed += block->fUsed;
     110           0 :             lastBlock = block;
     111           0 :             block = block->fNext;
     112             :         }
     113           0 :         SkASSERT(minUsed <= totalUsed);
     114           0 :         if (tail) {
     115           0 :             SkASSERT(tail == lastBlock);
     116             :         }
     117             : #endif
     118           0 :     }
     119             : };
     120             : 
     121             : ///////////////////////////////////////////////////////////////////////////////////////////////////
     122             : // The reader can only access block.fCapacity (which never changes), and cannot access
     123             : // block.fUsed, which may be updated by the writer.
     124             : //
     125           0 : SkROBuffer::SkROBuffer(const SkBufferHead* head, size_t available, const SkBufferBlock* tail)
     126           0 :     : fHead(head), fAvailable(available), fTail(tail)
     127             : {
     128           0 :     if (head) {
     129           0 :         fHead->ref();
     130           0 :         SkASSERT(available > 0);
     131           0 :         head->validate(available, tail);
     132             :     } else {
     133           0 :         SkASSERT(0 == available);
     134           0 :         SkASSERT(!tail);
     135             :     }
     136           0 : }
     137             : 
     138           0 : SkROBuffer::~SkROBuffer() {
     139           0 :     if (fHead) {
     140           0 :         fHead->unref();
     141             :     }
     142           0 : }
     143             : 
     144           0 : SkROBuffer::Iter::Iter(const SkROBuffer* buffer) {
     145           0 :     this->reset(buffer);
     146           0 : }
     147             : 
     148           0 : void SkROBuffer::Iter::reset(const SkROBuffer* buffer) {
     149           0 :     fBuffer = buffer;
     150           0 :     if (buffer && buffer->fHead) {
     151           0 :         fBlock = &buffer->fHead->fBlock;
     152           0 :         fRemaining = buffer->fAvailable;
     153             :     } else {
     154           0 :         fBlock = nullptr;
     155           0 :         fRemaining = 0;
     156             :     }
     157           0 : }
     158             : 
     159           0 : const void* SkROBuffer::Iter::data() const {
     160           0 :     return fRemaining ? fBlock->startData() : nullptr;
     161             : }
     162             : 
     163           0 : size_t SkROBuffer::Iter::size() const {
     164           0 :     if (!fBlock) {
     165           0 :         return 0;
     166             :     }
     167           0 :     return SkTMin(fBlock->fCapacity, fRemaining);
     168             : }
     169             : 
     170           0 : bool SkROBuffer::Iter::next() {
     171           0 :     if (fRemaining) {
     172           0 :         fRemaining -= this->size();
     173           0 :         if (fBuffer->fTail == fBlock) {
     174             :             // There are more blocks, but fBuffer does not know about them.
     175           0 :             SkASSERT(0 == fRemaining);
     176           0 :             fBlock = nullptr;
     177             :         } else {
     178           0 :             fBlock = fBlock->fNext;
     179             :         }
     180             :     }
     181           0 :     return fRemaining != 0;
     182             : }
     183             : 
     184             : ///////////////////////////////////////////////////////////////////////////////////////////////////
     185             : 
     186           0 : SkRWBuffer::SkRWBuffer(size_t initialCapacity) : fHead(nullptr), fTail(nullptr), fTotalUsed(0) {
     187           0 :     if (initialCapacity) {
     188           0 :         fHead = SkBufferHead::Alloc(initialCapacity);
     189           0 :         fTail = &fHead->fBlock;
     190             :     }
     191           0 : }
     192             : 
     193           0 : SkRWBuffer::~SkRWBuffer() {
     194           0 :     this->validate();
     195           0 :     if (fHead) {
     196           0 :         fHead->unref();
     197             :     }
     198           0 : }
     199             : 
     200             : // It is important that we always completely fill the current block before spilling over to the
     201             : // next, since our reader will be using fCapacity (min'd against its total available) to know how
     202             : // many bytes to read from a given block.
     203             : //
     204           0 : void SkRWBuffer::append(const void* src, size_t length, size_t reserve) {
     205           0 :     this->validate();
     206           0 :     if (0 == length) {
     207           0 :         return;
     208             :     }
     209             : 
     210           0 :     fTotalUsed += length;
     211             : 
     212           0 :     if (nullptr == fHead) {
     213           0 :         fHead = SkBufferHead::Alloc(length + reserve);
     214           0 :         fTail = &fHead->fBlock;
     215             :     }
     216             : 
     217           0 :     size_t written = fTail->append(src, length);
     218           0 :     SkASSERT(written <= length);
     219           0 :     src = (const char*)src + written;
     220           0 :     length -= written;
     221             : 
     222           0 :     if (length) {
     223           0 :         SkBufferBlock* block = SkBufferBlock::Alloc(length + reserve);
     224           0 :         fTail->fNext = block;
     225           0 :         fTail = block;
     226           0 :         written = fTail->append(src, length);
     227           0 :         SkASSERT(written == length);
     228             :     }
     229           0 :     this->validate();
     230             : }
     231             : 
     232             : #ifdef SK_DEBUG
     233           0 : void SkRWBuffer::validate() const {
     234           0 :     if (fHead) {
     235           0 :         fHead->validate(fTotalUsed, fTail);
     236             :     } else {
     237           0 :         SkASSERT(nullptr == fTail);
     238           0 :         SkASSERT(0 == fTotalUsed);
     239             :     }
     240           0 : }
     241             : #endif
     242             : 
     243           0 : SkROBuffer* SkRWBuffer::newRBufferSnapshot() const {
     244           0 :     return new SkROBuffer(fHead, fTotalUsed, fTail);
     245             : }
     246             : 
     247             : ///////////////////////////////////////////////////////////////////////////////////////////////////
     248             : 
     249             : class SkROBufferStreamAsset : public SkStreamAsset {
     250           0 :     void validate() const {
     251             : #ifdef SK_DEBUG
     252           0 :         SkASSERT(fGlobalOffset <= fBuffer->size());
     253           0 :         SkASSERT(fLocalOffset <= fIter.size());
     254           0 :         SkASSERT(fLocalOffset <= fGlobalOffset);
     255             : #endif
     256           0 :     }
     257             : 
     258             : #ifdef SK_DEBUG
     259             :     class AutoValidate {
     260             :         SkROBufferStreamAsset* fStream;
     261             :     public:
     262           0 :         AutoValidate(SkROBufferStreamAsset* stream) : fStream(stream) { stream->validate(); }
     263           0 :         ~AutoValidate() { fStream->validate(); }
     264             :     };
     265             :     #define AUTO_VALIDATE   AutoValidate av(this);
     266             : #else
     267             :     #define AUTO_VALIDATE
     268             : #endif
     269             : 
     270             : public:
     271           0 :     SkROBufferStreamAsset(const SkROBuffer* buffer) : fBuffer(SkRef(buffer)), fIter(buffer) {
     272           0 :         fGlobalOffset = fLocalOffset = 0;
     273           0 :     }
     274             : 
     275           0 :     ~SkROBufferStreamAsset() override { fBuffer->unref(); }
     276             : 
     277           0 :     size_t getLength() const override { return fBuffer->size(); }
     278             : 
     279           0 :     bool rewind() override {
     280           0 :         AUTO_VALIDATE
     281           0 :         fIter.reset(fBuffer);
     282           0 :         fGlobalOffset = fLocalOffset = 0;
     283           0 :         return true;
     284             :     }
     285             : 
     286           0 :     size_t read(void* dst, size_t request) override {
     287           0 :         AUTO_VALIDATE
     288           0 :         size_t bytesRead = 0;
     289             :         for (;;) {
     290           0 :             size_t size = fIter.size();
     291           0 :             SkASSERT(fLocalOffset <= size);
     292           0 :             size_t avail = SkTMin(size - fLocalOffset, request - bytesRead);
     293           0 :             if (dst) {
     294           0 :                 memcpy(dst, (const char*)fIter.data() + fLocalOffset, avail);
     295           0 :                 dst = (char*)dst + avail;
     296             :             }
     297           0 :             bytesRead += avail;
     298           0 :             fLocalOffset += avail;
     299           0 :             SkASSERT(bytesRead <= request);
     300           0 :             if (bytesRead == request) {
     301           0 :                 break;
     302             :             }
     303             :             // If we get here, we've exhausted the current iter
     304           0 :             SkASSERT(fLocalOffset == size);
     305           0 :             fLocalOffset = 0;
     306           0 :             if (!fIter.next()) {
     307           0 :                 break;   // ran out of data
     308             :             }
     309           0 :         }
     310           0 :         fGlobalOffset += bytesRead;
     311           0 :         SkASSERT(fGlobalOffset <= fBuffer->size());
     312           0 :         return bytesRead;
     313             :     }
     314             : 
     315           0 :     bool isAtEnd() const override {
     316           0 :         return fBuffer->size() == fGlobalOffset;
     317             :     }
     318             : 
     319           0 :     SkStreamAsset* duplicate() const override { return new SkROBufferStreamAsset(fBuffer); }
     320             : 
     321           0 :     size_t getPosition() const override {
     322           0 :         return fGlobalOffset;
     323             :     }
     324             : 
     325           0 :     bool seek(size_t position) override {
     326           0 :         AUTO_VALIDATE
     327           0 :         if (position < fGlobalOffset) {
     328           0 :             this->rewind();
     329             :         }
     330           0 :         (void)this->skip(position - fGlobalOffset);
     331           0 :         return true;
     332             :     }
     333             : 
     334           0 :     bool move(long offset)  override{
     335           0 :         AUTO_VALIDATE
     336           0 :         offset += fGlobalOffset;
     337           0 :         if (offset <= 0) {
     338           0 :             this->rewind();
     339             :         } else {
     340           0 :             (void)this->seek(SkToSizeT(offset));
     341             :         }
     342           0 :         return true;
     343             :     }
     344             : 
     345           0 :     SkStreamAsset* fork() const override {
     346           0 :         SkStreamAsset* clone = this->duplicate();
     347           0 :         clone->seek(this->getPosition());
     348           0 :         return clone;
     349             :     }
     350             : 
     351             : 
     352             : private:
     353             :     const SkROBuffer*   fBuffer;
     354             :     SkROBuffer::Iter    fIter;
     355             :     size_t              fLocalOffset;
     356             :     size_t              fGlobalOffset;
     357             : };
     358             : 
     359           0 : SkStreamAsset* SkRWBuffer::newStreamSnapshot() const {
     360           0 :     sk_sp<SkROBuffer> buffer(this->newRBufferSnapshot());
     361           0 :     return new SkROBufferStreamAsset(buffer.get());
     362             : }

Generated by: LCOV version 1.13