#pragma once //#define WIN32_LEAN_AND_MEAN #include #include #include #include namespace LdH::Asyncio { #if 0 template class lambda_t> concept OverlappedFunc = std::invocable, LPOVERLAPPED, LPOVERLAPPED_COMPLETION_ROUTINE> && std::same_as, LPOVERLAPPED, LPOVERLAPPED_COMPLETION_ROUTINE>, ret_t>; #endif template concept OverlappedFunc = std::invocable && std::same_as, DWORD>; class WindowsOverlappedEventloop { private: static thread_local struct _running_loop_variable_t { private: WindowsOverlappedEventloop *_value; public: [[nodiscard]] WindowsOverlappedEventloop *get() { auto cached = this->_value; if (cached == nullptr) throw LdH::Exception{"No running loop"}; return cached; } [[nodiscard]] WindowsOverlappedEventloop *getOrNull() { return this->_value; } void set(WindowsOverlappedEventloop *v) { if (this->_value != nullptr && v != nullptr) throw LdH::Exception{"Recursive loops not allowed"}; this->_value = v; } } _running_loop; struct FiberMetadata { public: OVERLAPPED overlapped; void *fiber_id; FiberMetadata *next_existing; FiberMetadata *prev_existing; FiberMetadata *next_active; FiberMetadata *prev_active; DWORD err_code; DWORD read_count; }; HANDLE const notifier; bool const need_rollback_to_thread; void *const master_fiber; bool interrupted; FiberMetadata *next_existing; FiberMetadata *next_active; DWORD const fls_fiber_metadata; void *fiber_to_destroy; public: WindowsOverlappedEventloop(); ~WindowsOverlappedEventloop(); private: [[nodiscard]] HANDLE createEvent() const; [[nodiscard]] HANDLE prepareFibers() const; [[nodiscard]] DWORD allocFls() const; public: void runUntilHasTasksAndNotInterrupted(); private: void _addTask(void (*routine)(void *), void *arg); static void _overlapped_completion_routine(DWORD dwErrorCode, DWORD dwNumberOfBytesTransfered, FiberMetadata *lpOverlapped); public: template static void addTaskToRuningLoop(void (*routine)(T *), T *arg) { WindowsOverlappedEventloop::_running_loop.get()->_addTask( reinterpret_cast(routine), reinterpret_cast(arg) ); } template void addTask(void (*routine)(T *), T *arg) { this->_addTask( reinterpret_cast(routine), reinterpret_cast(arg) ); } static DWORD overlappedCall(OverlappedFunc auto func) { auto loop = WindowsOverlappedEventloop::_running_loop.get(); auto metadata = reinterpret_cast(FlsGetValue(loop->fls_fiber_metadata)); if (metadata == nullptr) LdH::Exception::throwFromLastWindowsErr(); DWORD read_count = func(reinterpret_cast(metadata), reinterpret_cast(&WindowsOverlappedEventloop::_overlapped_completion_routine)); if (read_count != 0) return read_count; if (loop->next_active == metadata) loop->next_active = metadata->next_active; if (metadata->next_active != nullptr) metadata->next_active->prev_active = metadata->prev_active; if (metadata->prev_active != nullptr) metadata->prev_active->next_active = metadata->next_active; metadata->next_active = nullptr; metadata->prev_active = nullptr; SwitchToFiber(loop->master_fiber); if (metadata->err_code != ERROR_SUCCESS) LdH::Exception::throwFromWindowsErrCode(metadata->err_code); return metadata->read_count; } static void interruptEventLoop() { WindowsOverlappedEventloop::_running_loop.get()->interrupted = true; } private: struct FiberInitializer { WindowsOverlappedEventloop *loop; void (*routine)(void *); void *routine_arg; void *caller_fiber; }; static void fiber_kernel(FiberInitializer *init); }; }