[*] 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 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 DispatchTarget_t = AuPair<ThreadGroup_t, AuOptional<ThreadId_t>>;
|
||||
|
||||
struct WorkPriv
|
||||
@ -63,27 +72,28 @@ namespace Aurora::Async
|
||||
std::function<void(const Info_t &, const Result_t &)> onSuccess = 0;
|
||||
std::function<void(const Info_t &, bool)> onFailure = 0;
|
||||
};
|
||||
|
||||
|
||||
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;
|
||||
ret.onSuccess = [=](const Info_t &in, const Result_t &a)
|
||||
{
|
||||
onSuccess(a);
|
||||
onSuccess(in, a);
|
||||
};
|
||||
return ret;
|
||||
}
|
||||
|
||||
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;
|
||||
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);
|
||||
};
|
||||
@ -91,23 +101,23 @@ namespace Aurora::Async
|
||||
}
|
||||
|
||||
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;
|
||||
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);
|
||||
};
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
using FVoidJob = FJob<AVoid, AVoid>;
|
||||
|
||||
|
||||
template<class Info_t = AVoid, class Result_t = AVoid>
|
||||
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);
|
||||
|
||||
#pragma region EASE_OF_READING
|
||||
struct BasicWorkStdFunc : IWorkItemHandler
|
||||
{
|
||||
std::function<void()> callback;
|
||||
@ -239,7 +250,6 @@ namespace Aurora::Async
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
|
||||
#if !defined(_CPPSHARP)
|
||||
/// @hideinitializer
|
||||
@ -516,6 +526,8 @@ namespace Aurora::Async
|
||||
#undef ASYNC_FINISH
|
||||
|
||||
#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>>
|
||||
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();
|
||||
}
|
||||
|
||||
|
||||
class IAsyncApp
|
||||
{
|
||||
public:
|
||||
@ -547,6 +558,7 @@ namespace Aurora::Async
|
||||
virtual WorkerId_t GetCurrentThread() = 0;
|
||||
|
||||
// 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 void Signal(ThreadGroup_t group) = 0;
|
||||
|
||||
|
@ -585,11 +585,14 @@ namespace Aurora::Async
|
||||
bool AsyncApp::Sync(ThreadGroup_t groupId, bool requireSignal, AuUInt32 timeoutMs)
|
||||
{
|
||||
AU_LOCK_GUARD(rwlock_->AsReadable());
|
||||
|
||||
auto group = GetGroup(groupId);
|
||||
|
||||
auto currentWorkerId = GetCurrentThread().second;
|
||||
|
||||
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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user