#pragma once namespace Aurora::IO::Net { struct NetSrvWorkers; struct NetWorker : INetWorker { NetWorker(NetSrvWorkers *pParent, AuUInt8 workerIndex, AuSPtr pIOProcessor); AuSPtr ToEvent(); bool IsOnThread(); AuSPtr ToProcessor() override; AuUInt8 GetWorkerIndex() override; void Destroy() override; bool IncrementIOEventTaskCounter(); void DecrementIOEventTaskCounter(); AuSPtr pWorkItem_; void AddSocket(ISocket *pSocket); void RemoveSocket(ISocket *pSocket); AuList childSockets; // Yea, so, we have some pretty lax rules about threading... template bool TryScheduleInternalTemplate(Callable_t &&work, const AuSPtr> &callback) { struct Waiter : IIOProcessorWorkUnit { inline Waiter(const AuConsumer> &> worker, const AuSPtr> &callbacks) : callbacks_(callbacks), worker_(worker) { } inline Waiter(const AuConsumer> &> worker, const AuSPtr> &callbacks, AuAsync::WorkerPId_t origin) : callbacks_(callbacks), worker_(worker), origin_(origin) { SysAssert(MakeProxy()); } inline virtual void OnRun() override { //SysAssert(this->callbacks_); SysAssert(this->worker_); this->worker_(this->callbacks_); } inline virtual void OnCanceled() override { if (!this->callbacks_) { return; } //SysAssert(this->callbacks_); this->callbacks_->OnFailure((void *)nullptr); } inline bool MakeProxy() { auto old = this->callbacks_; auto temp = AuMakeShared>([=](const AuSPtr &response) { auto pWorkItem = this->origin_.pool->NewWorkItem(this->origin_, AuMakeShared([response, callbacks = old]() { callbacks->OnSuccess(response.get()); }, []() { SysPanic("Eh"); })); SysAssert(pWorkItem); SysAssert(pWorkItem->Dispatch(), "A network task failed to dispatch critically"); }, [=](const AuSPtr &response) { auto pWorkItem = this->origin_.pool->NewWorkItem(this->origin_, AuMakeShared([response, callbacks = old]() { callbacks->OnFailure(response.get()); }, []() { SysPanic("Eh"); })); SysAssert(pWorkItem); SysAssert(pWorkItem->Dispatch(), "A network task failed to dispatch critically"); }); if (!temp) { return {}; } this->callbacks_ = temp; return true; } const AuConsumer> &> worker_; AuSPtr> callbacks_; AuAsync::WorkerPId_t origin_; }; AuSPtr temp; auto pid = AuAsync::GetCurrentWorkerPId(); if (pid) { temp = AuMakeShared(work, callback, pid); } else { temp = AuMakeShared(work, callback); } if (!temp) { SysPushErrorIO("No memory to allocate work unit"); return false; } return this->pIOProcessor_->SubmitIOWorkItem(temp); } private: AuThreadPrimitives::SpinLock spinLock_; AuSPtr pIOProcessor_; NetSrvWorkers *pParent_; AuUInt8 workerIndex_; AuSPtr pEvent_; AuUInt32 dwAtomicEventCounter_ {}; }; }