5#include "../Common/CompilerMacrosExport.h"
6#include "../Common/PlatformMacrosInstructionSet.h"
7#ifndef SC_EXPORT_LIBRARY_ASYNC_STREAMS
8#define SC_EXPORT_LIBRARY_ASYNC_STREAMS 0
10#define SC_ASYNC_STREAMS_EXPORT SC_COMPILER_LIBRARY_EXPORT(SC_EXPORT_LIBRARY_ASYNC_STREAMS)
12#include "../Common/AlignedStorage.h"
13#include "../Common/Assert.h"
14#include "../Common/Function.h"
15#include "../Common/IGrowableBufferSpan.h"
16#include "../Common/PlatformMacrosInstructionSet.h"
17#include "../Common/Result.h"
18#include "../Common/Span.h"
19#include "AsyncStreamsError.h"
20#include "Internal/CircularQueue.h"
21#include "Internal/Event.h"
57SC_DECLARE_ASSERT_PROVIDER(AsyncStreamsAssert, SC_ASYNC_STREAMS_EXPORT);
59#define SC_ASYNC_STREAMS_ASSERT_RELEASE(e) SC_ASSERT_PROVIDER_RELEASE(SC::AsyncStreamsAssert, e)
60#define SC_ASYNC_STREAMS_ASSERT_DEBUG(e) SC_ASSERT_PROVIDER_DEBUG(SC::AsyncStreamsAssert, e)
61#define SC_ASYNC_STREAMS_TRUST_RESULT(expression) SC_ASYNC_STREAMS_ASSERT_RELEASE(expression)
66 struct SC_ASYNC_STREAMS_EXPORT
ID
68 using NumericType = int32_t;
70 static constexpr NumericType InvalidValue = -1;
72 NumericType identifier;
74 constexpr ID() : identifier(InvalidValue) {}
75 explicit constexpr ID(int32_t value) : identifier(value) {}
77 [[nodiscard]]
constexpr bool isValid()
const {
return identifier != InvalidValue; }
78 [[nodiscard]]
constexpr bool operator==(
ID other)
const {
return identifier == other.identifier; }
80 enum class Type : uint8_t
89 AsyncBufferView() : writableData(), offset(0), length(0), refs(0), type(Type::Empty), reUse(false) {}
90 AsyncBufferView(Span<char> data) : writableData(data)
92 type = Type::Writable;
94 length = data.sizeInBytes();
97 AsyncBufferView(Span<const char> data) : readonlyData(data)
99 type = Type::ReadOnly;
101 length = data.sizeInBytes();
111 template <
typename T>
114 type = Type::Growable;
121 getGrowableBuffer = [t = forward<T>(t)](GrowableStorage& storage,
bool construct)
mutable -> IGrowableBuffer*
123 using Type =
typename TypeTraits::RemoveReference<T>::type;
126 placementNew(storage.reinterpret_as<GrowableBuffer<Type>>(), t);
127 return &storage.reinterpret_as<GrowableBuffer<Type>>();
131 dtor(storage.reinterpret_as<GrowableBuffer<Type>>());
140 readonlyData = {literal, N - 1};
141 type = Type::ReadOnly;
146 Type getType()
const {
return type; }
149#if SC_PLATFORM_64_BIT
150 static constexpr int TypeErasedCaptureSize =
sizeof(
void*) * 3;
152 static constexpr int TypeErasedCaptureSize =
sizeof(
void*) * 6;
154 static constexpr int TypeErasedGrowableSize =
sizeof(
void*) * 6;
156 using GrowableStorage = AlignedStorage<TypeErasedGrowableSize>;
157 Function<IGrowableBuffer*(GrowableStorage&, bool), TypeErasedCaptureSize> getGrowableBuffer;
161 Span<char> writableData;
162 Span<const char> readonlyData;
164 AsyncBufferView::ID parentID;
166 friend struct AsyncBuffersPool;
171 Type type = Type::Empty;
205 static Result
sliceInEqualParts(Span<AsyncBufferView> buffers, Span<char> memory,
size_t numSlices);
208 void setBuffers(Span<AsyncBufferView> newBuffers) { buffers = newBuffers; }
211 [[nodiscard]]
size_t getNumBuffers()
const {
return buffers.sizeInElements(); }
219 Span<AsyncBufferView> buffers;
238 static constexpr int MaxListeners = 8;
240 Event<MaxListeners, Result> eventError;
264 [[nodiscard]]
bool isEnded()
const {
return state == State::Ended; }
267 [[nodiscard]]
bool hasQueuedData()
const {
return not readQueue.isEmpty(); }
273 [[nodiscard]]
bool canStart()
const {
return state == State::CanRead; }
279 constexpr void setReadQueue(Span<Request> requests) { readQueue = requests; }
327 void maybeDestroyEndedReadable();
331 enum class State : uint8_t
346 State state = State::Stopped;
348 bool destroyed =
false;
349 bool autoDestroy =
true;
353 CircularQueue<Request> readQueue;
377 static constexpr int MaxListeners = 8;
379 Event<MaxListeners, Result> eventError;
391 constexpr void setWriteQueue(Span<Request> requests) { writeQueue = requests; }
435 [[nodiscard]]
bool isStillWriting()
const {
return state == State::Writing or state == State::Ending; }
464 [[nodiscard]]
bool isEndingWritable()
const {
return state == State::Ending; }
466 void stop() { state = State::Stopped; }
469 [[nodiscard]]
bool canAcceptWrite()
const
471 return (state == State::Stopped or state == State::Writing) and not writeQueue.isFull();
474 enum class State : uint8_t
483 State state = State::Stopped;
485 bool destroyed =
false;
486 bool autoDestroy =
true;
488 AsyncBuffersPool* buffers =
nullptr;
490 CircularQueue<Request> writeQueue;
498 Result init(
AsyncBuffersPool& buffersPool, Span<AsyncReadableStream::Request> readableRequests,
499 Span<AsyncWritableStream::Request> writableRequests);
509 void afterProcess(Span<const char> inputAfter, Span<char> outputAfter);
510 void afterFinalize(Span<char> outputAfter,
bool streamEnded);
512 virtual Result onProcess(Span<const char>, Span<char>) = 0;
513 virtual Result onFinalize(Span<char>) = 0;
517 virtual bool canEndWritable()
override;
521 Span<const char> inputData;
522 Span<char> outputData;
539 State state = State::None;
562 static constexpr int MaxListeners = 8;
563 static constexpr int MaxTransforms = 8;
564 static constexpr int MaxSinks = 8;
576 Event<MaxListeners, Result> eventError = {};
599 PendingWrite pendingWrites[MaxTransforms + MaxSinks] = {};
600 bool shouldEndWhenDrained =
false;
601 bool endingPipes =
false;
605 void emitError(Result res);
606 Result checkBuffersPool();
616 bool retryPendingWrites();
617 bool hasPendingWrites()
const;
619 void releasePendingWrites();
Definition AsyncStreams.h:67
A Span of bytes memory to be read or written by async streams.
Definition AsyncStreams.h:65
AsyncBufferView(T &&t)
Saves a copy (or a moved instance) of a String / Buffer (or anything that works with GrowableBuffer<T...
Definition AsyncStreams.h:112
void setReusable(bool reusable)
Tags this AsyncBufferView as reusable after its refCount goes to zero.
Definition AsyncStreams.h:106
Holds a Span of AsyncBufferView (allocated by user) holding available memory for the streams.
Definition AsyncStreams.h:178
Result getReadableData(AsyncBufferView::ID bufferID, Span< const char > &data)
Access data span owned by the buffer.
void setBuffers(Span< AsyncBufferView > newBuffers)
Sets memory for the new buffers.
Definition AsyncStreams.h:208
void refBuffer(AsyncBufferView::ID bufferID)
Increments a buffer reference count.
AsyncBufferView * getBuffer(AsyncBufferView::ID bufferID)
Access the raw AsyncBufferView (if any) at a given bufferID (or nullptr if invalid)
Result createChildView(AsyncBufferView::ID parentBufferID, size_t offset, size_t length, AsyncBufferView::ID &outChildBufferID)
Creates a child view that references a slice of the parent buffer.
void setNewBufferSize(AsyncBufferView::ID bufferID, size_t newSizeInBytes)
Sets the new size in bytes for the buffer.
Result getWritableData(AsyncBufferView::ID bufferID, Span< char > &data)
Access data span owned by the buffer.
static Result sliceInEqualParts(Span< AsyncBufferView > buffers, Span< char > memory, size_t numSlices)
Splits a span of memory in equally sized slices, assigning them to buffers and marking them as reusab...
Result requestNewBuffer(size_t minimumSizeInBytes, AsyncBufferView::ID &bufferID, Span< char > &data)
Requests a new available buffer that is at least minimumSizeInBytes, incrementing its refcount.
Result pushBuffer(AsyncBufferView &&buffer, AsyncBufferView::ID &bufferID)
Adds a buffer to the pool in any empty slot (found by scanning from start to end)
void unrefBuffer(AsyncBufferView::ID bufferID)
Decrements a buffer reference count.
size_t getNumBuffers() const
Gets size of buffers held by the pool.
Definition AsyncStreams.h:211
A stream that can both produce and consume buffers.
Definition AsyncStreams.h:495
virtual Result asyncRead() override
Function that every stream must define to implement its custom read operation.
Definition AsyncStreams.h:594
Pipes read data from SC::AsyncReadableStream, forwarding them to SC::AsyncWritableStream.
Definition AsyncStreams.h:561
Result pipe()
Reports errors by source, transforms or sinks.
bool unpipe()
Unregisters all events from source, transforms and sinks.
Result start()
Starts the pipeline.
Definition AsyncStreams.h:234
Async source abstraction emitting data events in caller provided byte buffers.
Definition AsyncStreams.h:229
bool getAutoDestroy() const
Returns true if stream will automatically call .destroy() when Ended state is reached.
Definition AsyncStreams.h:308
void pushEnd()
Use pushEnd from inside AsyncReadableStream::asyncRead to signal production end.
void emitError(Result error)
Signals an async error received.
void resumeReading()
Resumes the readable stream paused by AsyncReadableStream::pause.
bool push(AsyncBufferView::ID bufferID, size_t newSize)
Use push from inside AsyncReadableStream::asyncRead function to queue received data.
Event< MaxListeners > eventEnd
Emitted when a new buffer has been read.
Definition AsyncStreams.h:242
bool hasBeenDestroyed() const
Returns true if the stream has been already destroyed (asynchronously through destroy())
Definition AsyncStreams.h:270
Result finishedDestroyingReadable()
Called from inside asyncDestroy to transition from Destroying to Destroyed state (emitting eventClose...
virtual Result asyncResumeReading()
Function that streams may define to resume an already pending async read.
bool hasQueuedData() const
Returns true if there are buffered reads waiting to be emitted.
Definition AsyncStreams.h:267
Event< MaxListeners > eventClose
Emitted when there is no more data.
Definition AsyncStreams.h:243
Event< MaxListeners, AsyncBufferView::ID > eventData
Emitted when an error occurs.
Definition AsyncStreams.h:241
AsyncBuffersPool & getBuffersPool()
Obtains the AsyncBuffersPool to request more buffers.
size_t getReadQueueSize() const
Returns the size of read queue.
Definition AsyncStreams.h:282
void setAutoDestroy(bool value)
If set to true will automatically call .destroy() when Ended state is reached.
Definition AsyncStreams.h:305
virtual Result asyncDestroyReadable()
Function that a readable stream can re-implement to release its internal resources.
void destroy()
Forcefully destroys the readable stream before calling end event releasing all resources.
virtual Result asyncRead()=0
Function that every stream must define to implement its custom read operation.
bool getBufferOrPause(size_t minumumSizeInBytes, AsyncBufferView::ID &bufferID, Span< char > &data)
Returns an unused buffer from pool or pauses the stream if none is available.
bool isEnded() const
Returns true if the stream is ended (AsyncReadableStream::end has been called)
Definition AsyncStreams.h:264
constexpr void setReadQueue(Span< Request > requests)
Sets the read queue for this readable stream.
Definition AsyncStreams.h:279
Result init(AsyncBuffersPool &buffersPool)
Emitted when the underlying resource has been closed.
void reactivate(bool doReactivate)
Use reactivate(true) from inside AsyncReadableStream::asyncRead function to ask the state machine to ...
void pause()
Pauses the readable stream (that can be later resumed)
bool canStart() const
Returns true when start() is currently valid for this stream.
Definition AsyncStreams.h:273
Result unshift(AsyncBufferView::ID bufferID)
Push back a buffer to the front of the read queue (e.g. for un-consumed data)
Result start()
Starts the readable stream, that will emit eventData.
Traits exposing AsyncStreams public types through a single template parameter.
Definition AsyncStreams.h:545
Definition AsyncStreams.h:372
Async destination abstraction where bytes can be written to.
Definition AsyncStreams.h:365
size_t getWriteQueueSize() const
Returns the size of write queue.
Definition AsyncStreams.h:394
Event< MaxListeners > eventFinish
Emitted when write queue is empty.
Definition AsyncStreams.h:382
Result write(AsyncBufferView::ID bufferID, Function< void(AsyncBufferView::ID)> cb={})
Writes a buffer (that must be allocated by the AsyncBuffersPool passed in AsyncWritableStream) When t...
void end()
Ends the writable stream, waiting for all in-flight and queued writes to finish.
void destroy()
Forcefully destroys the writable stream before calling end event releasing all resources.
void emitError(Result error)
Signals an async error received.
void finishedDestroyingWritable()
Function that MUST be called by re-implementations of asyncDestroyWritable once they're done.
Event< MaxListeners > eventDrain
Emitted when an error occurs.
Definition AsyncStreams.h:381
virtual bool canEndWritable()
Allows keeping a writable in ENDING state until it has finished flushing all pending data.
virtual Result asyncWrite(AsyncBufferView::ID, Function< void(AsyncBufferView::ID)> func)=0
Function that every stream must define to implement its custom write operation.
bool isStillWriting() const
Returns true if this stream is writing something.
Definition AsyncStreams.h:435
void resumeWriting()
Resumes writing queued requests for this stream.
virtual Result asyncDestroyWritable()
Function that a writable stream can re-implement to release its internal resources.
void setAutoDestroy(bool value)
If set to true will automatically call .destroy() when Ended state is reached.
Definition AsyncStreams.h:441
bool hasBeenDestroyed() const
Returns true if the stream has been already destroyed (asynchronously through destroy())
Definition AsyncStreams.h:438
Result init(AsyncBuffersPool &buffersPool)
Emitted when the underlying resource has been closed.
void finishedWriting(AsyncBufferView::ID bufferID, Function< void(AsyncBufferView::ID)> &&cb, Result res)
Signals that the given buffer (previously queued by write) has been fully written.
bool getAutoDestroy() const
Returns true if stream will automatically call .destroy() when Ended state is reached.
Definition AsyncStreams.h:444
void tryAsync(Result potentialError)
Will emit error if the passed in Result is false.
Result unshift(AsyncBufferView::ID bufferID, Function< void(AsyncBufferView::ID)> &&cb)
Puts back a buffer at the top of the write queue.
Result write(AsyncBufferView &&bufferView, Function< void(AsyncBufferView::ID)> cb={})
Push a new buffer view to the queue, registering it with the allocator.
AsyncBuffersPool & getBuffersPool()
Obtains the buffers pool to access its data.
Event< MaxListeners > eventClose
Emitted when no more data can be written.
Definition AsyncStreams.h:383
constexpr void setWriteQueue(Span< Request > requests)
Sets the write queue for this writable stream.
Definition AsyncStreams.h:391