[+] Aurora::IO::FS::IMemoryMappedFile

[+] Aurora::IO::Adapters::NewMemoryViewWriteSeekableAdapter
[*] ViewSeekableReadable -> ViewSeekableReader
[+] Aurora::IO::FS::OpenMap
[+] Aurora::IO::FS::OpenMapFromSharedHandle
This commit is contained in:
Reece Wilson 2024-03-07 06:49:23 +00:00
parent 6d4fc2c5f7
commit 38bf52e852
28 changed files with 1062 additions and 315 deletions

View File

@ -9,8 +9,8 @@
namespace Aurora::IO::Adapters
{
AUKN_SYM AuSPtr<IAsyncTransaction> NewAsyncTransactionFromStreamReader(const AuSPtr<IStreamReader> &pStreamReader, AuOptional<Aurora::Async::WorkerPId_t> workers);
AUKN_SYM AuSPtr<IAsyncTransaction> NewAsyncTransactionFromStreamSeekingReader(const AuSPtr<ISeekingReader> &pStreamReader, AuOptional<Aurora::Async::WorkerPId_t> workers);
AUKN_SYM AuSPtr<IAsyncTransaction> NewAsyncTransactionFromStreamWriter(const AuSPtr<IStreamWriter> &pStreamWriter, AuOptional<Aurora::Async::WorkerPId_t> workers);
AUKN_SYM AuSPtr<IAsyncTransaction> NewAsyncTransactionFromStreamSeekingWriter(const AuSPtr<ISeekingWriter> &pStreamWriter, AuOptional<Aurora::Async::WorkerPId_t> workers);
AUKN_SYM AuSPtr<IAsyncTransaction> NewAsyncTransactionFromStreamReader(const AuSPtr<IStreamReader> &pStreamReader, AuOptional<Aurora::Async::WorkerPId_t> workers);
AUKN_SYM AuSPtr<IAsyncTransaction> NewAsyncTransactionFromStreamSeekingReader(const AuSPtr<ISeekingReader> &pStreamReader, AuOptional<Aurora::Async::WorkerPId_t> workers);
AUKN_SYM AuSPtr<IAsyncTransaction> NewAsyncTransactionFromStreamWriter(const AuSPtr<IStreamWriter> &pStreamWriter, AuOptional<Aurora::Async::WorkerPId_t> workers);
AUKN_SYM AuSPtr<IAsyncTransaction> NewAsyncTransactionFromStreamSeekingWriter(const AuSPtr<ISeekingWriter> &pStreamWriter, AuOptional<Aurora::Async::WorkerPId_t> workers);
}

View File

@ -10,6 +10,7 @@
namespace Aurora::IO::Adapters
{
AUKN_SYM AuSPtr<IStreamReader> NewByteBufferReadAdapter(const AuSPtr<Memory::ByteBuffer> &pBuffer);
AUKN_SYM AuSPtr<ISeekingReader> NewByteBufferLinearSeekableAdapter(const AuSPtr<Memory::ByteBuffer> &pBuffer);
AUKN_SYM AuSPtr<ISeekingReader> NewByteBufferLinearReadSeekableAdapter(const AuSPtr<Memory::ByteBuffer> &pBuffer);
AUKN_SYM AuSPtr<ISeekingWriter> NewByteBufferLinearWriteSeekableAdapter(const AuSPtr<Memory::ByteBuffer> &pBuffer);
AUKN_SYM AuSPtr<IStreamWriter> NewByteBufferWriteAdapter(const AuSPtr<Memory::ByteBuffer> &pBuffer);
}

View File

@ -10,6 +10,7 @@
namespace Aurora::IO::Adapters
{
AUKN_SYM AuSPtr<IStreamReader> NewMemoryViewReadAdapter(const AuSPtr<Memory::MemoryViewRead> &pView);
AUKN_SYM AuSPtr<ISeekingReader> NewMemoryViewLinearSeekableAdapter(const AuSPtr<Memory::MemoryViewRead> &pView);
AUKN_SYM AuSPtr<ISeekingReader> NewMemoryViewReadSeekingAdapter(const AuSPtr<Memory::MemoryViewRead> &pView);
AUKN_SYM AuSPtr<IStreamWriter> NewMemoryViewWriteAdapter(const AuSPtr<Memory::MemoryViewWrite> &pView);
AUKN_SYM AuSPtr<ISeekingWriter> NewMemoryViewWriteSeekableAdapter(const AuSPtr<Memory::MemoryViewWrite> &pView);
}

View File

@ -11,18 +11,16 @@ namespace Aurora::IO::Buffered
{
struct BlobReader : IStreamReader
{
AU_NO_COPY(BlobReader)
AU_COPY_MOVE(BlobReader)
inline BlobReader(const AuSPtr<Memory::ByteBuffer> &buffer) : buffer_(buffer) {}
inline BlobReader(Memory::ByteBuffer &&buffer) : buffer_(AuMakeShared<Memory::ByteBuffer>(buffer)) {}
inline BlobReader(const Memory::ByteBuffer &buffer) : buffer_(AuMakeShared<Memory::ByteBuffer>(buffer)) {}
inline BlobReader() {}
inline ~BlobReader() {}
inline BlobReader(const AuSPtr<Memory::ByteBuffer> &buffer) : pBuffer_(buffer) {}
inline BlobReader(Memory::ByteBuffer &&buffer) : pBuffer_(AuMakeShared<Memory::ByteBuffer>(buffer)) {}
inline BlobReader(const Memory::ByteBuffer &buffer) : pBuffer_(AuMakeShared<Memory::ByteBuffer>(buffer)) {}
inline BlobReader() : pBuffer_(AuMakeShared<Memory::ByteBuffer>()) {}
inline virtual EStreamError IsOpen() override
{
auto pBuffer = this->buffer_;
auto pBuffer = this->pBuffer_;
if (!pBuffer)
{
return EStreamError::eErrorStreamNotOpen;
@ -38,7 +36,7 @@ namespace Aurora::IO::Buffered
inline virtual EStreamError Read(const Memory::MemoryViewStreamWrite &parameters) override
{
auto pBuffer = this->buffer_;
auto pBuffer = this->pBuffer_;
if (!pBuffer)
{
return EStreamError::eErrorStreamNotOpen;
@ -55,10 +53,10 @@ namespace Aurora::IO::Buffered
inline virtual void Close() override
{
AuResetMember(this->buffer_);
AuResetMember(this->pBuffer_);
}
protected:
AuSPtr<Memory::ByteBuffer> buffer_;
AuSPtr<Memory::ByteBuffer> pBuffer_;
};
}

View File

@ -11,18 +11,15 @@ namespace Aurora::IO::Buffered
{
struct BlobSeekableReader : ISeekingReader
{
AU_NO_COPY_NO_MOVE(BlobSeekableReader)
AU_COPY_MOVE_DEF(BlobSeekableReader)
inline BlobSeekableReader(const AuSPtr<Memory::ByteBuffer> &buffer) : buffer_(buffer) {}
inline BlobSeekableReader(Memory::ByteBuffer &&buffer) : buffer_(AuMakeShared<Memory::ByteBuffer>(AuMove(buffer))) {}
inline BlobSeekableReader(const Memory::ByteBuffer &buffer) : buffer_(AuMakeShared<Memory::ByteBuffer>(buffer)) {}
inline BlobSeekableReader() {}
inline ~BlobSeekableReader(){}
inline BlobSeekableReader(const AuSPtr<Memory::ByteBuffer> &buffer) : pBuffer_(buffer) {}
inline BlobSeekableReader(Memory::ByteBuffer &&buffer) : pBuffer_(AuMakeShared<Memory::ByteBuffer>(AuMove(buffer))) {}
inline BlobSeekableReader(const Memory::ByteBuffer &buffer) : pBuffer_(AuMakeShared<Memory::ByteBuffer>(buffer)) {}
inline virtual EStreamError IsOpen() override
{
if (!this->buffer_)
if (!this->pBuffer_)
{
return EStreamError::eErrorStreamNotOpen;
}
@ -32,27 +29,27 @@ namespace Aurora::IO::Buffered
inline virtual EStreamError ArbitraryRead(AuUInt offset, const Memory::MemoryViewStreamWrite &parameters) override
{
if (!this->buffer_)
if (!this->pBuffer_)
{
return EStreamError::eErrorStreamNotOpen;
}
if (this->buffer_->empty())
if (this->pBuffer_->empty())
{
return EStreamError::eErrorEndOfStream;
}
this->buffer_->readPtr = this->buffer_->base + offset;
parameters.outVariable = this->buffer_->Read(parameters.ptr, parameters.length);
this->pBuffer_->readPtr = this->pBuffer_->base + offset;
parameters.outVariable = this->pBuffer_->Read(parameters.ptr, parameters.length);
return parameters.outVariable == 0 ? EStreamError::eErrorEndOfStream : EStreamError::eErrorNone;
}
inline virtual void Close() override
{
AuResetMember(this->buffer_);
AuResetMember(this->pBuffer_);
}
private:
AuSPtr<Memory::ByteBuffer> buffer_;
AuSPtr<Memory::ByteBuffer> pBuffer_;
};
}

View File

@ -0,0 +1,59 @@
/***
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: BlobSeekableWriter.hpp
Date: 2024-03-05
Author: Reece
***/
#pragma once
namespace Aurora::IO::Buffered
{
struct BlobSeekableWriter : ISeekingWriter
{
AU_COPY_MOVE_DEF(BlobSeekableWriter)
inline BlobSeekableWriter(const AuSPtr<Memory::ByteBuffer> &buffer) : pBuffer_(buffer) {}
inline BlobSeekableWriter(Memory::ByteBuffer &&buffer) : pBuffer_(AuMakeShared<Memory::ByteBuffer>(AuMove(buffer))) {}
inline BlobSeekableWriter(const Memory::ByteBuffer &buffer) : pBuffer_(AuMakeShared<Memory::ByteBuffer>(buffer)) {}
inline virtual EStreamError IsOpen() override
{
if (!this->pBuffer_)
{
return EStreamError::eErrorStreamNotOpen;
}
return EStreamError::eErrorNone;
}
inline virtual EStreamError ArbitraryWrite(AuUInt offset, const Memory::MemoryViewStreamRead &parameters) override
{
if (!this->pBuffer_)
{
return EStreamError::eErrorStreamNotOpen;
}
if (this->pBuffer_->empty())
{
return EStreamError::eErrorEndOfStream;
}
this->pBuffer_->writePtr = this->pBuffer_->base + offset;
parameters.outVariable = this->pBuffer_->Write(parameters.ptr, parameters.length);
return parameters.outVariable == 0 ? EStreamError::eErrorEndOfStream : EStreamError::eErrorNone;
}
inline virtual void Flush() override
{
}
inline virtual void Close() override
{
AuResetMember(this->pBuffer_);
}
private:
AuSPtr<Memory::ByteBuffer> pBuffer_;
};
}

View File

@ -11,15 +11,15 @@ namespace Aurora::IO::Buffered
{
struct BlobWriter : IStreamWriter
{
AU_NO_COPY_NO_MOVE(BlobWriter)
AU_COPY_MOVE(BlobWriter)
inline BlobWriter(const AuSPtr<Memory::ByteBuffer> &buffer) : buffer_(buffer) {}
inline BlobWriter() : buffer_(AuMakeShared<Memory::ByteBuffer>()) {}
inline BlobWriter(const AuSPtr<Memory::ByteBuffer> &buffer) : pBuffer_(buffer) {}
inline BlobWriter() : pBuffer_(AuMakeShared<Memory::ByteBuffer>()) {}
inline ~BlobWriter() {}
inline virtual EStreamError IsOpen() override
{
auto pBuffer = this->buffer_;
auto pBuffer = this->pBuffer_;
if (!pBuffer)
{
return EStreamError::eErrorStreamNotOpen;
@ -35,7 +35,7 @@ namespace Aurora::IO::Buffered
inline virtual EStreamError Write(const Memory::MemoryViewStreamRead &parameters) override
{
auto pBuffer = this->buffer_;
auto pBuffer = this->pBuffer_;
if (!pBuffer)
{
return EStreamError::eErrorStreamNotOpen;
@ -56,15 +56,15 @@ namespace Aurora::IO::Buffered
inline virtual void Close() override
{
AuResetMember(this->buffer_);
AuResetMember(this->pBuffer_);
}
inline AuSPtr<Memory::ByteBuffer> GetBuffer()
{
return this->buffer_;
return this->pBuffer_;
}
private:
AuSPtr<Memory::ByteBuffer> buffer_;
AuSPtr<Memory::ByteBuffer> pBuffer_;
};
}

View File

@ -7,12 +7,12 @@
***/
#pragma once
// Most internal transactions will be buffered.
// For sake of being able to mix network, file, serial, and other code, its nice to use the same reader interface for buffered and streams where read/write until EOS is required
#include "BlobSeekableReader.hpp"
#include "BlobReader.hpp"
#include "BlobSeekableReader.hpp"
#include "BlobWriter.hpp"
#include "BlobSeekableWriter.hpp"
#include "ViewReader.hpp"
#include "ViewSeekableReadable.hpp"
#include "ViewSeekableReader.hpp"
#include "ViewWriter.hpp"
#include "ViewSeekableWriter.hpp"

View File

@ -12,8 +12,12 @@ namespace Aurora::IO::Buffered
struct ViewReader : IStreamReader
{
AU_NO_COPY(ViewReader)
AU_MOVE(ViewReader)
inline ViewReader(const AuSPtr<Memory::MemoryViewRead> &view) : pView_(view)
inline ViewReader(const AuSPtr<Memory::MemoryViewRead> &pView) : view_(pView ? *pView.get() : Memory::MemoryViewRead {}), pHold(pView)
{ }
inline ViewReader(const Memory::MemoryViewRead &view, AuSPtr<void> pBlock) : view_(view), pHold(pBlock)
{ }
inline ViewReader()
@ -24,12 +28,12 @@ namespace Aurora::IO::Buffered
inline virtual EStreamError IsOpen() override
{
if (!this->pView_)
if (!this->view_)
{
return EStreamError::eErrorStreamNotOpen;
}
if (!(*this->pView_.get()))
if (!this->pHold)
{
return EStreamError::eErrorStreamNotOpen;
}
@ -41,27 +45,28 @@ namespace Aurora::IO::Buffered
{
parameters.outVariable = 0;
if (!this->pView_)
if (!this->view_)
{
return EStreamError::eErrorStreamNotOpen;
}
if (!(*this->pView_.get()))
if (!this->pHold)
{
this->pView_.reset();
this->Close();
return this->uOffset_ ? EStreamError::eErrorStreamNotOpen : EStreamError::eErrorNone;
}
auto uToRead = AuMin(this->pView_->length - this->uOffset_, parameters.length);
auto uToRead = AuMin(this->view_.length - this->uOffset_, parameters.length);
parameters.outVariable = uToRead;
AuMemcpy(parameters.ptr, this->pView_->Begin<AuUInt8>() + this->uOffset_, uToRead);
AuMemcpy(parameters.ptr, this->view_.Begin<AuUInt8>() + this->uOffset_, uToRead);
this->uOffset_ += uToRead;
return parameters.outVariable == 0 ? EStreamError::eErrorEndOfStream : EStreamError::eErrorNone;
}
inline virtual void Close() override
{
this->pView_.reset();
AuResetMember(this->pHold);
AuResetMember(this->view_);
}
inline AuUInt &GetOffset()
@ -74,7 +79,8 @@ namespace Aurora::IO::Buffered
return this->uOffset_;
}
private:
AuSPtr<Memory::MemoryViewRead> pView_;
Memory::MemoryViewRead view_;
AuSPtr<void> pHold;
AuUInt uOffset_ {};
};
}

View File

@ -1,71 +0,0 @@
/***
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: ViewSeekableReadable.hpp
Date: 2022-12-11
Author: Reece
***/
#pragma once
namespace Aurora::IO::Buffered
{
struct ViewSeekableReadable : ISeekingReader
{
AU_NO_COPY(ViewSeekableReadable)
inline ViewSeekableReadable(const AuSPtr<Memory::MemoryViewRead> &view) : view_(view)
{ }
inline ViewSeekableReadable()
{ }
inline ~ViewSeekableReadable()
{ }
inline virtual EStreamError IsOpen() override
{
if (!this->view_)
{
return EStreamError::eErrorStreamNotOpen;
}
if (!(*this->view_.get()))
{
return EStreamError::eErrorStreamNotOpen;
}
return EStreamError::eErrorNone;
}
inline virtual EStreamError ArbitraryRead(AuUInt uOffset, const Memory::MemoryViewStreamWrite &parameters) override
{
if (!this->view_)
{
return EStreamError::eErrorStreamNotOpen;
}
if (!(*this->view_.get()))
{
return EStreamError::eErrorStreamNotOpen;
}
if (this->view_->length < uOffset)
{
return EStreamError::eErrorEndOfStream;
}
auto uToRead = AuMin(this->view_->length - uOffset, parameters.length);
parameters.outVariable = uToRead;
AuMemcpy(parameters.ptr, this->view_->Begin<AuUInt8>() + uOffset, uToRead);
return parameters.outVariable == 0 ? EStreamError::eErrorEndOfStream : EStreamError::eErrorNone;
}
inline virtual void Close() override
{
this->view_.reset();
}
private:
AuSPtr<Memory::MemoryViewRead> view_;
};
}

View File

@ -0,0 +1,98 @@
/***
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: ViewSeekableReader.hpp
Date: 2022-12-11
Author: Reece
***/
#pragma once
namespace Aurora::IO::Buffered
{
struct ViewSeekableReader : ISeekingReader
{
AU_NO_COPY(ViewSeekableReader)
AU_MOVE(ViewSeekableReader)
inline ViewSeekableReader(const AuSPtr<Memory::MemoryViewRead> &pView) : view_(pView ? *pView.get() : Memory::MemoryViewRead {}), pHold(pView)
{ }
inline ViewSeekableReader(const Memory::MemoryViewRead &view, AuSPtr<void> pBlock) : view_(view), pHold(pBlock)
{ }
inline ViewSeekableReader()
{ }
inline ~ViewSeekableReader()
{ }
inline virtual EStreamError IsOpen() override
{
if (!this->view_)
{
return EStreamError::eErrorStreamNotOpen;
}
if (!this->pHold)
{
return EStreamError::eErrorStreamNotOpen;
}
return EStreamError::eErrorNone;
}
inline virtual EStreamError ArbitraryRead(AuUInt uOffset, const Memory::MemoryViewStreamWrite &parameters) override
{
if (!this->view_)
{
return EStreamError::eErrorStreamNotOpen;
}
if (!this->pHold)
{
return EStreamError::eErrorStreamNotOpen;
}
auto iOffset = this->iBaseOffset + AuInt64(uOffset);
if (iOffset < 0)
{
return EStreamError::eErrorOutOfBounds;
}
else
{
uOffset = iOffset;
}
if (this->view_.length < uOffset)
{
return EStreamError::eErrorEndOfStream;
}
auto uToRead = AuMin(this->view_.length - uOffset, parameters.length);
parameters.outVariable = uToRead;
AuMemcpy(parameters.ptr, this->view_.Begin<AuUInt8>() + uOffset, uToRead);
return parameters.outVariable == 0 ? EStreamError::eErrorEndOfStream : EStreamError::eErrorNone;
}
inline virtual void Close() override
{
AuResetMember(this->pHold);
AuResetMember(this->view_);
}
inline AuInt64 &GetBaseOffset()
{
return this->iBaseOffset;
}
inline const AuInt64 &GetBaseOffset() const
{
return this->iBaseOffset;
}
private:
Memory::MemoryViewRead view_;
AuSPtr<void> pHold;
AuInt64 iBaseOffset {};
};
}

View File

@ -0,0 +1,102 @@
/***
Copyright (C) 2022-2024 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: ViewSeekableWriter.hpp
Date: 2024-03-05
Author: Reece
***/
#pragma once
namespace Aurora::IO::Buffered
{
struct ViewSeekableWriter : ISeekingWriter
{
AU_NO_COPY(ViewSeekableWriter)
AU_MOVE(ViewSeekableWriter)
inline ViewSeekableWriter(const AuSPtr<Memory::MemoryViewWrite> &pView) : view_(pView ? *pView.get() : Memory::MemoryViewWrite {}), pHold(pView)
{ }
inline ViewSeekableWriter(const Memory::MemoryViewWrite &view, AuSPtr<void> pBlock) : view_(view), pHold(pBlock)
{ }
inline ViewSeekableWriter()
{ }
inline ~ViewSeekableWriter()
{ }
inline virtual EStreamError IsOpen() override
{
if (!this->view_)
{
return EStreamError::eErrorStreamNotOpen;
}
if (!this->pHold)
{
return EStreamError::eErrorStreamNotOpen;
}
return EStreamError::eErrorNone;
}
inline virtual EStreamError ArbitraryWrite(AuUInt uOffset, const Memory::MemoryViewStreamRead &parameters) override
{
if (!this->view_)
{
return EStreamError::eErrorStreamNotOpen;
}
if (!this->pHold)
{
return EStreamError::eErrorStreamNotOpen;
}
auto iOffset = this->iBaseOffset + AuInt64(uOffset);
if (iOffset < 0)
{
return EStreamError::eErrorOutOfBounds;
}
else
{
uOffset = iOffset;
}
if (this->view_.length < uOffset)
{
return EStreamError::eErrorEndOfStream;
}
auto uToRead = AuMin(this->view_.length - uOffset, parameters.length);
parameters.outVariable = uToRead;
AuMemcpy(this->view_.Begin<AuUInt8>() + uOffset, parameters.ptr, uToRead);
return parameters.outVariable == 0 ? EStreamError::eErrorEndOfStream : EStreamError::eErrorNone;
}
inline virtual void Close() override
{
AuResetMember(this->pHold);
AuResetMember(this->view_);
}
inline virtual void Flush() override
{
}
inline AuInt64 &GetBaseOffset()
{
return this->iBaseOffset;
}
inline const AuInt64 &GetBaseOffset() const
{
return this->iBaseOffset;
}
private:
Memory::MemoryViewWrite view_;
AuSPtr<void> pHold;
AuInt64 iBaseOffset {};
};
}

View File

@ -12,8 +12,12 @@ namespace Aurora::IO::Buffered
struct ViewWriter : IStreamWriter
{
AU_NO_COPY(ViewWriter)
AU_MOVE(ViewWriter)
inline ViewWriter(const AuSPtr<Memory::MemoryViewWrite> &view) : pView_(view)
inline ViewWriter(const AuSPtr<Memory::MemoryViewWrite> &pView) : view_(pView ? *pView.get() : Memory::MemoryViewWrite {}), pHold(pView)
{ }
inline ViewWriter(const Memory::MemoryViewWrite &view, AuSPtr<void> pBlock) : view_(view), pHold(pBlock)
{ }
inline ViewWriter()
@ -24,12 +28,12 @@ namespace Aurora::IO::Buffered
inline virtual EStreamError IsOpen() override
{
if (!this->pView_)
if (!this->view_)
{
return EStreamError::eErrorStreamNotOpen;
}
if (!(*this->pView_.get()))
if (!this->pHold)
{
return EStreamError::eErrorStreamNotOpen;
}
@ -39,26 +43,27 @@ namespace Aurora::IO::Buffered
inline virtual EStreamError Write(const Memory::MemoryViewStreamRead &parameters) override
{
if (!this->pView_)
if (!this->view_)
{
return EStreamError::eErrorStreamNotOpen;
}
if (!(*this->pView_.get()))
if (!this->pHold)
{
return EStreamError::eErrorStreamNotOpen;
}
auto uToRead = AuMin(this->pView_->length - this->uOffset_, parameters.length);
auto uToRead = AuMin(this->view_.length - this->uOffset_, parameters.length);
parameters.outVariable = uToRead;
AuMemcpy(this->pView_->Begin<AuUInt8>() + this->uOffset_, parameters.ptr, uToRead);
AuMemcpy(this->view_.Begin<AuUInt8>() + this->uOffset_, parameters.ptr, uToRead);
this->uOffset_ += uToRead;
return parameters.outVariable == 0 ? EStreamError::eErrorEndOfStream : EStreamError::eErrorNone;
}
inline virtual void Close() override
{
this->pView_.reset();
AuResetMember(this->pHold);
AuResetMember(this->view_);
}
inline virtual void Flush() override
@ -76,7 +81,8 @@ namespace Aurora::IO::Buffered
return this->uOffset_;
}
private:
AuSPtr<Memory::MemoryViewWrite> pView_;
Memory::MemoryViewWrite view_;
AuSPtr<void> pHold;
AuUInt uOffset_ {};
};
}

View File

@ -314,7 +314,9 @@ namespace Aurora::IO::FS
#include "Resources.hpp"
#include "Stat.hpp"
#include "IAsyncFileStream.hpp"
#include "IMemoryMappedFile.hpp"
#include "Async.hpp"
#include "Watcher.hpp"
#include "IReadDir.hpp"
#include "Overlapped.hpp"
#include "MemoryMappedFile.hpp"

View File

@ -0,0 +1,36 @@
/***
Copyright (C) 2024 Jamie Reece Wilson (a/k/a "Reece"). All rights reserved.
File: IMemoryMappedFile.hpp
Date: 2024-03-05
Author: Reece
***/
#pragma once
namespace Aurora::IO::FS
{
struct IMemoryMappedFile
{
virtual IIOHandle * ToHandle() = 0;
virtual AuUInt GetBaseAddress() = 0;
virtual AuUInt GetEndAddress() = 0;
virtual AuUInt GetLength() = 0;
virtual AuSPtr<IStreamReader> NewStreamReader() = 0;
virtual AuSPtr<IStreamWriter> NewStreamWriter() = 0;
virtual AuSPtr<IAsyncTransaction> NewAsyncReadTransaction() = 0;
virtual AuSPtr<IAsyncTransaction> NewAsyncWriteTransaction() = 0;
virtual ISeekingReader * ToStreamSeekingReader() = 0;
virtual ISeekingWriter * ToStreamSeekingWriter() = 0;
virtual void Flush(AuUInt uOffset,
AuUInt uLength) = 0;
virtual void Prefetch(AuUInt uOffset,
AuUInt uLength) = 0;
};
}

View File

@ -0,0 +1,29 @@
/***
Copyright (C) 2024 Jamie Reece Wilson (a/k/a "Reece"). All rights reserved.
File: MemoryMappedFile.hpp
Date: 2024-03-05
Author: Reece
***/
#pragma once
namespace Aurora::IO::FS
{
AUKN_SHARED_API(OpenMap, IMemoryMappedFile,
const AuString &path,
AuOptional<EFileOpenMode> opteMode = { EFileOpenMode::eRead },
AuOptional<AuUInt64> optuFileMapOffset = { 0 },
AuOptional<AuUInt64> optuFileMapLength = { 0 },
AuOptional<AuInt64> optiAdjustStreamOffset = { /* optuFileMapOffset */ }, // uFileMapOffset <= Stream transactions offset and IMemoryMappedFile::Flush(uOffset, ...) + iAdjustStreamOffset < uFileMapOffset + uFileMapLength
AuOptional<EFileAdvisoryLockLevel> opteSuccessPostAdvisoryLevel = { EFileAdvisoryLockLevel::eBlockReadWrite },
AuOptional<bool> optbLockEntireFile = { true });
AUKN_SHARED_API(OpenMapFromSharedHandle, IMemoryMappedFile,
const AuSPtr<IIOHandle> &pIOHandle,
AuOptional<AuUInt64> optuFileMapOffset = { 0 },
AuOptional<AuUInt64> optuFileMapLength = { 0 },
AuOptional<AuInt64> optiAdjustStreamOffset = { /* optuFileMapOffset */ }, // uFileMapOffset <= Stream transactions offset and IMemoryMappedFile::Flush(uOffset, ...) + iAdjustStreamOffset < uFileMapOffset + uFileMapLength
AuOptional<EFileAdvisoryLockLevel> opteSuccessPostAdvisoryLevel = { EFileAdvisoryLockLevel::eNoSafety }
);
}

View File

@ -155,6 +155,8 @@ namespace Aurora::IO
virtual bool SharingIsShared() = 0;
virtual void SharingStop() = 0;
virtual AuUInt64 GetFileLength() = 0;
};
AUKN_SHARED_SOO_CC(IOHandle, IIOHandle, 256);

View File

@ -749,4 +749,17 @@ namespace Aurora
pWakeByAddressAll((void *)pAddress);
}
}
AuUInt64 SysGetFileLength(AuUInt uOSHandle)
{
LARGE_INTEGER length;
if (!::GetFileSizeEx((HANDLE)uOSHandle, &length))
{
SysPushErrorIO();
return 0;
}
return length.QuadPart;
}
}

View File

@ -137,4 +137,9 @@ namespace Aurora
return true;
}
AuUInt64 SysGetFileLength(AuUInt uOSHandle)
{
return PosixGetLength(uOSHandle);
}
}

View File

@ -43,4 +43,6 @@ namespace Aurora
AuUInt32 dwCount);
void SysWakeAllOnAddress(const void *pAddress);
AuUInt64 SysGetFileLength(AuUInt uOSHandle);
}

View File

@ -12,219 +12,202 @@
namespace Aurora::IO::Adapters
{
struct AsyncReaderWriter : IAsyncTransaction,
Async::APCLessWaitable,
AuAsync::IWorkItemHandler
void AsyncReaderWriter::DispatchFrame(ProcessInfo &info)
{
AuSPtr<IStreamReader> pStreamReader;
AuSPtr<ISeekingReader> pStreamReaderEx;
AuSPtr<IStreamWriter> pStreamWriter;
AuSPtr<ISeekingWriter> pStreamWriterEx;
AuSPtr<Memory::MemoryViewRead> pReadView;
AuSPtr<Memory::MemoryViewWrite> pWriteView;
AuWorkerPId workers;
void DispatchFrame(ProcessInfo &info) override
try
{
try
if (this->iBaseOffset + AuInt64(this->uLastOffset) < 0)
{
if (this->pReadView)
this->eStreamError = EStreamError::eErrorOutOfBounds;
}
else if (this->pReadView)
{
if (this->pStreamWriter)
{
if (this->pStreamWriter)
{
this->eStreamError = this->pStreamWriter->Write(AuMemoryViewStreamRead(*this->pReadView, this->uLastLength));
}
else if (this->pStreamWriterEx)
{
this->eStreamError = this->pStreamWriterEx->ArbitraryWrite(this->uBaseOffset + this->uLastOffset, AuMemoryViewStreamRead(*this->pReadView, this->uLastLength));
}
this->eStreamError = this->pStreamWriter->Write(AuMemoryViewStreamRead(*this->pReadView, this->uLastLength));
}
else if (this->pWriteView)
else if (this->pStreamWriterEx)
{
if (this->pStreamReader)
{
this->eStreamError = this->pStreamReader->Read(AuMemoryViewStreamWrite(*this->pWriteView, this->uLastLength));
}
else if (this->pStreamReaderEx)
{
this->eStreamError = this->pStreamReaderEx->ArbitraryRead(this->uBaseOffset + this->uLastOffset, AuMemoryViewStreamWrite(*this->pWriteView, this->uLastLength));
}
this->eStreamError = this->pStreamWriterEx->ArbitraryWrite(this->iBaseOffset + this->uLastOffset, AuMemoryViewStreamRead(*this->pReadView, this->uLastLength));
}
}
catch (...)
else if (this->pWriteView)
{
this->eStreamError = EStreamError::eErrorGenericFault;
if (this->pStreamReader)
{
this->eStreamError = this->pStreamReader->Read(AuMemoryViewStreamWrite(*this->pWriteView, this->uLastLength));
}
else if (this->pStreamReaderEx)
{
this->eStreamError = this->pStreamReaderEx->ArbitraryRead(this->iBaseOffset + this->uLastOffset, AuMemoryViewStreamWrite(*this->pWriteView, this->uLastLength));
}
}
this->bInProgress = false;
this->SignalComplete();
}
void OnFailure() override
catch (...)
{
this->bInProgress = false;
this->Reset();
this->eStreamError = EStreamError::eErrorGenericFault;
}
bool StartRead(AuUInt64 uOffset, const AuSPtr<Memory::MemoryViewWrite> &memoryView) override
this->bInProgress = false;
this->SignalComplete();
}
void AsyncReaderWriter::OnFailure()
{
this->bInProgress = false;
this->Reset();
}
bool AsyncReaderWriter::StartRead(AuUInt64 uOffset, const AuSPtr<Memory::MemoryViewWrite> &memoryView)
{
if (!memoryView)
{
if (!memoryView)
{
SysPushErrorArg();
return false;
}
if (this->bInProgress)
{
return false;
}
if (!this->pStreamReaderEx && !this->pStreamReader)
{
return false;
}
AuResetMember(this->pReadView);
AuResetMember(this->pWriteView);
this->bInProgress = true;
this->uLastOffset = uOffset;
this->pWriteView = memoryView;
auto pThat = AuAsync::NewWorkItem(this->workers, AuStaticCast<AsyncReaderWriter>(this->SharedFromThis()));
if (!pThat)
{
return false;
}
return pThat->Dispatch();
SysPushErrorArg();
return false;
}
bool StartWrite(AuUInt64 uOffset, const AuSPtr<Memory::MemoryViewRead> &memoryView) override
if (this->bInProgress)
{
if (!memoryView)
{
SysPushErrorArg();
return false;
}
if (this->bInProgress)
{
return false;
}
if (!this->pStreamWriterEx && !this->pStreamWriter)
{
return false;
}
AuResetMember(this->pReadView);
AuResetMember(this->pWriteView);
this->bInProgress = true;
this->uLastOffset = uOffset;
this->pReadView = memoryView;
auto pThat = AuAsync::NewWorkItem(this->workers, AuStaticCast<AsyncReaderWriter>(this->SharedFromThis()));
if (!pThat)
{
return false;
}
return pThat->Dispatch();
return false;
}
AuUInt32 GetLastPacketLength() override
if (!this->pStreamReaderEx && !this->pStreamReader)
{
return this->uLastLength;
return false;
}
void OnOriginThreadComplete() override
AuResetMember(this->pReadView);
AuResetMember(this->pWriteView);
this->bInProgress = true;
this->uLastOffset = uOffset;
this->pWriteView = memoryView;
auto pThat = AuAsync::NewWorkItem(this->workers, AuStaticCast<AsyncReaderWriter>(this->SharedFromThis()));
if (!pThat)
{
if (this->pSubscriber)
{
this->pSubscriber->OnAsyncFileOpFinished(this->uBaseOffset + this->uLastOffset, this->GetLastPacketLength());
}
AuResetMember(this->pReadView);
AuResetMember(this->pWriteView);
return false;
}
bool Complete() override
return pThat->Dispatch();
}
bool AsyncReaderWriter::StartWrite(AuUInt64 uOffset, const AuSPtr<Memory::MemoryViewRead> &memoryView)
{
if (!memoryView)
{
Async::APCLessWaitable::CheckLocal();
return Async::APCLessWaitable::HasBeenSignaled();
SysPushErrorArg();
return false;
}
bool HasFailed() override
if (this->bInProgress)
{
return Async::APCLessWaitable::HasBeenSignaled() && this->eStreamError != EStreamError::eErrorNone;
return false;
}
bool HasCompleted() override
if (!this->pStreamWriterEx && !this->pStreamWriter)
{
return Async::APCLessWaitable::HasBeenSignaled() && this->eStreamError == EStreamError::eErrorNone;
return false;
}
AuUInt GetOSErrorCode() override
AuResetMember(this->pReadView);
AuResetMember(this->pWriteView);
this->bInProgress = true;
this->uLastOffset = uOffset;
this->pReadView = memoryView;
auto pThat = AuAsync::NewWorkItem(this->workers, AuStaticCast<AsyncReaderWriter>(this->SharedFromThis()));
if (!pThat)
{
return this->HasFailed() ? AuUInt(this->eStreamError) : 0;
return false;
}
void SetCallback(const AuSPtr<IAsyncFinishedSubscriber> &pSubscriber) override
return pThat->Dispatch();
}
AuUInt32 AsyncReaderWriter::GetLastPacketLength()
{
return this->uLastLength;
}
void AsyncReaderWriter::OnOriginThreadComplete()
{
if (this->pSubscriber)
{
this->pSubscriber = pSubscriber;
this->pSubscriber->OnAsyncFileOpFinished(this->uLastOffset, this->GetLastPacketLength());
}
bool Wait(AuUInt32 uTimeout) override
AuResetMember(this->pReadView);
AuResetMember(this->pWriteView);
}
bool AsyncReaderWriter::Complete()
{
Async::APCLessWaitable::CheckLocal();
return Async::APCLessWaitable::HasBeenSignaled();
}
bool AsyncReaderWriter::HasFailed()
{
return Async::APCLessWaitable::HasBeenSignaled() && this->eStreamError != EStreamError::eErrorNone;
}
bool AsyncReaderWriter::HasCompleted()
{
return Async::APCLessWaitable::HasBeenSignaled() && this->eStreamError == EStreamError::eErrorNone;
}
AuUInt AsyncReaderWriter::GetOSErrorCode()
{
return this->HasFailed() ? AuUInt(this->eStreamError) : 0;
}
void AsyncReaderWriter::SetCallback(const AuSPtr<IAsyncFinishedSubscriber> &pSubscriber)
{
this->pSubscriber = pSubscriber;
}
bool AsyncReaderWriter::Wait(AuUInt32 uTimeout)
{
return NewLoopSource()->WaitOn(uTimeout);
}
AuSPtr<IO::Loop::ILoopSource> AsyncReaderWriter::NewLoopSource()
{
return Async::APCLessWaitable::GetLoopSource();
}
void AsyncReaderWriter::Reset()
{
if (this->bInProgress)
{
return NewLoopSource()->WaitOn(uTimeout);
return;
}
AuSPtr<IO::Loop::ILoopSource> NewLoopSource() override
{
return Async::APCLessWaitable::GetLoopSource();
}
AuResetMember(this->pReadView);
AuResetMember(this->pWriteView);
Async::APCLessWaitable::Reset();
}
void Reset() override
{
if (this->bInProgress)
{
return;
}
void AsyncReaderWriter::SetBaseOffset(AuUInt64 uBaseOffset)
{
this->iBaseOffset = uBaseOffset;
}
AuResetMember(this->pReadView);
AuResetMember(this->pWriteView);
Async::APCLessWaitable::Reset();
}
bool AsyncReaderWriter::TryAttachToCompletionGroup(const AuSPtr<CompletionGroup::ICompletionGroup> &pCompletionGroup)
{
return Async::APCLessWaitable::TryAttachToCompletionGroup(pCompletionGroup);
}
void SetBaseOffset(AuUInt64 uBaseOffset) override
{
this->uBaseOffset = uBaseOffset;
}
CompletionGroup::ICompletionGroupWorkHandle *AsyncReaderWriter::ToCompletionGroupHandle()
{
return this;
}
bool TryAttachToCompletionGroup(const AuSPtr<CompletionGroup::ICompletionGroup> &pCompletionGroup) override
{
return Async::APCLessWaitable::TryAttachToCompletionGroup(pCompletionGroup);
}
AuSPtr<CompletionGroup::ICompletionGroup> AsyncReaderWriter::GetCompletionGroup()
{
return Async::APCLessWaitable::GetCompletionGroup();
}
CompletionGroup::ICompletionGroupWorkHandle *ToCompletionGroupHandle() override
{
return this;
}
AuSPtr<CompletionGroup::ICompletionGroup> GetCompletionGroup() override
{
return Async::APCLessWaitable::GetCompletionGroup();
}
private:
AuMutex mutex;
AuSPtr<IAsyncFinishedSubscriber> pSubscriber;
AuUInt64 uBaseOffset {};
AuUInt64 uLastOffset {};
AuUInt uLastLength {};
bool bInProgress {};
EStreamError eStreamError = EStreamError::eErrorNone;
};
static AuWorkerPId GetAuxWorkerPool()
{

View File

@ -7,6 +7,66 @@
***/
#pragma once
#include <Source/IO/Async/AuIOThreadPool.hpp>
#include <Source/IO/Async/AuIOAPCLessWaitable.hpp>
namespace Aurora::IO::Adapters
{
struct AsyncReaderWriter : IAsyncTransaction,
Async::APCLessWaitable,
AuAsync::IWorkItemHandler
{
AuSPtr<IStreamReader> pStreamReader;
AuSPtr<ISeekingReader> pStreamReaderEx;
AuSPtr<IStreamWriter> pStreamWriter;
AuSPtr<ISeekingWriter> pStreamWriterEx;
AuSPtr<Memory::MemoryViewRead> pReadView;
AuSPtr<Memory::MemoryViewWrite> pWriteView;
AuWorkerPId workers;
void DispatchFrame(ProcessInfo &info) override;
void OnFailure() override;
bool StartRead(AuUInt64 uOffset, const AuSPtr<Memory::MemoryViewWrite> &memoryView) override;
bool StartWrite(AuUInt64 uOffset, const AuSPtr<Memory::MemoryViewRead> &memoryView) override;
AuUInt32 GetLastPacketLength() override;
void OnOriginThreadComplete() override;
bool Complete() override;
bool HasFailed() override;
bool HasCompleted() override;
AuUInt GetOSErrorCode() override;
void SetCallback(const AuSPtr<IAsyncFinishedSubscriber> &pSubscriber) override;
bool Wait(AuUInt32 uTimeout) override;
AuSPtr<IO::Loop::ILoopSource> NewLoopSource() override;
void Reset() override;
void SetBaseOffset(AuUInt64 uBaseOffset) override;
bool TryAttachToCompletionGroup(const AuSPtr<CompletionGroup::ICompletionGroup> &pCompletionGroup) override;
CompletionGroup::ICompletionGroupWorkHandle *ToCompletionGroupHandle() override;
AuSPtr<CompletionGroup::ICompletionGroup> GetCompletionGroup() override;
AuInt64 iBaseOffset {};
private:
AuMutex mutex;
AuSPtr<IAsyncFinishedSubscriber> pSubscriber;
AuUInt64 uLastOffset {};
AuUInt uLastLength {};
bool bInProgress {};
EStreamError eStreamError = EStreamError::eErrorNone;
};
}

View File

@ -17,7 +17,7 @@ namespace Aurora::IO::Adapters
SysCheckRetExpNotNullMemory(AuMakeShared<Buffered::BlobReader>(pBuffer), {});
}
AUKN_SYM AuSPtr<ISeekingReader> NewByteBufferLinearSeekableAdapter(const AuSPtr<Memory::ByteBuffer> &pBuffer)
AUKN_SYM AuSPtr<ISeekingReader> NewByteBufferLinearReadSeekableAdapter(const AuSPtr<Memory::ByteBuffer> &pBuffer)
{
SysCheckArgNotNull(pBuffer, {});
if (pBuffer->flagCircular)
@ -29,6 +29,18 @@ namespace Aurora::IO::Adapters
SysCheckRetExpNotNullMemory(AuMakeShared<Buffered::BlobSeekableReader>(pBuffer), {});
}
AUKN_SYM AuSPtr<ISeekingWriter> NewByteBufferLinearWriteSeekableAdapter(const AuSPtr<Memory::ByteBuffer> &pBuffer)
{
SysCheckArgNotNull(pBuffer, {});
if (pBuffer->flagCircular)
{
SysPushErrorIO("Seekable buffer must not be circular");
return {};
}
SysCheckRetExpNotNullMemory(AuMakeShared<Buffered::BlobSeekableWriter>(pBuffer), {});
}
AUKN_SYM AuSPtr<IStreamWriter> NewByteBufferWriteAdapter(const AuSPtr<Memory::ByteBuffer> &pBuffer)
{
SysCheckArgNotNull(pBuffer, {});

View File

@ -18,10 +18,10 @@ namespace Aurora::IO::Adapters
SysCheckRetExpNotNullMemory(AuMakeShared<Buffered::ViewReader>(pView), {});
}
AUKN_SYM AuSPtr<ISeekingReader> NewMemoryViewLinearSeekableAdapter(const AuSPtr<Memory::MemoryViewRead> &pView)
AUKN_SYM AuSPtr<ISeekingReader> NewMemoryViewReadSeekingAdapter(const AuSPtr<Memory::MemoryViewRead> &pView)
{
SysCheckArgNotNull(pView, {});
SysCheckRetExpNotNullMemory(AuMakeShared<Buffered::ViewSeekableReadable>(pView), {});
SysCheckRetExpNotNullMemory(AuMakeShared<Buffered::ViewSeekableReader>(pView), {});
}
AUKN_SYM AuSPtr<IStreamWriter> NewMemoryViewWriteAdapter(const AuSPtr<Memory::MemoryViewWrite> &pView)
@ -29,4 +29,10 @@ namespace Aurora::IO::Adapters
SysCheckArgNotNull(pView, {});
SysCheckRetExpNotNullMemory(AuMakeShared<Buffered::ViewWriter>(pView), {});
}
AUKN_SYM AuSPtr<ISeekingWriter> NewMemoryViewWriteSeekableAdapter(const AuSPtr<Memory::MemoryViewWrite> &pView)
{
SysCheckArgNotNull(pView, {});
SysCheckRetExpNotNullMemory(AuMakeShared<Buffered::ViewSeekableWriter>(pView), {});
}
}

View File

@ -259,7 +259,10 @@ namespace Aurora::IO
AuUInt64 AFileHandle::GetOSHandle() const
{
return this->uOSReadHandle.ValueOr(this->uOSWriteHandle.value());
return this->uOSWriteHandle.OrElse(AuMove([=]()
{
return this->uOSReadHandle;
})).Value();
}
AuUInt64 AFileHandle::GetOSReadHandle() const
@ -397,6 +400,17 @@ namespace Aurora::IO
}
}
AuUInt64 AFileHandle::GetFileLength()
{
if (this->uOSReadHandle)
{
return SysGetFileLength(this->uOSReadHandle.Value());
}
SysPushErrorResourceInvalid();
return 0;
}
AUKN_SYM IIOHandle *IOHandleNew()
{
return _new AFileHandle();

View File

@ -77,6 +77,8 @@ namespace Aurora::IO
bool SharingIsShared() override;
void SharingStop() override;
AuUInt64 GetFileLength() override;
AuOptionalEx<AuUInt64> uOSWriteHandle;
AuOptionalEx<AuUInt64> uOSReadHandle;
AuSPtr<IIOHandle> pThat;

View File

@ -0,0 +1,330 @@
/***
Copyright (C) 2024 Jamie Reece Wilson (a/k/a "Reece"). All rights reserved.
File: FSMemoryMappedFile.cpp
Date: 2024-03-05
Author: Reece
***/
#include <Source/RuntimeInternal.hpp>
#include "FSMemoryMappedFile.hpp"
#include <Source/IO/Adapters/AuIOAdapterAsyncDelegators.hpp>
namespace Aurora::IO::FS
{
IIOHandle * MemoryMappedFile::ToHandle()
{
return this->pHandleShared ?
this->pHandleShared.get() :
this->handle.AsPointer();
}
AuUInt MemoryMappedFile::GetBaseAddress()
{
if (this->pView)
{
return (AuUInt)this->pView->GetBasePointer();
}
else
{
return 0;
}
}
AuUInt MemoryMappedFile::GetEndAddress()
{
if (this->pView)
{
return (AuUInt)this->pView->GetBasePointer() +
this->GetLength();
}
else
{
return 0;
}
}
AuUInt MemoryMappedFile::GetLength()
{
return this->uFileMapLength;
}
AuSPtr<IStreamReader> MemoryMappedFile::NewStreamReader()
{
return AuMakeShared<IO::Buffered::ViewReader>(this->ToReadView(), this->pView);
}
AuSPtr<IStreamWriter> MemoryMappedFile::NewStreamWriter()
{
return AuMakeShared<IO::Buffered::ViewWriter>(this->ToWriteView(), this->pView);
}
AuSPtr<IAsyncTransaction> MemoryMappedFile::NewAsyncReadTransaction()
{
auto pReader = AuMakeShared<IO::Buffered::ViewSeekableReader>(this->ToReadViewAlt(), this->pView);
SysCheckNotNullMemory(pReader, {});
auto iBaseOffset = 0 -
AuInt64(this->uFileMapOffset) +
this->iAdjustStreamOffset;
pReader->GetBaseOffset() = iBaseOffset;
auto pTransaction = Adapters::NewAsyncTransactionFromStreamSeekingReader(pReader, {});
SysCheckNotNullMemory(pTransaction, {});
return pTransaction;
}
AuSPtr<IAsyncTransaction> MemoryMappedFile::NewAsyncWriteTransaction()
{
auto pWriter = AuMakeShared<IO::Buffered::ViewSeekableWriter>(this->ToWriteViewAlt(), this->pView);
SysCheckNotNullMemory(pWriter, {});
auto iBaseOffset = 0 -
AuInt64(this->uFileMapOffset) +
this->iAdjustStreamOffset;
pWriter->GetBaseOffset() = iBaseOffset;
auto pTransaction = Adapters::NewAsyncTransactionFromStreamSeekingWriter(pWriter, {});
SysCheckNotNullMemory(pTransaction, {});
return pTransaction;
}
ISeekingReader *MemoryMappedFile::ToStreamSeekingReader()
{
if (this->optSeekableReader)
{
return &this->optSeekableReader.Value();
}
else
{
return nullptr;
}
}
ISeekingWriter *MemoryMappedFile::ToStreamSeekingWriter()
{
if (this->optSeekableWriter)
{
return &this->optSeekableWriter.Value();
}
else
{
return nullptr;
}
}
AuMemoryViewRead MemoryMappedFile::ToReadView()
{
auto pBasePointer = this->pView->GetBasePointer();
auto iBaseOffset = 0 -
AuInt64(this->uFileMapOffset) +
this->iAdjustStreamOffset;
if (iBaseOffset < 0)
{
return {};
}
auto pHeadPointer = pBasePointer + iBaseOffset;
return { pHeadPointer, this->GetEndAddress() - AuUInt(pHeadPointer) };
}
AuMemoryViewWrite MemoryMappedFile::ToWriteView()
{
auto pBasePointer = this->pView->GetBasePointer();
auto iBaseOffset = 0 -
AuInt64(this->uFileMapOffset) +
this->iAdjustStreamOffset;
if (iBaseOffset < 0)
{
return {};
}
auto pHeadPointer = pBasePointer + iBaseOffset;
return { pHeadPointer, this->GetEndAddress() - AuUInt(pHeadPointer) };
}
AuMemoryViewRead MemoryMappedFile::ToReadViewAlt()
{
auto pBasePointer = this->pView->GetBasePointer();
return { pBasePointer, this->GetEndAddress() - AuUInt(pBasePointer) };
}
AuMemoryViewWrite MemoryMappedFile::ToWriteViewAlt()
{
auto pBasePointer = this->pView->GetBasePointer();
return { pBasePointer, this->GetEndAddress() - AuUInt(pBasePointer) };
}
void MemoryMappedFile::Flush(AuUInt uOffset,
AuUInt uLength)
{
auto iOffset = 0 - AuSInt(this->uFileMapOffset) + AuSInt(iAdjustStreamOffset) + AuSInt(uOffset);
if (iOffset < 0)
{
return;
}
auto uStartAddress = iOffset;
auto uEndAddress = AuMin(this->GetLength(), uStartAddress + uLength);
auto uSecondLength = uEndAddress - uStartAddress;
this->pView->Flush(iOffset, uSecondLength);
}
void MemoryMappedFile::Prefetch(AuUInt uOffset,
AuUInt uLength)
{
AU_DEBUG_MEMCRUNCH;
auto iOffset = 0 - AuSInt(this->uFileMapOffset) + AuSInt(iAdjustStreamOffset) + AuSInt(uOffset);
if (iOffset < 0)
{
return;
}
auto uStartAddress = this->GetBaseAddress() + iOffset;
auto uEndAddress = AuMin(this->GetEndAddress(), uStartAddress + uLength);
auto uSecondLength = uEndAddress - uStartAddress;
AuMemory::Cache::OptimizeAddressRangeOnCore({
{
uStartAddress,
uSecondLength
}
});
}
bool MemoryMappedFile::Init(EFileOpenMode eMode,
AuUInt64 uFileMapOffset,
AuUInt64 uFileMapLength,
AuInt64 iAdjustStreamOffset,
EFileAdvisoryLockLevel eLockLevel)
{
auto pHandle = this->ToHandle();
if (!uFileMapLength)
{
uFileMapLength = pHandle->GetFileLength();
}
this->uFileMapLength = uFileMapLength;
this->uFileMapOffset = uFileMapOffset;
this->iAdjustStreamOffset = iAdjustStreamOffset;
auto pAddressSpace = AuProcess::GetGlobalProcessSpace();
this->pView = pAddressSpace->MapFileByObject(AuUnsafeRaiiToShared(this->ToHandle()),
uFileMapOffset,
uFileMapLength,
eMode,
eLockLevel);
if (!this->pView)
{
SysPushErrorNested();
return false;
}
{
auto iBaseOffset = 0 -
AuInt64(this->uFileMapOffset) +
this->iAdjustStreamOffset;
IO::Buffered::ViewSeekableReader reader(this->ToReadViewAlt(), this->pView);
IO::Buffered::ViewSeekableWriter writer(this->ToWriteViewAlt(), this->pView);
writer.GetBaseOffset() = iBaseOffset;
reader.GetBaseOffset() = iBaseOffset;
this->optSeekableReader = AuMove(reader);
this->optSeekableWriter = AuMove(writer);
}
return true;
}
IMemoryMappedFile *OpenMapNew(const AuString &path,
AuOptional<EFileOpenMode> opteMode,
AuOptional<AuUInt64> optuFileMapOffset,
AuOptional<AuUInt64> optuFileMapLength,
AuOptional<AuInt64> optiAdjustStreamOffset,
AuOptional<EFileAdvisoryLockLevel> opteAdvisoryLevel,
AuOptional<bool> optbLockEntireFile)
{
auto eMode = opteMode.ValueOr(EFileOpenMode::eRead);
auto uFileMapOffset = optuFileMapOffset.ValueOr(0);
auto uFileLength = optuFileMapLength.ValueOr(0);
auto iAdjustStreamOffset = optiAdjustStreamOffset.ValueOr(uFileMapOffset);
auto bLockEntireFile = optbLockEntireFile.ValueOr(true);
auto eAdvisoryLevel = opteAdvisoryLevel.ValueOr(EFileAdvisoryLockLevel::eBlockReadWrite);
auto pReturn = _new MemoryMappedFile();
SysCheckNotNullMemory(pReturn, {});
auto createRequest = AuIO::IIOHandle::HandleCreate::Create(path);
createRequest.eMode = eMode;
createRequest.eAdvisoryLevel = bLockEntireFile ? eAdvisoryLevel : EFileAdvisoryLockLevel::eNoSafety;
createRequest.bDirectIOMode = false;
if (!pReturn->handle->InitFromPath(createRequest))
{
delete pReturn;
return nullptr;
}
if (!pReturn->Init(eMode, uFileMapOffset, uFileLength, iAdjustStreamOffset, !bLockEntireFile ? eAdvisoryLevel : EFileAdvisoryLockLevel::eNoSafety))
{
delete pReturn;
return nullptr;
}
return pReturn;
}
void OpenMapRelease(IMemoryMappedFile *pReturn)
{
AuSafeDelete<MemoryMappedFile *>(pReturn);
}
IMemoryMappedFile *OpenMapFromSharedHandleNew(const AuSPtr<IIOHandle> &pIOHandle,
AuOptional<AuUInt64> optuFileMapOffset,
AuOptional<AuUInt64> optuFileMapLength,
AuOptional<AuInt64> optiAdjustStreamOffset,
AuOptional<EFileAdvisoryLockLevel> opteAdvisoryLevel)
{
auto uFileMapOffset = optuFileMapOffset.ValueOr(0);
auto uFileLength = optuFileMapLength.ValueOr(0);
auto iAdjustStreamOffset = optiAdjustStreamOffset.ValueOr(uFileMapOffset);
auto eAdvisoryLevel = opteAdvisoryLevel.ValueOr(EFileAdvisoryLockLevel::eNoSafety);
SysCheckArgNotNull(pIOHandle, {});
auto pReturn = _new MemoryMappedFile();
SysCheckNotNullMemory(pReturn, {});
pReturn->pHandleShared = pIOHandle;
if (!pReturn->Init(pIOHandle->GetOSWriteHandleSafe() ? EFileOpenMode::eReadWrite : EFileOpenMode::eRead,
uFileMapOffset,
uFileLength,
iAdjustStreamOffset,
eAdvisoryLevel))
{
delete pReturn;
return nullptr;
}
return pReturn;
}
void OpenMapFromSharedHandleRelease(IMemoryMappedFile *pReturn)
{
AuSafeDelete<MemoryMappedFile *>(pReturn);
}
}

View File

@ -0,0 +1,54 @@
/***
Copyright (C) 2024 Jamie Reece Wilson (a/k/a "Reece"). All rights reserved.
File: FSMemoryMappedFile.hpp
Date: 2024-03-05
Author: Reece
***/
#pragma once
namespace Aurora::IO::FS
{
struct MemoryMappedFile : IMemoryMappedFile
{
virtual IIOHandle * ToHandle() override;
virtual AuUInt GetBaseAddress() override;
virtual AuUInt GetEndAddress() override;
virtual AuUInt GetLength() override;
virtual AuSPtr<IStreamReader> NewStreamReader() override;
virtual AuSPtr<IStreamWriter> NewStreamWriter() override;
virtual AuSPtr<IAsyncTransaction> NewAsyncReadTransaction() override;
virtual AuSPtr<IAsyncTransaction> NewAsyncWriteTransaction() override;
virtual ISeekingReader * ToStreamSeekingReader() override;
virtual ISeekingWriter * ToStreamSeekingWriter() override;
AuMemoryViewRead ToReadView();
AuMemoryViewWrite ToWriteView();
AuMemoryViewRead ToReadViewAlt();
AuMemoryViewWrite ToWriteViewAlt();
virtual void Flush(AuUInt uOffset,
AuUInt uLength) override;
virtual void Prefetch(AuUInt uOffset,
AuUInt uLength) override;
bool Init(EFileOpenMode eMode,
AuUInt64 uFileMapOffset,
AuUInt64 uFileMapLength,
AuInt64 iAdjustStreamOffset,
EFileAdvisoryLockLevel eLockLevel);
AuIOHandle handle;
AuSPtr<AuIO::IIOHandle> pHandleShared;
AuSPtr<AuProcess::IProcessSectionMapView> pView;
AuUInt64 uFileMapLength;
AuUInt64 uFileMapOffset;
AuInt64 iAdjustStreamOffset;
AuOptional<IO::Buffered::ViewSeekableWriter> optSeekableWriter;
AuOptional<IO::Buffered::ViewSeekableReader> optSeekableReader;
};
}