[+] Add IAsyncTransaction::Reset

[*] Bug fixes: Async.NT.cpp
This commit is contained in:
Reece Wilson 2022-05-05 11:24:44 +01:00
parent 08b9c48f6c
commit dfc21453ef
3 changed files with 78 additions and 22 deletions

View File

@ -45,5 +45,10 @@ namespace Aurora::IO::FS
* Polling the transaction may result in the execution of the callback. * Polling the transaction may result in the execution of the callback.
*/ */
virtual AuSPtr<Loop::ILoopSource> NewLoopSource() = 0; virtual AuSPtr<Loop::ILoopSource> NewLoopSource() = 0;
/**
* @brief Resets ::Complete() and NewLoopSource()->IsSignaled() to false
*/
virtual void Reset() = 0;
}; };
} }

View File

@ -29,7 +29,14 @@ namespace Aurora::IO::FS
bool NtAsyncFileTransactionLoopSource::OnTrigger(AuUInt handle) bool NtAsyncFileTransactionLoopSource::OnTrigger(AuUInt handle)
{ {
return IsSignaled(); auto lock = caller_.lock();
if (lock)
{
return lock->Complete();
}
return true;
} }
Loop::ELoopSource NtAsyncFileTransactionLoopSource::GetType() Loop::ELoopSource NtAsyncFileTransactionLoopSource::GetType()
@ -40,8 +47,17 @@ namespace Aurora::IO::FS
bool NtAsyncFileTransactionLoopSource::IsSignaled() bool NtAsyncFileTransactionLoopSource::IsSignaled()
{ {
auto lock = caller_.lock(); auto lock = caller_.lock();
if (!lock) return LSHandle::IsSignaled();
return lock->Complete(); //if (LSHandle::IsSignaled())
{
if (lock)
{
return lock->Complete();
}
return LSHandle::IsSignaled();
}
return false;
} }
NtAsyncFileTransaction::~NtAsyncFileTransaction() NtAsyncFileTransaction::~NtAsyncFileTransaction()
@ -209,22 +225,17 @@ namespace Aurora::IO::FS
this->overlap_.hEvent = this->event_ = CreateEventW(nullptr, true, false, nullptr); this->overlap_.hEvent = this->event_ = CreateEventW(nullptr, true, false, nullptr);
return this->overlap_.hEvent != INVALID_HANDLE_VALUE; return this->overlap_.hEvent != INVALID_HANDLE_VALUE;
} }
static bool TranslateNtStatus(NtAsyncFileTransaction *that, BOOL val) static bool TranslateNtStatus(NtAsyncFileTransaction *that, BOOL val)
{ {
if ((val) || if ((val) ||
(!val && GetLastError() == ERROR_IO_PENDING)) (!val && (GetLastError() == ERROR_IO_PENDING)))
{ {
if (val)
{
SetEvent(that->event_);
that->DispatchCb(that->lastAbstractStat_);
}
return true; return true;
} }
else else
{ {
that->pin_.reset(); that->pin_.reset();
that->Reset();
SysPushErrorFIO("Async FIO error: {} {}", that->GetFileHandle()->path, GetLastError()); SysPushErrorFIO("Async FIO error: {} {}", that->GetFileHandle()->path, GetLastError());
return false; return false;
} }
@ -237,14 +248,37 @@ namespace Aurora::IO::FS
) )
{ {
auto transaction = reinterpret_cast<NtAsyncFileTransaction *>(reinterpret_cast<AuUInt8*>(lpOverlapped) - offsetof(NtAsyncFileTransaction, overlap_)); auto transaction = reinterpret_cast<NtAsyncFileTransaction *>(reinterpret_cast<AuUInt8*>(lpOverlapped) - offsetof(NtAsyncFileTransaction, overlap_));
transaction->Complete(); auto hold = AuExchange(transaction->pin_, {});
hold->Complete();
}
bool NtAsyncFileTransaction::IDontWannaUsePorts()
{
// TODO: maybe we could use a semaphore counter of read attempts
// to allow APC callbacks to drag behind
if (AuExchange(this->pin_, AuSharedFromThis()))
{
while (SleepEx(100, true) == WAIT_IO_COMPLETION)
{
}
if (AuExchange(this->pin_, AuSharedFromThis()))
{
SysPushErrorUnavailableError();
return {};
}
}
return true;
} }
bool NtAsyncFileTransaction::StartRead(AuUInt64 offset, const AuSPtr<AuMemoryViewWrite> &memoryView) bool NtAsyncFileTransaction::StartRead(AuUInt64 offset, const AuSPtr<AuMemoryViewWrite> &memoryView)
{ {
if (AuExchange(this->pin_, AuSharedFromThis())) if (!IDontWannaUsePorts())
{ {
return {}; return false;
} }
this->latch_ = false; this->latch_ = false;
@ -264,9 +298,9 @@ namespace Aurora::IO::FS
bool NtAsyncFileTransaction::StartWrite(AuUInt64 offset, const AuSPtr<AuMemoryViewRead> &memoryView) bool NtAsyncFileTransaction::StartWrite(AuUInt64 offset, const AuSPtr<AuMemoryViewRead> &memoryView)
{ {
if (AuExchange(this->pin_, AuSharedFromThis())) if (!IDontWannaUsePorts())
{ {
return {}; return false;
} }
this->latch_ = false; this->latch_ = false;
@ -290,28 +324,40 @@ namespace Aurora::IO::FS
return; return;
} }
auto memoryHold = this->memoryHold_;
this->memoryHold_.reset();
if (this->sub_) if (this->sub_)
{ {
this->sub_->OnAsyncFileOpFinished(this->lastAbstractOffset_, read); this->sub_->OnAsyncFileOpFinished(this->lastAbstractOffset_, read);
} }
}
this->memoryHold_.reset(); void NtAsyncFileTransaction::Reset()
{
::ResetEvent(this->event_);
this->lastAbstractStat_ = 0; // do not use latch
} }
bool NtAsyncFileTransaction::Complete() bool NtAsyncFileTransaction::Complete()
{ {
DWORD read; DWORD read;
if (!this->lastAbstractStat_)
{
return false;
}
if (this->latch_) if (this->latch_)
{ {
return true; return false;
} }
if (GetOverlappedResult(this->handle_->handle, &this->overlap_, &read, false)) if (GetOverlappedResult(this->handle_->handle, &this->overlap_, &read, false))
{ {
auto hold = AuExchange(this->pin_, {}); bool bLatched = this->latch_;
hold->DispatchCb(read); DispatchCb(read);
return true; return !bLatched;
} }
return false; return false;

View File

@ -55,6 +55,10 @@ namespace Aurora::IO::FS
bool Wait(AuUInt32 timeout) override; bool Wait(AuUInt32 timeout) override;
AuSPtr<Loop::ILoopSource> NewLoopSource() override; AuSPtr<Loop::ILoopSource> NewLoopSource() override;
void Reset();
bool IDontWannaUsePorts();
void DispatchCb(AuUInt32 len); void DispatchCb(AuUInt32 len);
HANDLE GetHandle(); HANDLE GetHandle();
AuSPtr<FileHandle> GetFileHandle(); AuSPtr<FileHandle> GetFileHandle();
@ -64,10 +68,11 @@ namespace Aurora::IO::FS
HANDLE event_ = INVALID_HANDLE_VALUE; HANDLE event_ = INVALID_HANDLE_VALUE;
AuSPtr<NtAsyncFileTransaction> pin_; AuSPtr<NtAsyncFileTransaction> pin_;
AuUInt32 lastAbstractStat_ {}, lastAbstractOffset_ {}; AuUInt32 lastAbstractStat_ {}, lastAbstractOffset_ {};
bool latch_ {};
private: private:
AuSPtr<void> memoryHold_; AuSPtr<void> memoryHold_;
AuSPtr<FileHandle> handle_; AuSPtr<FileHandle> handle_;
bool latch_ {};
AuSPtr<IAsyncFinishedSubscriber> sub_; AuSPtr<IAsyncFinishedSubscriber> sub_;
}; };
} }