28#ifndef AISTATEFULTASKMUTEX_H
29#define AISTATEFULTASKMUTEX_H
31#include "threadsafe/aithreadsafe.h"
32#include "utils/NodeMemoryResource.h"
33#include "utils/threading/MpscQueue.h"
34#include "utils/FuzzyBool.h"
35#include "utils/cpu_relax.h"
43 using condition_type = uint32_t;
46 condition_type
const m_condition;
87 using condition_type = uint32_t;
91 class Queue :
public utils::threading::MpscQueue
93 using MpscNode = utils::threading::MpscNode;
94 std::mutex m_abort_mutex;
97 utils::FuzzyBool push(MpscNode* node)
99 node->m_next.store(
nullptr, std::memory_order_relaxed);
100 MpscNode* prev = m_head.exchange(node, std::memory_order_relaxed);
149 bool is_front = prev == &m_stub && m_tail.load(std::memory_order_acquire) == &m_stub;
154 prev->m_next.store(node, std::memory_order_release);
156 return is_front ? fuzzy::True : fuzzy::WasFalse;
168 MpscNode
const* peek()
const
182 MpscNode
const* tail = m_tail.load(std::memory_order_relaxed);
185 MpscNode
const* head = m_head.load(std::memory_order_relaxed);
189 MpscNode
const* next;
190 while (!(next = m_stub.m_next.load(std::memory_order_acquire)))
197 utils::FuzzyBool is_front(MpscNode
const* node)
const
199 MpscNode
const* tail = m_tail.load(std::memory_order_relaxed);
200 return (tail == node || tail == &m_stub && m_stub.m_next.load(std::memory_order_acquire) == node) ? fuzzy::True : fuzzy::WasFalse;
256 return next ? next->m_task :
nullptr;
282 return m_queue.is_front(handle);
316#ifndef AISTATEFULTASKMUTEX_H_definitions
317#define AISTATEFULTASKMUTEX_H_definitions
321 DoutEntering(dc::notice,
"AIStatefulTaskMutex::lock(" << task <<
", " << task->print_conditions(condition) <<
") [mutex:" <<
this <<
"]");
324 Dout(dc::notice,
"Create new node at " << new_node <<
" [" << task <<
"]");
326 utils::FuzzyBool have_lock = m_queue.push(new_node);
330 if (have_lock.is_true())
332 Dout(dc::notice,
"Mutex acquired [" << task <<
"]");
335 Dout(dc::notice,
"Mutex already locked [" << task <<
"]");
Declaration of base class AIStatefulTask.
Definition: AIStatefulTaskMutex.h:86
AIStatefulTaskMutex()
Construct an unlocked AIStatefulTaskMutex.
Definition: AIStatefulTaskMutex.h:216
Node const * lock(AIStatefulTask *task, condition_type condition)
Try to obtain ownership for owner (recursive locking allowed).
static utils::NodeMemoryResource s_node_memory_resource
Memory resource to allocate Node's from.
Definition: AIStatefulTaskMutex.h:209
static void init(utils::MemoryPagePool *mpp_ptr)
This must be called once before using a AIStatefulTaskMutex.
Definition: AIStatefulTaskMutex.h:208
static constexpr size_t node_size()
Returns the size of the nodes that will be allocated from s_node_memory_resource.
Definition: AIStatefulTaskMutex.h:206
void unlock()
Undo one (succcessful) call to lock.
Definition: AIStatefulTaskMutex.cxx:32
Definition: AIStatefulTask.h:96
Definition: AIStatefulTaskMutex.h:290
utils::FuzzyBool is_self_locked(AIStatefulTaskMutex const &stateful_task_mutex, AIStatefulTaskMutexNode const *handle)
Tasks defined by the library project are put into this namespace.
Definition: AIStatefulTask.h:857
Definition: AIStatefulTaskMutex.h:42