[+] Add IAsyncTransaction::Reset
[*] Bug fixes: Async.NT.cpp
This commit is contained in:
parent
08b9c48f6c
commit
dfc21453ef
@ -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;
|
||||||
};
|
};
|
||||||
}
|
}
|
@ -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;
|
||||||
|
@ -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_;
|
||||||
};
|
};
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user