AuroraRuntime/Include/Aurora/IO/IIOPipeProcessor.hpp

141 lines
3.8 KiB
C++

/***
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: IIOPipeProcessor.hpp
Date: 2022-6-6
Author: Reece
***/
#pragma once
namespace Aurora::IO
{
struct IIOPipeInterceptor;
struct IPipeFrames
{
/**
* @brief pipe starting hook
*/
virtual void OnStart() = 0;
/**
* @brief This function is called once the stream reader returns zero
* You should use this opportunity to schedule the next waitable item state (eg, initiate async read, set event high, etc)
* You can return false to soft-fail the pipe to indicate EoS
* You should otherwise return true in order to continue yield until the next waitable item state change
* Note, an EoS event may also occur during the next alert state change should the stream reader return an error
*/
virtual void OnEndPump() = 0;
/**
* @brief pipe shutdown hook
*/
virtual void OnEnd(bool fatal) = 0;
};
struct IOPipeData
{
/**
* @brief IO events
*/
AuSPtr<IIOWaitableItem> watchItem;
/**
* @brief Input source
*/
AuSPtr<IStreamReader> reader;
/**
* @brief Output drain
*/
AuSPtr<IStreamWriter> writer;
/**
* @brief Callbacks
*/
AuSPtr<IPipeFrames> frames;
/**
* @brief Enables aggressive stream consumption, allowing for bias towards clients if they were to send a lot of data (including dos)
* Instead of reading the input stream once, so long as the output stream written paremeter yields a non-zero number, bytes
* will continue to pump through the writer. Breakdown of the pipe is expected on reader oversaturation as defined by the
* IOPipeRequest
*/
bool bShouldReadUntilZero {};
bool bFlush {true};
};
struct IOPipeRequest
{
/**
* @brief Amount of bytes to transfer or zero if stream
*/
AuUInt32 lengthOrZero {};
/**
* @brief internal frame size or zero if fallback
*/
AuUInt32 pageLengthOrZero {};
/**
* @brief event listener
*/
AuSPtr<IIOPipeEventListener> listener;
/**
* @brief Used as the buffer size for streams of page length 0
*/
AuUInt32 fallbackPageSize {4096 * 50};
AuSPtr<IIOPipeInterceptor> processor;
};
struct IOPipeRequestBasic : IOPipeRequest
{
/**
* @brief The two streams to join and an invokable object
*/
IOPipeData data;
};
struct IOPipeRequestAIO : IOPipeRequest
{
AuSPtr<IAsyncTransaction> asyncTransaction;
AuSPtr<IStreamWriter> writer;
bool shouldReadUntilZero {};
};
struct IIOPipeWork
{
/**
* @brief
* @return false should no IIOPipeEventListener event ever be fired. you should generally expect callback based failure.
*/
virtual bool Start() = 0;
virtual bool End() = 0;
};
/**
* @brief Different operating systems implement high level stream copy abstraction between network, file, and/or file descriptors.
* This interface connects arbitrary stream objects to one another by piping data under an iprocessor tick; or delegates
* such task to the operating system, if possible.
*/
struct IIOPipeProcessor
{
/**
* @brief
* @param request
* @return
*/
virtual AuSPtr<IIOPipeWork> NewBasicPipe(const IOPipeRequestBasic &request) = 0;
/**
* @brief
*/
virtual AuSPtr<IIOPipeWork> NewAIOPipe(const IOPipeRequestAIO &request) = 0;
};
}