diff --git a/Include/Aurora/IO/Async.hpp b/Include/Aurora/IO/Async.hpp new file mode 100644 index 00000000..7787fb6f --- /dev/null +++ b/Include/Aurora/IO/Async.hpp @@ -0,0 +1,35 @@ +/*** + Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved. + + File: Async.hpp + Date: 2022-5-13 + Author: Reece +***/ +#pragma once + +namespace Aurora::IO +{ + /** + * Waits for at least one overlapped IO event + * @param transactions An array mask of FIO transactions + * @param timeout Timeout in milliseconds, zero = indefinite + */ + AUKN_SYM AuUInt32 WaitMultiple(const AuList> &transactions, AuUInt32 timeoutMs); + + AUKN_SYM AuList> WaitMultiple2(const AuList> &transactions, AuUInt32 timeoutMs); + + /** + * A hint to dispatch any outstanding IO requests. + * + * The Aurora Runtime optimizes file FileRead/Writes by batching on some platforms. + * It may be required to call SendBatched for lower latency immediately after a Read/Write. + * + * Consider any call to WaitMultiple, internal loop source signal state, or loop queue wait, + * an internal hint to request an async IO work-queue flush. + * + * @warning This does nothing on NT + * @warning Linux StartRead/StartWrites will not start immediately. + * They instead wait for a yield or call to SendBatched, unless reconfigured under the RuntimeConfig struct. + */ + AUKN_SYM void SendBatched(); +} \ No newline at end of file diff --git a/Include/Aurora/IO/FS/Async.hpp b/Include/Aurora/IO/FS/Async.hpp index df91c69c..b3f86a6a 100644 --- a/Include/Aurora/IO/FS/Async.hpp +++ b/Include/Aurora/IO/FS/Async.hpp @@ -9,31 +9,9 @@ namespace Aurora::IO::FS { - // WARNING: AURORA::IO::FS ASYNC IS NOT THREAD SAFE // You can use the synchronization objects for the purpose of cross-thread synchronization - // However; IAsyncTransaction should not be accessed from differing threads. + // However, IAsyncTransaction should not be accessed from differing threads. AUKN_SHARED_API(OpenAsync, IAsyncFileStream, const AuString &path, EFileOpenMode openMode, bool directIO = false, EFileAdvisoryLockLevel lock = EFileAdvisoryLockLevel::eNoSafety); - - /** - * Waits for at least one file IO event - * @param transactions An array mask of FIO transactions - * @param timeout Timeout in milliseconds, zero = indefinite - */ - AUKN_SYM AuUInt32 WaitMultiple(const AuList> &transactions, AuUInt32 timeout); - - /** - * A hint to dispatch any outstanding IO requests. - * - * The Aurora Runtime optimizes file FileRead/Writes by batching on some platforms. - * It may be required to call SendBatched for lower latency immediately after a Read/Write. - * - * Consider any call to WaitMultiple, internal loop source signal state, or loop queue wait, - * an internal hint to request an async IO work-queue flush. - * - * @warning This does nothing on NT - * @warning Linux StartRead/StartWrites will not start immediately. They instead wait for a yield or call to SendBatched. - */ - AUKN_SYM void SendBatched(); } \ No newline at end of file diff --git a/Include/Aurora/IO/IO.hpp b/Include/Aurora/IO/IO.hpp index 3988eca5..4516da31 100644 --- a/Include/Aurora/IO/IO.hpp +++ b/Include/Aurora/IO/IO.hpp @@ -17,6 +17,7 @@ #include "IAsyncFinishedSubscriber.hpp" #include "IAsyncTransaction.hpp" +#include "Async.hpp" #include "FS/FS.hpp" #include "Net/Net.hpp" diff --git a/Source/IO/FS/Async.Linux.cpp b/Source/IO/FS/Async.Linux.cpp index ada2684a..dc4bd91e 100644 --- a/Source/IO/FS/Async.Linux.cpp +++ b/Source/IO/FS/Async.Linux.cpp @@ -396,64 +396,4 @@ namespace Aurora::IO::FS { AuSafeDelete(handle); } - - AUKN_SYM AuUInt32 WaitMultiple(const AuList> &files, AuUInt32 timeout) - { - AuCtorCode_t code; - AuUInt32 count {}; - - AuUInt64 endTime = AuTime::CurrentInternalClockMS() + AuUInt64(timeout); - - auto waitQueue = AuTryConstruct>>(code, files); - if (!code) - { - return 0; - } - - while (true) - { - if (waitQueue.empty()) - { - break; - } - - AuUInt32 timeoutMS {}; - - if (timeout) - { - AuInt64 delta = (AuInt64)endTime - AuTime::CurrentInternalClockMS(); - if (delta <= 0) - { - break; - } - timeoutMS = delta; - } - - if (!UNIX::LinuxOverlappedPoll(timeoutMS)) - { - continue; - } - - for (auto itr = waitQueue.begin(); - itr != waitQueue.end();) - { - if (AuStaticPointerCast(*itr)->Complete()) - { - count ++; - itr = waitQueue.erase(itr); - } - else - { - itr++; - } - } - - if (count) - { - break; - } - } - - return count; - } } \ No newline at end of file diff --git a/Source/IO/FS/Async.NT.cpp b/Source/IO/FS/Async.NT.cpp index bf1ae64b..755710ce 100644 --- a/Source/IO/FS/Async.NT.cpp +++ b/Source/IO/FS/Async.NT.cpp @@ -438,34 +438,4 @@ namespace Aurora::IO::FS { AuSafeDelete(handle); } - - AUKN_SYM AuUInt32 WaitMultiple(const AuList> &files, AuUInt32 timeout) - { - AuList handles; - AuUInt32 count {}; - - if (files.empty()) - { - return true; - } - - for (const auto & file : files) - { - handles.push_back(AuStaticPointerCast(file)->GetHandle()); - } - - auto ret = WaitForMultipleObjectsEx(handles.size(), handles.data(), false, timeout ? timeout : INFINITE, TRUE); - - if (ret == WAIT_TIMEOUT || ret == WAIT_FAILED) - { - return false; - } - - for (auto &file : files) - { - count += AuStaticPointerCast(file)->Complete(); - } - - return count; - } } \ No newline at end of file diff --git a/Source/IO/IO.cpp b/Source/IO/IO.cpp index 1ec4a92a..0ab055ea 100755 --- a/Source/IO/IO.cpp +++ b/Source/IO/IO.cpp @@ -31,11 +31,4 @@ namespace Aurora::IO UNIX::DeinitUnixIO(); #endif } - - AUKN_SYM void SendBatched() - { - #if defined(AURORA_IS_LINUX_DERIVED) - UNIX::SendIOBuffers(); - #endif - } } \ No newline at end of file diff --git a/Source/IO/WaitMultiple.Linux.cpp b/Source/IO/WaitMultiple.Linux.cpp new file mode 100644 index 00000000..6228d247 --- /dev/null +++ b/Source/IO/WaitMultiple.Linux.cpp @@ -0,0 +1,142 @@ +/*** + Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved. + + File: WaitMultiple.Linux.cpp + Date: 2022-5-13 + Author: Reece +***/ +#include +#include "IO.hpp" +#include "WaitMultiple.Linux.hpp" +#include "FS/Async.Linux.hpp" +#include "UNIX/IOSubmit.Linux.hpp" + +namespace Aurora::IO +{ + AUKN_SYM AuUInt32 WaitMultiple(const AuList> &files, AuUInt32 timeout) + { + AuCtorCode_t code; + AuUInt32 count {}; + + AuUInt64 endTime = AuTime::CurrentInternalClockMS() + AuUInt64(timeout); + + auto waitQueue = AuTryConstruct>>(code, files); + if (!code) + { + return 0; + } + + while (true) + { + if (waitQueue.empty()) + { + break; + } + + AuUInt32 timeoutMS {}; + + if (timeout) + { + AuInt64 delta = (AuInt64)endTime - AuTime::CurrentInternalClockMS(); + if (delta <= 0) + { + break; + } + timeoutMS = delta; + } + + if (!UNIX::LinuxOverlappedPoll(timeoutMS)) + { + continue; + } + + for (auto itr = waitQueue.begin(); + itr != waitQueue.end();) + { + if (AuStaticPointerCast(*itr)->Complete()) + { + count ++; + itr = waitQueue.erase(itr); + } + else + { + itr++; + } + } + + if (count) + { + break; + } + } + + return count; + } + + AUKN_SYM AuList> WaitMultiple2(const AuList> &transactions, AuUInt32 requestedTimeoutMs) + { + AuCtorCode_t code; + AuList> retTransactions; + + AuUInt64 endTime = AuTime::CurrentInternalClockMS() + AuUInt64(requestedTimeoutMs); + + auto waitQueue = AuTryConstruct>>(code, transactions); + if (!code) + { + return 0; + } + + while (true) + { + if (waitQueue.empty()) + { + break; + } + + AuUInt32 timeoutMS {}; + + if (requestedTimeoutMs) + { + AuInt64 delta = (AuInt64)endTime - AuTime::CurrentInternalClockMS(); + if (delta <= 0) + { + break; + } + timeoutMS = delta; + } + + if (!UNIX::LinuxOverlappedPoll(timeoutMS)) + { + continue; + } + + for (auto itr = waitQueue.begin(); + itr != waitQueue.end();) + { + if (AuStaticPointerCast(*itr)->Complete()) + { + AuTryInsert(retTransactions, *itr); + itr = waitQueue.erase(itr); + } + else + { + itr++; + } + } + + if (retTransactions.size()) + { + break; + } + } + + return retTransactions; + } + + AUKN_SYM void SendBatched() + { + #if defined(AURORA_IS_LINUX_DERIVED) + UNIX::SendIOBuffers(); + #endif + } +} \ No newline at end of file diff --git a/Source/IO/WaitMultiple.Linux.hpp b/Source/IO/WaitMultiple.Linux.hpp new file mode 100644 index 00000000..cfed8b80 --- /dev/null +++ b/Source/IO/WaitMultiple.Linux.hpp @@ -0,0 +1,13 @@ +/*** + Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved. + + File: WaitMultiple.Linux.hpp + Date: 2022-5-13 + Author: Reece +***/ +#pragma once + +namespace Aurora::IO +{ + +} \ No newline at end of file diff --git a/Source/IO/WaitMultiple.NT.cpp b/Source/IO/WaitMultiple.NT.cpp new file mode 100644 index 00000000..f7df66a2 --- /dev/null +++ b/Source/IO/WaitMultiple.NT.cpp @@ -0,0 +1,85 @@ +/*** + Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved. + + File: WaitMultiple.NT.cpp + Date: 2022-5-13 + Author: Reece +***/ +#include +#include "IO.hpp" +#include "WaitMultiple.NT.hpp" +#include "FS/Async.NT.hpp" + +namespace Aurora::IO +{ + AUKN_SYM AuUInt32 WaitMultiple(const AuList> &files, AuUInt32 timeout) + { + AuList handles; + AuUInt32 count {}; + + if (files.empty()) + { + return 0; + } + + for (const auto &file : files) + { + AuTryInsert(handles, AuStaticPointerCast(file)->GetHandle()); + } + + auto ret = WaitForMultipleObjectsEx(handles.size(), handles.data(), false, timeout ? timeout : INFINITE, TRUE); + + if (ret == WAIT_TIMEOUT || ret == WAIT_FAILED) + { + return 0; + } + + for (auto &file : files) + { + count += AuStaticPointerCast(file)->Complete(); + } + + return count; + } + + AUKN_SYM AuList> WaitMultiple2(const AuList> &transactions, AuUInt32 timeoutMs) + { + AuList> retTransasctions; + AuList handles; + AuUInt32 count {}; + + if (transactions.empty()) + { + return {}; + } + + retTransasctions.reserve(transactions.size()); + + for (const auto &file : transactions) + { + AuTryInsert(handles, AuStaticPointerCast(file)->GetHandle()); + } + + auto ret = WaitForMultipleObjectsEx(handles.size(), handles.data(), false, timeoutMs ? timeoutMs : INFINITE, TRUE); + + if (ret == WAIT_TIMEOUT || ret == WAIT_FAILED) + { + return {}; + } + + for (auto &file : transactions) + { + if (AuStaticPointerCast(file)->Complete()) + { + AuTryInsert(retTransasctions, file); + } + } + + return retTransasctions; + } + + AUKN_SYM void SendBatched() + { + + } +} \ No newline at end of file diff --git a/Source/IO/WaitMultiple.NT.hpp b/Source/IO/WaitMultiple.NT.hpp new file mode 100644 index 00000000..30aa0e06 --- /dev/null +++ b/Source/IO/WaitMultiple.NT.hpp @@ -0,0 +1,13 @@ +/*** + Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved. + + File: WaitMultiple.NT.hpp + Date: 2022-5-13 + Author: Reece +***/ +#pragma once + +namespace Aurora::IO +{ + +} \ No newline at end of file