From 15740faf9fe9fe4be08965098bbf2947e096aeeb Mon Sep 17 00:00:00 2001 From: chai Date: Wed, 14 Aug 2019 22:50:43 +0800 Subject: +Unity Runtime code --- Runtime/Containers/ExtendedRingbuffer.h | 146 ++++++++++++++++++++++++++++++++ 1 file changed, 146 insertions(+) create mode 100644 Runtime/Containers/ExtendedRingbuffer.h (limited to 'Runtime/Containers/ExtendedRingbuffer.h') diff --git a/Runtime/Containers/ExtendedRingbuffer.h b/Runtime/Containers/ExtendedRingbuffer.h new file mode 100644 index 0000000..0eb6d7b --- /dev/null +++ b/Runtime/Containers/ExtendedRingbuffer.h @@ -0,0 +1,146 @@ +#ifndef RUNTIME_CONTAINERS_RINGBUFFERS_H +#define RUNTIME_CONTAINERS_RINGBUFFERS_H + +#include "GrowingRingbuffer.h" +#include "Ringbuffer.h" +#include "TransactionalRingbuffer.h" +#include "Runtime/Threads/Semaphore.h" +#include "Runtime/Utilities/NonCopyable.h" + +#if SUPPORT_THREADS +namespace RingbufferTemplates +{ + // ------------------------------------------------------------------------ + // Support base classes used to avoid casting to 'normal' ringbuffer impl + // ------------------------------------------------------------------------ + template + class NonCastable : protected Ringbuffer + { + public: + using Ringbuffer::WritePtr; + using Ringbuffer::WritePtrUpdate; + using Ringbuffer::ReadPtr; + using Ringbuffer::ReadPtrUpdate; + using Ringbuffer::GetSize; + using Ringbuffer::GetFreeSize; + using Ringbuffer::GetAllocatedSize; + using Ringbuffer::GetAvailableSize; + using Ringbuffer::Reset; + + protected: + NonCastable(MemLabelId label, UInt32 size) : Ringbuffer(label, size) {} + }; + + // ------------------------------------------------------------------------ + // Adds support for notifications whenever data or free space is available + // ------------------------------------------------------------------------ + template + class AbstractNotificationSupport : public NonCastable, public NonCopyable + { + public: + AbstractNotificationSupport(MemLabelId label, UInt32 size) : NonCastable(label, size) {} + + void ReleaseBlockedThreads(bool indefinitely = false) + { + m_FreeSemaphore.Suspend(indefinitely); + m_AvailableSemaphore.Suspend(indefinitely); + } + + void BlockUntilFree() + { + if (Ringbuffer::GetFreeSize()) + return; + + m_FreeSemaphore.Resume(true); + if (Ringbuffer::GetFreeSize() == 0) + m_FreeSemaphore.WaitForSignal(); + m_FreeSemaphore.Suspend(); + } + + void BlockUntilAvailable() + { + if (Ringbuffer::GetAvailableSize()) + return; + + m_AvailableSemaphore.Resume(true); + if (Ringbuffer::GetAvailableSize() == 0) + m_AvailableSemaphore.WaitForSignal(); + m_AvailableSemaphore.Suspend(); + } + + protected: + SuspendableSemaphore m_AvailableSemaphore; + SuspendableSemaphore m_FreeSemaphore; + }; + + template + class RNotificationSupport : public AbstractNotificationSupport + { + public: + RNotificationSupport(MemLabelId label, UInt32 size) : AbstractNotificationSupport(label, size) {} + + void WritePtrUpdate(void* writePtr, UInt32 nBytesWritten) + { + Ringbuffer::WritePtrUpdate(writePtr, nBytesWritten); + AbstractNotificationSupport::m_AvailableSemaphore.Signal(); + } + + void ReadPtrUpdate(const void* readPtr, UInt32 nBytesRead) + { + Ringbuffer::ReadPtrUpdate(readPtr, nBytesRead); + AbstractNotificationSupport::m_FreeSemaphore.Signal(); + } + }; + + + template + class TRNotificationSupport : public AbstractNotificationSupport + { + public: + TRNotificationSupport(MemLabelId label, UInt32 size) : AbstractNotificationSupport(label, size) {} + + using AbstractNotificationSupport::ReadPtrReset; + using AbstractNotificationSupport::WritePtrReset; + + void WritePtrCommit() + { + AbstractNotificationSupport::WritePtrCommit(); + AbstractNotificationSupport::m_AvailableSemaphore.Signal(); + } + + void ReadPtrCommit() + { + AbstractNotificationSupport::ReadPtrCommit(); + AbstractNotificationSupport::m_FreeSemaphore.Signal(); + } + }; + +} + +typedef RingbufferTemplates::RNotificationSupport ExtendedRingbuffer; +typedef RingbufferTemplates::RNotificationSupport ExtendedGrowingRingbuffer; +typedef RingbufferTemplates::TRNotificationSupport ExtendedTransactionalRingbuffer; + +#else // no thread support + +namespace RingbufferTemplates +{ + template + class NotificationSupport : public Ringbuffer, public NonCopyable + { + public: + NotificationSupport(MemLabelId label, UInt32 size) : Ringbuffer(label, size) {} + + void ReleaseBlockedThreads(bool indefinitely = false) {} + void BlockUntilFree() {} + void BlockUntilAvailable() {} + }; +} + +typedef RingbufferTemplates::NotificationSupport ExtendedRingbuffer; +typedef RingbufferTemplates::NotificationSupport ExtendedGrowingRingbuffer; +typedef RingbufferTemplates::NotificationSupport ExtendedTransactionalRingbuffer; + +#endif + +#endif //RUNTIME_CONTAINERS_RINGBUFFERS_H -- cgit v1.1-26-g67d0