AuroraRuntime/Include/Aurora/IO/IAsyncTransaction.hpp
2024-02-25 23:30:56 +00:00

155 lines
5.1 KiB
C++

/***
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: IAsyncTransaction.hpp
Date: 2022-2-14
Author: Reece
***/
#pragma once
namespace Aurora::IO::Loop
{
struct ILoopSource;
}
namespace Aurora::IO::CompletionGroup
{
struct ICompletionGroup;
}
#include "CompletionGroup/ICompletionGroupWorkHandle.hpp"
#include <Aurora/Debug/Debug.hpp>
namespace Aurora::IO
{
/**
* @brief Cross-platform reusable overlapped-based IO transaction
*
* @warning this object is bound by the current thread at time of creation.
* Do not access this object across threads as there is no MT guarantee on this particular object
* Using the synchronization primitives, loop or authreading, is fine.
*/
struct IAsyncTransaction
{
virtual bool StartRead(AuUInt64 uOffset, const AuSPtr<Memory::MemoryViewWrite> &memoryView) = 0;
virtual bool StartWrite(AuUInt64 uOffset, const AuSPtr<Memory::MemoryViewRead> &memoryView) = 0;
/**
* @brief "Non-blocking" is-signaled and call callback poll routine (similar to nt alertable sleeps of a period zero)
*/
virtual bool Complete() = 0;
/**
* @brief Non-blocking has-failed (no callbacks, no alert sleep)
* @return
*/
virtual bool HasFailed() = 0;
/**
* @brief Non-blocking is-signaled (...and dispatched via ::Complete() or other IO yield) (no callbacks, no alert sleep)
* @return
*/
virtual bool HasCompleted() = 0;
/**
* @brief
* @return
*/
virtual AuUInt GetOSErrorCode() = 0;
/**
* @brief Returns the last packets length assuming ::Complete() is true or you are within the registered callback
*/
virtual AuUInt32 GetLastPacketLength() = 0;
/**
* @brief Registers an NT-like APC callback for the IO transaction.
* Can be executed under any Aurora loop subsystem sleep
*/
virtual void SetCallback(const AuSPtr<IAsyncFinishedSubscriber> &pSubscriber) = 0;
/**
* @brief Block for completion
*/
virtual bool Wait(AuUInt32 uTimeout) = 0;
/**
* @brief Provides a loop source that becomes signaled once the transaction is complete.
* Polling the transaction may result in the execution of the callback.
*/
virtual AuSPtr<IO::Loop::ILoopSource> NewLoopSource() = 0;
/**
* @brief Resets ::Complete() and NewLoopSource()->IsSignaled() to false
*/
virtual void Reset() = 0;
virtual void SetBaseOffset(AuUInt64 uBaseOffset) = 0;
virtual bool TryAttachToCompletionGroup(const AuSPtr<CompletionGroup::ICompletionGroup> &pCompletionGroup) = 0;
virtual CompletionGroup::ICompletionGroupWorkHandle *ToCompletionGroupHandle() = 0;
virtual AuSPtr<CompletionGroup::ICompletionGroup> GetCompletionGroup() = 0;
AURT_ADD_USR_DATA_EXP(this->ToCompletionGroupHandle());
};
inline bool ReadAsync(const AuSPtr<IAsyncTransaction> &pTransaction,
AuUInt64 uOffset,
const AuSPtr<Memory::MemoryViewWrite> &memoryView,
AuOptional<AuConsumer<AuUInt /*offset*/, AuUInt64 /*length*/>> callback = {},
AuOptional<AuSPtr<CompletionGroup::ICompletionGroup>> pCompletionGroup = {})
{
SysCheckArgNotNull(pTransaction, false);
if (pCompletionGroup)
{
(void)pTransaction->TryAttachToCompletionGroup(pCompletionGroup.Value());
}
if (callback)
{
auto pRet = AuMakeShared<IAsyncFinishedSubscriberFunctional>();
if (!pRet)
{
SysPushErrorMemory();
return false;
}
pRet->OnAsyncFileOpFinishedFunctional = callback.Value();
pTransaction->SetCallback(pRet);
}
return pTransaction->StartRead(uOffset, memoryView);
}
inline bool WriteAsync(const AuSPtr<IAsyncTransaction> &pTransaction,
AuUInt64 uOffset,
const AuSPtr<Memory::MemoryViewRead> &memoryView,
AuOptional<AuConsumer<AuUInt /*offset*/, AuUInt64 /*length*/>> callback = {},
AuOptional<AuSPtr<CompletionGroup::ICompletionGroup>> pCompletionGroup = {})
{
SysCheckArgNotNull(pTransaction, false);
if (pCompletionGroup)
{
(void)pTransaction->TryAttachToCompletionGroup(pCompletionGroup.Value());
}
if (callback)
{
auto pRet = AuMakeShared<IAsyncFinishedSubscriberFunctional>();
if (!pRet)
{
SysPushErrorMemory();
return false;
}
pRet->OnAsyncFileOpFinishedFunctional = callback.Value();
pTransaction->SetCallback(pRet);
}
return pTransaction->StartWrite(uOffset, memoryView);
}
}