diff --git a/orbis-kernel/include/orbis/evf.hpp b/orbis-kernel/include/orbis/evf.hpp index 72fcb2893..0310fa91f 100644 --- a/orbis-kernel/include/orbis/evf.hpp +++ b/orbis-kernel/include/orbis/evf.hpp @@ -61,6 +61,12 @@ struct EventFlag { shared_mutex queueMtx; + enum class NotifyType { + Set, + Cancel, + Destroy + }; + explicit EventFlag(std::int32_t attrs) : attrs(attrs) {} ErrorCode wait(Thread *thread, std::uint8_t waitMode, @@ -68,33 +74,23 @@ struct EventFlag { std::uint32_t *timeout); ErrorCode tryWait(Thread *thread, std::uint8_t waitMode, std::uint64_t bitPattern, std::uint64_t *patternSet); - std::size_t notify(bool isCancel = false, std::uint64_t cancelValue = 0); + std::size_t notify(NotifyType type, std::uint64_t bits); std::size_t destroy() { - isDeleted = true; - return notify(); + return notify(NotifyType::Destroy, {}); } std::size_t cancel(std::uint64_t value) { - return notify(true, value); + return notify(NotifyType::Cancel, value); } std::size_t set(std::uint64_t bits) { - { - writer_lock lock(queueMtx); - value.fetch_or(bits, std::memory_order::relaxed); - } - - return notify(); + return notify(NotifyType::Set, bits); } void clear(std::uint64_t bits) { - { - writer_lock lock(queueMtx); - value.fetch_and(bits, std::memory_order::relaxed); - } - - value &= bits; + writer_lock lock(queueMtx); + value.fetch_and(bits, std::memory_order::relaxed); } void incRef() { references.fetch_add(1, std::memory_order::relaxed); } diff --git a/orbis-kernel/src/evf.cpp b/orbis-kernel/src/evf.cpp index 80b03c7ea..faa179664 100644 --- a/orbis-kernel/src/evf.cpp +++ b/orbis-kernel/src/evf.cpp @@ -109,13 +109,19 @@ orbis::ErrorCode orbis::EventFlag::tryWait(Thread *, return ErrorCode::BUSY; } -std::size_t orbis::EventFlag::notify(bool isCancel, std::uint64_t cancelValue) { +std::size_t orbis::EventFlag::notify(NotifyType type, std::uint64_t bits) { writer_lock lock(queueMtx); auto count = waitingThreadsCount.load(std::memory_order::relaxed); auto patValue = value.load(std::memory_order::relaxed); + if (type == NotifyType::Destroy) { + isDeleted = true; + } else if (type == NotifyType::Set) { + patValue |= bits; + } + auto testThread = [&](WaitingThread *thread) { - if (!isCancel && !isDeleted && !thread->test(patValue)) { + if (type != NotifyType::Set && !thread->test(patValue)) { return false; } @@ -124,18 +130,16 @@ std::size_t orbis::EventFlag::notify(bool isCancel, std::uint64_t cancelValue) { if (thread->patternSet != nullptr) { *thread->patternSet = resultValue; } - if (isCancel) { + if (type == NotifyType::Cancel) { *thread->isCanceled = true; - } else { - value.store(resultValue, std::memory_order::relaxed); } // TODO: update thread state thread->mtx->unlock(); // release wait on waiter thread waitingThreadsCount.fetch_sub(1, std::memory_order::relaxed); + std::memmove(thread, thread + 1, (waitingThreads + count - (thread + 1)) * sizeof(*waitingThreads)); --count; - std::memmove(thread, thread + 1, waitingThreads + count - (thread + 1)); return true; }; @@ -160,8 +164,10 @@ std::size_t orbis::EventFlag::notify(bool isCancel, std::uint64_t cancelValue) { } } - if (isCancel) { - value.store(cancelValue, std::memory_order::relaxed); + if (type == NotifyType::Cancel) { + value.store(bits, std::memory_order::relaxed); + } else { + value.store(patValue, std::memory_order::relaxed); } return result; }