[*] Thread-safety: harden io file streams and improve construction api of OpenBlockingFileStreamFromHandle
This commit is contained in:
parent
ccc4116394
commit
25b1a9cad6
@ -9,7 +9,7 @@
|
||||
|
||||
namespace Aurora::IO::FS
|
||||
{
|
||||
// WARNING: there are no truncate write modes. IFileStream::WriteEoS must be called by the caller of Open[Write]s.
|
||||
// WARNING: there are no truncate write modes. IFileStream::WriteEoS or IFileStream::SetWriteEoSOnClose must be called by the caller of `Open[Write]/Create`s.
|
||||
|
||||
AUKN_SHARED_API(Create, IFileStream, const AuString &path);
|
||||
|
||||
@ -19,5 +19,5 @@ namespace Aurora::IO::FS
|
||||
|
||||
AUKN_SHARED_API(Open, IFileStream, const AuString &path, EFileOpenMode mode = EFileOpenMode::eRead, EFileAdvisoryLockLevel successPostAdvisoryLevel = EFileAdvisoryLockLevel::eBlockReadWrite);
|
||||
|
||||
AUKN_SYM AuSPtr<IFileStream> OpenBlockingFileStreamFromHandle(AuSPtr<IIOHandle> pIOHandle);
|
||||
AUKN_SHARED_API(OpenBlockingFileStreamFromHandle, IFileStream, const AuSPtr<IIOHandle> &pIOHandle);
|
||||
}
|
@ -9,7 +9,6 @@
|
||||
|
||||
namespace Aurora::IO::FS
|
||||
{
|
||||
// Thread-Local!
|
||||
struct IFileStream
|
||||
{
|
||||
/**
|
||||
@ -104,8 +103,14 @@ namespace Aurora::IO::FS
|
||||
*/
|
||||
virtual IO::IStreamWriter *ToStreamWriter() = 0;
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*/
|
||||
virtual IO::ISeekingReader *ToStreamSeekingReader() = 0;
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*/
|
||||
virtual IO::ISeekingWriter *ToStreamSeekingWriter() = 0;
|
||||
|
||||
AURT_ADD_USR_DATA;
|
||||
|
@ -38,6 +38,8 @@ namespace Aurora::IO::FS
|
||||
|
||||
AuUInt64 WinFileStream::GetOffset()
|
||||
{
|
||||
AU_LOCK_GUARD(this->mutex_);
|
||||
|
||||
LARGE_INTEGER distance {};
|
||||
LARGE_INTEGER pos {};
|
||||
HANDLE hHandle {};
|
||||
@ -78,6 +80,8 @@ namespace Aurora::IO::FS
|
||||
|
||||
bool WinFileStream::SetOffset(AuUInt64 offset)
|
||||
{
|
||||
AU_LOCK_GUARD(this->mutex_);
|
||||
|
||||
LARGE_INTEGER distance {};
|
||||
LARGE_INTEGER pos {};
|
||||
HANDLE hHandle {};
|
||||
@ -117,6 +121,8 @@ namespace Aurora::IO::FS
|
||||
|
||||
AuUInt64 WinFileStream::GetLength()
|
||||
{
|
||||
AU_LOCK_GUARD(this->mutex_);
|
||||
|
||||
LARGE_INTEGER length;
|
||||
HANDLE hHandle {};
|
||||
|
||||
@ -153,6 +159,8 @@ namespace Aurora::IO::FS
|
||||
|
||||
bool WinFileStream::Read(const Memory::MemoryViewStreamWrite ¶meters)
|
||||
{
|
||||
AU_LOCK_GUARD(this->mutex_);
|
||||
|
||||
OVERLAPPED overlapped {};
|
||||
AuUInt64 uOffset {};
|
||||
|
||||
@ -270,6 +278,8 @@ namespace Aurora::IO::FS
|
||||
|
||||
bool WinFileStream::Write(const Memory::MemoryViewStreamRead ¶meters)
|
||||
{
|
||||
AU_LOCK_GUARD(this->mutex_);
|
||||
|
||||
OVERLAPPED overlapped {};
|
||||
AuUInt64 uOffset {};
|
||||
|
||||
@ -376,6 +386,8 @@ namespace Aurora::IO::FS
|
||||
|
||||
void WinFileStream::WriteEoS()
|
||||
{
|
||||
AU_LOCK_GUARD(this->mutex_);
|
||||
|
||||
auto hHandle = this->GetWin32Handle();
|
||||
|
||||
if (hHandle == INVALID_HANDLE_VALUE)
|
||||
@ -389,6 +401,8 @@ namespace Aurora::IO::FS
|
||||
|
||||
void WinFileStream::Close()
|
||||
{
|
||||
AU_LOCK_GUARD(this->mutex_);
|
||||
|
||||
auto hHandle = this->GetWin32Handle();
|
||||
bool bDeleteFailed {};
|
||||
AuString path;
|
||||
@ -444,6 +458,8 @@ namespace Aurora::IO::FS
|
||||
|
||||
bool WinFileStream::IsFlushOnClose() const
|
||||
{
|
||||
AU_LOCK_GUARD(this->mutex_);
|
||||
|
||||
if (auto pHandle = this->pHandle_)
|
||||
{
|
||||
return pHandle->IsFlushOnClose();
|
||||
@ -456,6 +472,8 @@ namespace Aurora::IO::FS
|
||||
|
||||
void WinFileStream::SetFlushOnClose(bool bFlushOnClose)
|
||||
{
|
||||
AU_LOCK_GUARD(this->mutex_);
|
||||
|
||||
if (auto pHandle = this->pHandle_)
|
||||
{
|
||||
pHandle->SetFlushOnClose(bFlushOnClose);
|
||||
@ -514,30 +532,40 @@ namespace Aurora::IO::FS
|
||||
return INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
AUKN_SYM AuSPtr<IFileStream> OpenBlockingFileStreamFromHandle(AuSPtr<IIOHandle> pIOHandle)
|
||||
AUKN_SYM IFileStream *OpenBlockingFileStreamFromHandleNew(const AuSPtr<IIOHandle> &pIOHandle)
|
||||
{
|
||||
SysCheckArgNotNull(pIOHandle, {});
|
||||
|
||||
auto pStream = AuMakeShared<WinFileStream>();
|
||||
auto pStream = _new WinFileStream();
|
||||
SysCheckNotNullMemory(pStream, {});
|
||||
|
||||
if (!AuStaticCast<AFileHandle>(pIOHandle)->pIPCPipe &&
|
||||
AuStaticCast<AFileHandle>(pIOHandle)->ShouldClone())
|
||||
{
|
||||
auto pOld = pIOHandle;
|
||||
pIOHandle = AuMakeShared<AFileHandle>();
|
||||
SysCheckNotNullMemory(pIOHandle, {});
|
||||
if (!pIOHandle->InitFromPair(pOld->GetOSReadHandleSafe(), pOld->GetOSWriteHandle()))
|
||||
auto pIOHandle2 = AuMakeShared<AFileHandle>();
|
||||
SysCheckNotNullMemory(pIOHandle2, {});
|
||||
|
||||
if (!pIOHandle2->InitFromPair(pIOHandle->GetOSReadHandleSafe(), pIOHandle->GetOSWriteHandle()))
|
||||
{
|
||||
SysPushErrorIOResourceFailure();
|
||||
return {};
|
||||
}
|
||||
|
||||
pStream->Init(pIOHandle2);
|
||||
}
|
||||
else
|
||||
{
|
||||
pStream->Init(pIOHandle);
|
||||
}
|
||||
|
||||
pStream->Init(pIOHandle);
|
||||
return pStream;
|
||||
}
|
||||
|
||||
AUKN_SYM void OpenBlockingFileStreamFromHandleRelease(IFileStream *that)
|
||||
{
|
||||
AuSafeDelete<WinFileStream *>(that);
|
||||
}
|
||||
|
||||
static IFileStream *OpenNewEx(const AuString &path,
|
||||
EFileOpenMode openMode,
|
||||
EFileAdvisoryLockLevel lock,
|
||||
|
@ -47,6 +47,7 @@ namespace Aurora::IO::FS
|
||||
AuFS::FileWriter writer_;
|
||||
AuFS::FileSeekableReader sreader_;
|
||||
AuFS::FileSeekableWriter swriter_;
|
||||
AuMutex mutex_;
|
||||
};
|
||||
}
|
||||
#endif
|
@ -47,7 +47,7 @@ namespace Aurora::IO::FS
|
||||
|
||||
AuUInt64 PosixFileStream::GetOffset()
|
||||
{
|
||||
AU_LOCK_GUARD(this->spinlock_);
|
||||
AU_LOCK_GUARD(this->mutex_);
|
||||
|
||||
int fd {};
|
||||
if (auto pHandle = this->pHandle_)
|
||||
@ -79,7 +79,7 @@ namespace Aurora::IO::FS
|
||||
|
||||
bool PosixFileStream::SetOffset(AuUInt64 offset)
|
||||
{
|
||||
AU_LOCK_GUARD(this->spinlock_);
|
||||
AU_LOCK_GUARD(this->mutex_);
|
||||
|
||||
int fd {};
|
||||
if (auto pHandle = this->pHandle_)
|
||||
@ -111,7 +111,7 @@ namespace Aurora::IO::FS
|
||||
|
||||
AuUInt64 PosixFileStream::GetLength()
|
||||
{
|
||||
AU_LOCK_GUARD(this->spinlock_);
|
||||
AU_LOCK_GUARD(this->mutex_);
|
||||
|
||||
int fd {};
|
||||
if (auto pHandle = this->pHandle_)
|
||||
@ -147,7 +147,7 @@ namespace Aurora::IO::FS
|
||||
|
||||
bool PosixFileStream::Read(const Memory::MemoryViewStreamWrite ¶meters)
|
||||
{
|
||||
AU_LOCK_GUARD(this->spinlock_);
|
||||
AU_LOCK_GUARD(this->mutex_);
|
||||
|
||||
parameters.outVariable = 0;
|
||||
|
||||
@ -212,7 +212,7 @@ namespace Aurora::IO::FS
|
||||
|
||||
bool PosixFileStream::Write(const Memory::MemoryViewStreamRead ¶meters)
|
||||
{
|
||||
AU_LOCK_GUARD(this->spinlock_);
|
||||
AU_LOCK_GUARD(this->mutex_);
|
||||
|
||||
parameters.outVariable = 0;
|
||||
|
||||
@ -264,6 +264,8 @@ namespace Aurora::IO::FS
|
||||
|
||||
void PosixFileStream::Close()
|
||||
{
|
||||
AU_LOCK_GUARD(this->mutex_);
|
||||
|
||||
auto pHandle = this->pHandle_;
|
||||
AuResetMember(this->pHandle_);
|
||||
|
||||
@ -283,6 +285,8 @@ namespace Aurora::IO::FS
|
||||
|
||||
bool PosixFileStream::IsFlushOnClose() const
|
||||
{
|
||||
AU_LOCK_GUARD(this->mutex_);
|
||||
|
||||
if (auto pHandle = this->pHandle_)
|
||||
{
|
||||
return pHandle->IsFlushOnClose();
|
||||
@ -295,6 +299,8 @@ namespace Aurora::IO::FS
|
||||
|
||||
void PosixFileStream::SetFlushOnClose(bool bFlushOnClose)
|
||||
{
|
||||
AU_LOCK_GUARD(this->mutex_);
|
||||
|
||||
if (auto pHandle = this->pHandle_)
|
||||
{
|
||||
pHandle->SetFlushOnClose(bFlushOnClose);
|
||||
@ -313,6 +319,8 @@ namespace Aurora::IO::FS
|
||||
|
||||
void PosixFileStream::Flush()
|
||||
{
|
||||
AU_LOCK_GUARD(this->mutex_);
|
||||
|
||||
if (!this->pHandle_)
|
||||
{
|
||||
SysPushErrorUninitialized();
|
||||
@ -331,6 +339,8 @@ namespace Aurora::IO::FS
|
||||
|
||||
void PosixFileStream::WriteEoS()
|
||||
{
|
||||
AU_LOCK_GUARD(this->mutex_);
|
||||
|
||||
if (!this->pHandle_)
|
||||
{
|
||||
SysPushErrorUninitialized();
|
||||
@ -384,30 +394,40 @@ namespace Aurora::IO::FS
|
||||
return &this->swriter_;
|
||||
}
|
||||
|
||||
AUKN_SYM AuSPtr<IFileStream> OpenBlockingFileStreamFromHandle(AuSPtr<IIOHandle> pIOHandle)
|
||||
AUKN_SYM IFileStream *OpenBlockingFileStreamFromHandleNew(const AuSPtr<IIOHandle> &pIOHandle)
|
||||
{
|
||||
SysCheckArgNotNull(pIOHandle, {});
|
||||
|
||||
auto pStream = AuMakeShared<PosixFileStream>();
|
||||
auto pStream = _new PosixFileStream();
|
||||
SysCheckNotNullMemory(pStream, {});
|
||||
|
||||
if (!AuStaticCast<AFileHandle>(pIOHandle)->pIPCPipe &&
|
||||
AuStaticCast<AFileHandle>(pIOHandle)->ShouldClone())
|
||||
{
|
||||
auto pOld = pIOHandle;
|
||||
pIOHandle = AuMakeShared<AFileHandle>();
|
||||
SysCheckNotNullMemory(pIOHandle, {});
|
||||
if (!pIOHandle->InitFromPair(pOld->GetOSReadHandleSafe(), pOld->GetOSWriteHandle()))
|
||||
auto pIOHandle2 = AuMakeShared<AFileHandle>();
|
||||
SysCheckNotNullMemory(pIOHandle2, {});
|
||||
|
||||
if (!pIOHandle2->InitFromPair(pIOHandle->GetOSReadHandleSafe(), pIOHandle->GetOSWriteHandle()))
|
||||
{
|
||||
SysPushErrorIOResourceFailure();
|
||||
return {};
|
||||
}
|
||||
|
||||
pStream->Init(pIOHandle2);
|
||||
}
|
||||
else
|
||||
{
|
||||
pStream->Init(pIOHandle);
|
||||
}
|
||||
|
||||
pStream->Init(pIOHandle);
|
||||
return pStream;
|
||||
}
|
||||
|
||||
AUKN_SYM void OpenBlockingFileStreamFromHandleRelease(IFileStream *that)
|
||||
{
|
||||
AuSafeDelete<PosixFileStream *>(that);
|
||||
}
|
||||
|
||||
static IFileStream *OpenNewEx(const AuString &path,
|
||||
EFileOpenMode openMode,
|
||||
EFileAdvisoryLockLevel lock,
|
||||
|
@ -42,7 +42,7 @@ namespace Aurora::IO::FS
|
||||
private:
|
||||
AuSPtr<IIOHandle> pHandle_;
|
||||
AuString path_;
|
||||
AuThreadPrimitives::SpinLock spinlock_;
|
||||
AuMutex mutex_;
|
||||
bool bMadeTemporary {}, bShouldWriteEoS {};
|
||||
AuFS::FileReader reader_;
|
||||
AuFS::FileWriter writer_;
|
||||
|
Loading…
Reference in New Issue
Block a user