diff --git a/Include/Aurora/Runtime.hpp b/Include/Aurora/Runtime.hpp index 7eef62c0..02219734 100644 --- a/Include/Aurora/Runtime.hpp +++ b/Include/Aurora/Runtime.hpp @@ -113,7 +113,11 @@ namespace Aurora /** * @brief Single threaded main pump for GUI applications polling for non-async subsystem callbacks + * (primarily legacy command dispatch) + * @deprecated * @return */ AUKN_SYM void RuntimeSysPump(); + + AUKN_SYM void RuntimeWaitForSecondaryTick(); } \ No newline at end of file diff --git a/Source/AuRTEntrypoint.cpp b/Source/AuRTEntrypoint.cpp index e3316517..50b843a7 100644 --- a/Source/AuRTEntrypoint.cpp +++ b/Source/AuRTEntrypoint.cpp @@ -233,6 +233,11 @@ namespace Aurora Pump(); } + AUKN_SYM void RuntimeWaitForSecondaryTick() + { + Grug::WaitForGrugTick(); + } + void RuntimeLateClean() { ::RuntimeLateClean(); diff --git a/Source/Grug/AuGrug.cpp b/Source/Grug/AuGrug.cpp index d7c16f8b..d2fdf5d7 100644 --- a/Source/Grug/AuGrug.cpp +++ b/Source/Grug/AuGrug.cpp @@ -30,12 +30,13 @@ namespace Aurora::Grug static const auto kGrugSleepMs = 100; static const auto kGrugFlushMs = 500; - static AuThreads::ThreadUnique_t gGrugsBigWorld; - static AuCondMutex gMutex; // ^ that - static AuConditionVariable gCondVar(AuUnsafeRaiiToShared(gMutex.AsPointer())); // slow logger work queue - static AuSemaphore gArrows; - static AuMutex gOtherMutex; - static AuList gHandlesToClose; + static AuThreads::ThreadUnique_t gGrugsBigWorld; + static AuCondMutex gMutex; // ^ that + static AuConditionVariable gCondVar(AuUnsafeRaiiToShared(gMutex.AsPointer())); // slow logger work queue + static AuSemaphore gArrows; + static AuMutex gOtherMutex; + static AuList gHandlesToClose; + static AuList gEventsToTrigger; static void SlowStartupTasks() { @@ -194,13 +195,22 @@ namespace Aurora::Grug void GrugDoIoWork() { - if (gHandlesToClose.empty()) + decltype(gHandlesToClose) toClose; + decltype(gEventsToTrigger) toTrigger; + + if (gHandlesToClose.empty() && + gEventsToTrigger.empty()) { return; } - AU_LOCK_GUARD(gOtherMutex); - for (const auto uHandle : AuExchange(gHandlesToClose, {})) + { + AU_LOCK_GUARD(gOtherMutex); + toClose = AuMove(gHandlesToClose); + toTrigger = AuMove(gEventsToTrigger); + } + + for (const auto uHandle : toClose) { #if defined(AURORA_IS_MODERNNT_DERIVED) auto pHandle = (void *)uHandle; @@ -209,6 +219,11 @@ namespace Aurora::Grug close(uHandle); #endif } + + for (const auto pEvent : toTrigger) + { + pEvent->Set(); + } } void GrugFlushFlushs() @@ -229,4 +244,27 @@ namespace Aurora::Grug NotifyGrugOfTelemetry(); } + + void WaitForGrugTick() + { + AuEvent event(false, true, true); + + if (gGrugsBigWorld && + gGrugsBigWorld.get() == AuThreads::GetThread()) + { + return; + } + + { + AU_DEBUG_MEMCRUNCH; + AU_LOCK_GUARD(gOtherMutex); + gEventsToTrigger.push_back(event.AsPointer()); + } + + { + NotifyGrugOfTelemetry(); + } + + event->Lock(); + } } \ No newline at end of file diff --git a/Source/Grug/AuGrug.hpp b/Source/Grug/AuGrug.hpp index 929859fb..3a767e1f 100644 --- a/Source/Grug/AuGrug.hpp +++ b/Source/Grug/AuGrug.hpp @@ -25,4 +25,5 @@ namespace Aurora::Grug void DeinitGrug(); void CloseHandle(AuUInt64 handle); + void WaitForGrugTick(); } \ No newline at end of file diff --git a/Source/IO/AuIOHandle.NT.cpp b/Source/IO/AuIOHandle.NT.cpp index 690790a8..763cb948 100644 --- a/Source/IO/AuIOHandle.NT.cpp +++ b/Source/IO/AuIOHandle.NT.cpp @@ -158,144 +158,158 @@ namespace Aurora::IO dwAttrs |= FILE_ATTRIBUTE_NORMAL; } - switch (create.eMode) + for (AU_ITERATE_N(i, 2)) { - case FS::EFileOpenMode::eRead: - { - hFileHandle = Win32Open(win32Path.c_str(), - GENERIC_READ, - dwShare, - false, - OPEN_EXISTING, - dwFlags, - dwAttrs); - - if (hFileHandle != INVALID_HANDLE_VALUE) + switch (create.eMode) { - this->uOSReadHandle = AuUInt64(hFileHandle); - } - - break; - } - case FS::EFileOpenMode::eReadWrite: - { - if (create.bAlwaysCreateDirTree) - { - FS::CreateDirectories(pathex, true); - } - - if (create.bFailIfNonEmptyFile) + case FS::EFileOpenMode::eRead: { hFileHandle = Win32Open(win32Path.c_str(), - GENERIC_WRITE | GENERIC_READ | DELETE, - false, - false, - CREATE_NEW, - dwFlags, - dwAttrs); - - if (hFileHandle == INVALID_HANDLE_VALUE) - { - if (GetLastError() == ERROR_FILE_EXISTS || - AuFS::FileExists(pathex.c_str())) - { - SysPushErrorResourceExists("File {} already exists", create.path); - return false; - } - } - } - else - { - hFileHandle = Win32Open(win32Path.c_str(), - GENERIC_WRITE | GENERIC_READ | DELETE, + GENERIC_READ, dwShare, false, OPEN_EXISTING, dwFlags, dwAttrs); - if (hFileHandle == INVALID_HANDLE_VALUE) + if (hFileHandle != INVALID_HANDLE_VALUE) + { + this->uOSReadHandle = AuUInt64(hFileHandle); + } + + break; + } + case FS::EFileOpenMode::eReadWrite: + { + if (create.bAlwaysCreateDirTree) + { + FS::CreateDirectories(pathex, true); + } + + if (create.bFailIfNonEmptyFile) + { + hFileHandle = Win32Open(win32Path.c_str(), + GENERIC_WRITE | GENERIC_READ | DELETE, + false, + false, + CREATE_NEW, + dwFlags, + dwAttrs); + + if (hFileHandle == INVALID_HANDLE_VALUE) + { + if (GetLastError() == ERROR_FILE_EXISTS || + AuFS::FileExists(pathex.c_str())) + { + SysPushErrorResourceExists("File {} already exists", create.path); + return false; + } + } + } + else { hFileHandle = Win32Open(win32Path.c_str(), GENERIC_WRITE | GENERIC_READ | DELETE, dwShare, false, - CREATE_NEW, + OPEN_EXISTING, dwFlags, dwAttrs); - } - } - if (hFileHandle != INVALID_HANDLE_VALUE) - { - this->uOSReadHandle = AuUInt64(hFileHandle); - this->uOSWriteHandle = AuUInt64(hFileHandle); - } - - break; - } - case FS::EFileOpenMode::eWrite: - { - if (create.bAlwaysCreateDirTree) - { - FS::CreateDirectories(pathex, true); - } - - if (create.bFailIfNonEmptyFile) - { - hFileHandle = Win32Open(win32Path.c_str(), - GENERIC_WRITE | DELETE, - NULL, - false, - CREATE_NEW, - dwFlags, - dwAttrs); - - if (hFileHandle == INVALID_HANDLE_VALUE) - { - if (GetLastError() == ERROR_FILE_EXISTS || - AuFS::FileExists(pathex.c_str())) + if (hFileHandle == INVALID_HANDLE_VALUE) { - SysPushErrorResourceExists("File {} already exists", create.path); - return false; + hFileHandle = Win32Open(win32Path.c_str(), + GENERIC_WRITE | GENERIC_READ | DELETE, + dwShare, + false, + CREATE_NEW, + dwFlags, + dwAttrs); } } - } - else - { - hFileHandle = Win32Open(win32Path.c_str(), - GENERIC_WRITE | FILE_READ_ATTRIBUTES | DELETE, - dwShare, - false, - OPEN_EXISTING, - dwFlags, - dwAttrs); - if (hFileHandle == INVALID_HANDLE_VALUE) + if (hFileHandle != INVALID_HANDLE_VALUE) + { + this->uOSReadHandle = AuUInt64(hFileHandle); + this->uOSWriteHandle = AuUInt64(hFileHandle); + } + + break; + } + case FS::EFileOpenMode::eWrite: + { + if (create.bAlwaysCreateDirTree) + { + FS::CreateDirectories(pathex, true); + } + + if (create.bFailIfNonEmptyFile) { hFileHandle = Win32Open(win32Path.c_str(), GENERIC_WRITE | DELETE, - dwShare, + NULL, false, CREATE_NEW, dwFlags, dwAttrs); + + if (hFileHandle == INVALID_HANDLE_VALUE) + { + if (GetLastError() == ERROR_FILE_EXISTS || + AuFS::FileExists(pathex.c_str())) + { + SysPushErrorResourceExists("File {} already exists", create.path); + return false; + } + } + } + else + { + hFileHandle = Win32Open(win32Path.c_str(), + GENERIC_WRITE | FILE_READ_ATTRIBUTES | DELETE, + dwShare, + false, + OPEN_EXISTING, + dwFlags, + dwAttrs); + + if (hFileHandle == INVALID_HANDLE_VALUE) + { + hFileHandle = Win32Open(win32Path.c_str(), + GENERIC_WRITE | DELETE, + dwShare, + false, + CREATE_NEW, + dwFlags, + dwAttrs); + } + } + + if (hFileHandle != INVALID_HANDLE_VALUE) + { + this->uOSWriteHandle = AuUInt64(hFileHandle); + } + + break; + } + } + + if (hFileHandle == INVALID_HANDLE_VALUE) + { + if (i == 0) + { + RuntimeWaitForSecondaryTick(); + } + else + { + SysPushErrorIO("Couldn't open: {}", create.path); + return false; } } - - if (hFileHandle != INVALID_HANDLE_VALUE) + else { - this->uOSWriteHandle = AuUInt64(hFileHandle); + break; } - - break; - } - } - - if (hFileHandle == INVALID_HANDLE_VALUE) - { - SysPushErrorIO("Couldn't open: {}", create.path); - return false; } this->bIsAsync = create.bAsyncHandle; diff --git a/Source/IO/AuIOHandle.Unix.cpp b/Source/IO/AuIOHandle.Unix.cpp index 6fd47ae5..25f41cd9 100644 --- a/Source/IO/AuIOHandle.Unix.cpp +++ b/Source/IO/AuIOHandle.Unix.cpp @@ -13,6 +13,8 @@ #include "FS/FileAdvisory.Unix.hpp" #include "FS/FileStream.Unix.hpp" +#include + #include #include #include @@ -91,7 +93,11 @@ namespace Aurora::IO return; } + #if 0 ::close(fd); + #else + Grug::CloseHandle(uOSHandle); + #endif } void AFileHandle::InitStdIn(bool bSharing) @@ -183,30 +189,52 @@ namespace Aurora::IO if (iFileDescriptor < 0) { - if (errno == EEXIST) + if (create.bFailIfNonEmptyFile) { - SysPushErrorResourceExists("File {} already exists", create.path); - return false; + if (errno == EEXIST) + { + SysPushErrorResourceExists("File {} already exists", create.path); + return false; + } } - if (errno == EISDIR) + if (errno != EISDIR && + errno != ENOENT) { - flags &= ~(O_WRONLY | O_RDWR); + RuntimeWaitForSecondaryTick(); + iFileDescriptor = ::open(pathex.c_str(), flags, 0664); } - if (errno == ENFILE) - { - SysPushErrorIOResourceFailure("low resources"); - return false; - } - if (iFileDescriptor < 0) { - SysPushErrorIO("Couldn't open file: {} ({}) {}", path, pathex, errno); - return false; + if (errno == EEXIST) + { + SysPushErrorResourceExists("File {} already exists", create.path); + return false; + } + + if (errno == EISDIR) + { + flags &= ~(O_WRONLY | O_RDWR); + iFileDescriptor = ::open(pathex.c_str(), + flags, + 0664); + } + + if (iFileDescriptor < 0) + { + if (errno == ENFILE) + { + SysPushErrorIOResourceFailure("low resources"); + return false; + } + + SysPushErrorIO("Couldn't open file: {} ({}) {}", path, pathex, errno); + return false; + } } }