defaultcircularbuffer.cpp

来自「C++封装的视频采集代码」· C++ 代码 · 共 1,498 行 · 第 1/5 页

CPP
1,498
字号
//TRACE("$GDecoding was successful$n\n");            // Move the read position past the end of the decoded object            readPosition += decodeResult.GetBytesConsumed();            // Ensure the read position finishes on a quad boundary            unsigned remainder = readPosition.GetOffset() & 0x3UL;            if (remainder)            {                readPosition += (4 - remainder);            }            // Record the position within the circular buffer after the            // decoded object            SetAfterPosition(*object, readPosition);            // Determine whether any more objects are available for the reader            do            {                // If the read position is now coincident with the write position                // there must be no more objects available for the reader                if (readPosition == writePosition_)                {                    readPositions_[readerNumber].empty_ = true;                    break;                }                // Check whether there is a jump at the new read position                id = *reinterpret_cast<CircularBufferResidentObject::Id*>(buffer_->GetBuffer() + readPosition.GetOffset());                if (id >= MAX_SPECIAL_IDS)                {                    // No jump, so there must be more objects available for the                    // reader, as the write position is in advance of the read                    // position                    break;                }                // Move past the jump ID                readPosition += sizeof(CircularBufferResidentObject::Id);                // Follow the jump to its target                switch(id)                {                    case MOVE_TO_START_ID:                        // Move read position to the start of the buffer                        // Bear in mind that we may have wrapped if the                        // MOVE_TO_START_ID was the last thing in the                        // buffer.                        if (readPosition.GetOffset() != 0)                        {                            readPosition += readPosition.GetMargin();                        }                        break;                    case JUMP_ZERO_ID:                        // Already positioned after JUMP_ID symbol, so nothing                        // more to do                        break;                    case JUMP_ID:                        {                            // Read the length of the unused section of buffer                            unsigned long jumpLength =                                *reinterpret_cast<CircularBufferResidentObject::Id*>(                                    buffer_->GetBuffer() +                                    readPosition.GetOffset());                            // Jump over the unused section of the buffer                            readPosition += sizeof(unsigned long);                            readPosition += jumpLength;                        }                        break;                    default:                        TRACE("$RUnknown special ID found\n");                        return std::pair<bool, CircularBufferResidentObject*>(true, 0);                }            } while (true);            // Record the pool that the decoded object came from            SetPool(*object, readPool);            // If a read limit is in effect            if (readLimitInfo_[readerNumber].first)            {                // Increment the count of objects read since the limit was set                ++limitCount_[readerNumber];            }            // Increment the count of the number of objects currently acquired            // for read for this reader            ++outstandingReadAcquisitions_[readerNumber];#ifdef INUSE_TRACKING            // Ensure the in-use container is large enough            if ((readerInUse_[readerNumber]->size() + 1) == readerInUse_[readerNumber]->max_size())            {                readerInUse_[readerNumber]->expand(readerInUse_[readerNumber]->max_size() * 2);            }            // Remember the successful acquistion, by storing the prototype            // object pointer            readerInUse_[readerNumber]->push_back(object);#endif//TRACE("$GAR leaving: object=0x%lx, readerNumber = %u$n\n", reinterpret_cast<unsigned long>(object), readerNumber);            return std::pair<bool, CircularBufferResidentObject*>(false, object);        }        // }}}        bool DefaultCircularBuffer::AcquireForWrite(            CircularBufferResidentObject& object,            CircularBufferResidentObject* previousObject,            bool blockIfInsufficientSpace)        // {{{        {            syslib::Lock lock(mutex_);//TRACE("$YAW entered: object=0x%lx, previousObject = 0x%lx$n\n", reinterpret_cast<unsigned long>(&object), reinterpret_cast<unsigned long>(previousObject));            bool status = true;            // If a previous object is provided, use the position after its end            // within the buffer as the position into which to attempt to encode            // the object            CircularBufferPosition writePosition =                previousObject ? GetAfterPosition(*previousObject): writePosition_;//TRACE("$YAW writePosition = [%lu:%lu:%lu]$n\n", writePosition.GetLoopCount(), writePosition.GetOffset(), writePosition.GetMargin());            // Try to associate the object with a range of the circular buffer            CircularBufferSpaceInfo writeSpaceInfo = GetWriteSpaceInfo(writePosition);//TRACE("$YAW writeSpaceInfo = [0x%lx:%lu][0x%lx:%lu]$n\n", writeSpaceInfo.GetFirstAvailableSection().GetStartAddress(), writeSpaceInfo.GetFirstAvailableSection().GetLength(), writeSpaceInfo.GetSecondAvailableSection().GetStartAddress(), writeSpaceInfo.GetSecondAvailableSection().GetLength());            CircularBufferResidentObject::EncodeResult associationResult = object.AssociateWithBuffer(writeSpaceInfo);//TRACE("$YAW associationResult = %d$n\n", (int)associationResult.GetSuccessful());//TRACE("$W[%lu:%lu]->%s$n\n", writeSpaceInfo.GetFirstAvailableSection().GetLength(), writeSpaceInfo.GetSecondAvailableSection().GetLength(), associationResult.GetSuccessful() ? "OK" : "Too small");            while (!associationResult.GetSuccessful())            {                // No, so is blocking to await an object allowed?                if (!blockIfInsufficientSpace || doNotBlock_)                {                    // No                    status = false;                    break;                }                // Should block, so add this thread to the list of waiters for                // the space to become available for writing//TRACE("$YBlocking...$n\n");                ++writeWaitCount_;                lock.Give();                writeSemaphore_.take();                lock.Take();//TRACE("$YAwoken$n\n");                // If attempting to acquire for write after a previously acquired                // object, then are guarenteed that no zeroising of the write                // and read pointers can have occured                if (!previousObject)                {                    // Zeroising of write and read pointers could have occured,                    // so re-obtain the write pointer position                    writePosition = writePosition_;                }                // Re-query for the space available for writing                writeSpaceInfo = GetWriteSpaceInfo(writePosition);                associationResult = object.AssociateWithBuffer(writeSpaceInfo);//TRACE("$YAW Awoken from wait, associationResult=%d$n\n", (int)associationResult.GetSuccessful());            }            if (status)            {                // Association was successful. Did the object decide not to use                // the space remaining upto the end of the buffer?                if (associationResult.GetSkippedFirstSection())                {                    // Write move-to-start ID in case the object is discarded at                    // the commit stage, so that it can be determined whether                    // the associated buffer space included the margin or not                    *reinterpret_cast<CircularBufferResidentObject::Id*>(                        buffer_->GetBuffer() + writePosition.GetOffset()) = MOVE_TO_START_ID;                    writePosition += writePosition.GetMargin();//TRACE("$MAW writePosition = [%lu:%lu:%lu]$n\n", writePosition.GetLoopCount(), writePosition.GetOffset(), writePosition.GetMargin());                }                else                {                    // Write an invalid ID in case the object is discarded at                    // the commit stage, so that it can be determined whether                    // the associated buffer space included the margin or not.                    *reinterpret_cast<CircularBufferResidentObject::Id*>(                        buffer_->GetBuffer() + writePosition.GetOffset()) = MAX_SPECIAL_IDS;                }                // Move the write position past the end of the associated object                writePosition += associationResult.GetBytesConsumed();                // Ensure the write position finishes on a quad boundary                unsigned remainder = writePosition.GetOffset() & 0x3UL;                if (remainder)                {                    writePosition += (4 - remainder);                }//TRACE("$CAW EndwritePosition = [%lu:%lu:%lu]$n\n", writePosition.GetLoopCount(), writePosition.GetOffset(), writePosition.GetMargin());                // Have no interest in the pool from which objects for encode                // originate                SetPool(object, 0);                // Record the position within the circular buffer after the                // associated object                SetAfterPosition(object, writePosition);                // Record the position after the most recently acquired object                mostRecentAcquireAfterPosition_ = writePosition;                // Determine the reader with the oldest position                CircularBufferPosition* oldestReadPosition = &readPositions_[0].position_;                for (unsigned i=1; i < numberOfReaders_; ++i)                {                    if (readPositions_[i].position_ < *oldestReadPosition)                    {                        oldestReadPosition = &readPositions_[i].position_;                    }                }                // If have now used up all space available for writing                if (writePosition.GetOffset() == oldestReadPosition->GetOffset())                {//TRACE("YAW Setting writeEmpty_ true\n");                    writeEmpty_ = true;                }            }            if (status)            {                // Successfully acquired an object for write, so increment the                // count of such objects                ++outstandingWriteAcquisitions_;#ifdef INUSE_TRACKING                // Ensure the in-use container is large enough                if ((writeInUse_.size() + 1) == writeInUse_.max_size())                {                    writeInUse_.expand(writeInUse_.max_size() * 2);                }                // Remember the successful acquistion, by storing the prototype                // object pointer                writeInUse_.push_back(&object);#endif            }//TRACE("$YAW leaving: object=0x%lx, status = %d$n\n", reinterpret_cast<unsigned long>(&object), (int)status);            return status;        }        // }}}        void DefaultCircularBuffer::CommonReleaseFromRead(bool wasBelowWriteThreshold)        // {{{        {            // Determine the space available to the writer after the reader has            // released buffers            bool isBelowWriteThreshold = !IsAboveWriteThreshold();            // If have crossed the available for write threshold, notify            // any listeners            if ( GetWriteThreshold() || (wasBelowWriteThreshold && !isBelowWriteThreshold))            {//TRACE("$WNotifying write threshold listeners$n\n");                Notifier<WriteThresholdEventListener>::NotifyListeners();            }            // Determine whether there is any data available for read, i.e.            // whether the circular buffer is empty            bool anyReadBuffersAvailable = false;            bool outstandingReadAcquisitions = false;            for (unsigned readerNumber=0; readerNumber < numberOfReaders_; ++readerNumber)            {                if (!readPositions_[readerNumber].empty_)                {                    anyReadBuffersAvailable = true;                    break;                }                if (outstandingReadAcquisitions_[readerNumber])                {                    outstandingReadAcquisitions = true;                }            }            // If there is no data in the buffer and there are no buffers            // currently acquired for writing or reading            if (!anyReadBuffersAvailable && !outstandingWriteAcquisitions_ && !outstandingReadAcquisitions)            {//TRACE("$R*******************ZEROISING******************$n\n");                // Reposition the write and all read pointers to the start of                // the buffer, to maximise the space available in a single chunk                writePosition_.Zeroise(buffer_->GetRequestedSize() -1);                for (unsigned i=0; i < numberOfReaders_; i++)                {                    readPositions_[i].position_.Zeroise(buffer_->GetRequestedSize() - 1);                }            }            // Has the buffer just changed from having some data available for

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?