[*] Added a few notes in the Async.hpp header
[+] Ensure dead locks can not occur
This commit is contained in:
parent
d3a97257da
commit
2c5a492f08
@ -19,7 +19,16 @@ namespace Aurora::Async
|
|||||||
using ThreadGroup_t = AuUInt8;
|
using ThreadGroup_t = AuUInt8;
|
||||||
using ThreadId_t = AuUInt16;
|
using ThreadId_t = AuUInt16;
|
||||||
|
|
||||||
|
/// ThreadGroup_t:
|
||||||
|
/// 0 = system main thread
|
||||||
|
/// 1+ = user defined
|
||||||
|
///
|
||||||
|
/// ThreadId_t:
|
||||||
|
/// 0 = invalid
|
||||||
|
/// index+1 = tid/runner id
|
||||||
|
///
|
||||||
using WorkerId_t = AuPair<ThreadGroup_t, ThreadId_t>;
|
using WorkerId_t = AuPair<ThreadGroup_t, ThreadId_t>;
|
||||||
|
|
||||||
using DispatchTarget_t = AuPair<ThreadGroup_t, AuOptional<ThreadId_t>>;
|
using DispatchTarget_t = AuPair<ThreadGroup_t, AuOptional<ThreadId_t>>;
|
||||||
|
|
||||||
struct WorkPriv
|
struct WorkPriv
|
||||||
@ -65,25 +74,26 @@ namespace Aurora::Async
|
|||||||
};
|
};
|
||||||
|
|
||||||
template<class Info_t = AVoid, class Result_t = AVoid>
|
template<class Info_t = AVoid, class Result_t = AVoid>
|
||||||
static inline FJob<Info_t, Result_t> JobFromConsumer(const AuConsumer<const Result_t &> &onSuccess)
|
static inline FJob<Info_t, Result_t> JobFromConsumer(const AuConsumer<const Info_t &, const Result_t &> &onSuccess)
|
||||||
{
|
{
|
||||||
FJob<Info_t, Result_t> ret;
|
FJob<Info_t, Result_t> ret;
|
||||||
ret.onSuccess = [=](const Info_t &in, const Result_t &a)
|
ret.onSuccess = [=](const Info_t &in, const Result_t &a)
|
||||||
{
|
{
|
||||||
onSuccess(a);
|
onSuccess(in, a);
|
||||||
};
|
};
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Info_t = AVoid, class Result_t = AVoid>
|
template<class Info_t = AVoid, class Result_t = AVoid>
|
||||||
static inline FJob<Info_t, Result_t> JobFromConsumer(const AuConsumer<const Result_t &> &onSuccess, const AuConsumer<const Result_t &, bool/*neverDispatched*/> &onFailure)
|
static inline FJob<Info_t, Result_t> JobFromConsumer(const AuConsumer<const Info_t &, const Result_t &> &onSuccess, const AuConsumer<const Info_t &, bool/*neverDispatched*/> &onFailure)
|
||||||
|
|
||||||
{
|
{
|
||||||
FJob<Info_t, Result_t> ret;
|
FJob<Info_t, Result_t> ret;
|
||||||
ret.onSuccess = [=](const Info_t &in, const Result_t &a)
|
ret.onSuccess = [=](const Info_t &in, const Result_t &a)
|
||||||
{
|
{
|
||||||
onSuccess(a);
|
onSuccess(in, a);
|
||||||
};
|
};
|
||||||
ret.onFailure = [=](const Result_t &a, bool neverDispatched)
|
ret.onFailure = [=](const Info_t &a, bool neverDispatched)
|
||||||
{
|
{
|
||||||
onFailure(a, neverDispatched);
|
onFailure(a, neverDispatched);
|
||||||
};
|
};
|
||||||
@ -91,14 +101,15 @@ namespace Aurora::Async
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<class Info_t = AVoid, class Result_t = AVoid>
|
template<class Info_t = AVoid, class Result_t = AVoid>
|
||||||
static inline FJob<Info_t, Result_t> JobFromConsumer(const AuConsumer<const Result_t &> &onSuccess, const AuConsumer<const Result_t &> &onFailure)
|
static inline FJob<Info_t, Result_t> JobFromConsumer(const AuConsumer<const Info_t &, const Result_t &> &onSuccess, const AuConsumer<const Info_t &> &onFailure)
|
||||||
|
|
||||||
{
|
{
|
||||||
FJob<Info_t, Result_t> ret;
|
FJob<Info_t, Result_t> ret;
|
||||||
ret.onSuccess = [=](const Info_t &in, const Result_t &a)
|
ret.onSuccess = [=](const Info_t &in, const Result_t &a)
|
||||||
{
|
{
|
||||||
onSuccess(a);
|
onSuccess(in, a);
|
||||||
};
|
};
|
||||||
ret.onFailure = [=](const Result_t &a, bool neverDispatched)
|
ret.onFailure = [=](const Info_t &a, bool neverDispatched)
|
||||||
{
|
{
|
||||||
onFailure(a);
|
onFailure(a);
|
||||||
};
|
};
|
||||||
@ -107,7 +118,6 @@ namespace Aurora::Async
|
|||||||
|
|
||||||
using FVoidJob = FJob<AVoid, AVoid>;
|
using FVoidJob = FJob<AVoid, AVoid>;
|
||||||
|
|
||||||
|
|
||||||
template<class Info_t = AVoid, class Result_t = AVoid>
|
template<class Info_t = AVoid, class Result_t = AVoid>
|
||||||
struct CJob
|
struct CJob
|
||||||
{
|
{
|
||||||
@ -191,6 +201,7 @@ namespace Aurora::Async
|
|||||||
|
|
||||||
AUKN_SYM AuSPtr<IWorkItem> NewWorkItem(const DispatchTarget_t &worker, const AuSPtr<IWorkItemHandler> &task, bool supportsBlocking = false);
|
AUKN_SYM AuSPtr<IWorkItem> NewWorkItem(const DispatchTarget_t &worker, const AuSPtr<IWorkItemHandler> &task, bool supportsBlocking = false);
|
||||||
|
|
||||||
|
#pragma region EASE_OF_READING
|
||||||
struct BasicWorkStdFunc : IWorkItemHandler
|
struct BasicWorkStdFunc : IWorkItemHandler
|
||||||
{
|
{
|
||||||
std::function<void()> callback;
|
std::function<void()> callback;
|
||||||
@ -240,7 +251,6 @@ namespace Aurora::Async
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#if !defined(_CPPSHARP)
|
#if !defined(_CPPSHARP)
|
||||||
/// @hideinitializer
|
/// @hideinitializer
|
||||||
struct BasicWorkCtx : WorkPriv
|
struct BasicWorkCtx : WorkPriv
|
||||||
@ -517,6 +527,8 @@ namespace Aurora::Async
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#pragma endregion EASE_OF_READING
|
||||||
|
|
||||||
template<typename Info_t = AVoid, typename Result_t = AVoid, typename Task_t = FTask<Info_t, Result_t>, typename Job_t = FJob<Info_t, Result_t>>
|
template<typename Info_t = AVoid, typename Result_t = AVoid, typename Task_t = FTask<Info_t, Result_t>, typename Job_t = FJob<Info_t, Result_t>>
|
||||||
static AuSPtr<Async::IWorkItem> DispatchBasicWorkCallback(const DispatchTarget_t &worker, const Task_t &task, const Job_t &job, bool enableWait = false)
|
static AuSPtr<Async::IWorkItem> DispatchBasicWorkCallback(const DispatchTarget_t &worker, const Task_t &task, const Job_t &job, bool enableWait = false)
|
||||||
{
|
{
|
||||||
@ -529,7 +541,6 @@ namespace Aurora::Async
|
|||||||
return Async::NewWorkItem(worker, AuMakeShared<Async::BasicWorkCallback<Info_t, Result_t>>(task, job, inputParameters), enableWait)->Dispatch();
|
return Async::NewWorkItem(worker, AuMakeShared<Async::BasicWorkCallback<Info_t, Result_t>>(task, job, inputParameters), enableWait)->Dispatch();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class IAsyncApp
|
class IAsyncApp
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -547,6 +558,7 @@ namespace Aurora::Async
|
|||||||
virtual WorkerId_t GetCurrentThread() = 0;
|
virtual WorkerId_t GetCurrentThread() = 0;
|
||||||
|
|
||||||
// Synchronization
|
// Synchronization
|
||||||
|
// Note: syncing to yourself will nullify requireSignal to prevent deadlock
|
||||||
virtual bool Sync(ThreadGroup_t group, bool requireSignal = false, AuUInt32 timeout = 0) = 0;
|
virtual bool Sync(ThreadGroup_t group, bool requireSignal = false, AuUInt32 timeout = 0) = 0;
|
||||||
virtual void Signal(ThreadGroup_t group) = 0;
|
virtual void Signal(ThreadGroup_t group) = 0;
|
||||||
|
|
||||||
|
@ -585,11 +585,14 @@ namespace Aurora::Async
|
|||||||
bool AsyncApp::Sync(ThreadGroup_t groupId, bool requireSignal, AuUInt32 timeoutMs)
|
bool AsyncApp::Sync(ThreadGroup_t groupId, bool requireSignal, AuUInt32 timeoutMs)
|
||||||
{
|
{
|
||||||
AU_LOCK_GUARD(rwlock_->AsReadable());
|
AU_LOCK_GUARD(rwlock_->AsReadable());
|
||||||
|
|
||||||
auto group = GetGroup(groupId);
|
auto group = GetGroup(groupId);
|
||||||
|
|
||||||
|
auto currentWorkerId = GetCurrentThread().second;
|
||||||
|
|
||||||
for (auto &jobWorker : group->workers)
|
for (auto &jobWorker : group->workers)
|
||||||
{
|
{
|
||||||
if (!Barrier(jobWorker.second->id, timeoutMs, requireSignal, false)) // BAD!, should subtract time elapsed, clamp to, i dunno, 5ms min?
|
if (!Barrier(jobWorker.second->id, timeoutMs, requireSignal && jobWorker.second->id.second != currentWorkerId, false)) // BAD!, should subtract time elapsed, clamp to, i dunno, 5ms min?
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user