[util] Add util::deque container

Adding the util::deque container, implemented with the util::linked_list
of arrays of items.

Also, use the deque for a kobject's blocked thread list to maintain
order instead of a vector using remove_swap().
This commit is contained in:
Justin C. Miller
2022-01-30 20:42:49 -08:00
parent 2aef7176ab
commit a7245116b6
4 changed files with 182 additions and 19 deletions

View File

@@ -23,6 +23,8 @@ struct handle
static_cast<j6_handle_t>(obj ? obj->get_type() : kobject::type::none) << type_shift;
}
inline handle() : id {j6_handle_invalid}, object {nullptr} {}
inline handle(j6_handle_t in_id, kobject *in_obj, j6_cap_t caps) :
id {make_id(in_id, caps, in_obj)}, object {in_obj} {
if (object) object->handle_retain();
@@ -90,6 +92,7 @@ struct handle
inline const kobject * as<kobject>() const { return object; }
j6_handle_t id;
uint64_t badge;
kobject *object;
};

View File

@@ -37,32 +37,69 @@ kobject::koid_type(j6_koid_t koid)
return static_cast<type>((koid >> 48) & 0xffffull);
}
void
j6_signal_t
kobject::assert_signal(j6_signal_t s)
{
m_signals |= s;
j6_signal_t old =
__atomic_fetch_or(&m_signals, s, __ATOMIC_SEQ_CST);
notify_signal_observers();
return old;
}
j6_signal_t
kobject::deassert_signal(j6_signal_t s)
{
return __atomic_fetch_and(&m_signals, ~s, __ATOMIC_SEQ_CST);
}
void
kobject::deassert_signal(j6_signal_t s)
kobject::compact_blocked_threads()
{
m_signals &= ~s;
// Clean up what we can of the list
while (!m_blocked_threads.empty() && !m_blocked_threads.first())
m_blocked_threads.pop_front();
while (!m_blocked_threads.empty() && !m_blocked_threads.last())
m_blocked_threads.pop_back();
}
void
kobject::notify_signal_observers()
{
size_t i = 0;
while (i < m_blocked_threads.count()) {
thread *t = m_blocked_threads[i];
for (auto &entry : m_blocked_threads) {
if (entry == nullptr) continue;
if (entry->wake_on_signals(this, m_signals))
entry = nullptr;
}
compact_blocked_threads();
}
if (t->wake_on_signals(this, m_signals)) {
m_blocked_threads.remove_swap_at(i);
} else {
++i;
void
kobject::notify_object_observers(size_t count)
{
if (!count) return;
for (auto &entry : m_blocked_threads) {
if (entry == nullptr) continue;
if (entry->wake_on_object(this)) {
entry = nullptr;
if (--count) break;
}
}
compact_blocked_threads();
}
void
kobject::remove_blocked_thread(thread *t)
{
// Can't really remove from a deque, so just
// null out removed entries.
for (auto &entry : m_blocked_threads) {
if (entry == t) {
entry = nullptr;
break;
}
}
compact_blocked_threads();
}
void

View File

@@ -5,7 +5,7 @@
#include <j6/errors.h>
#include <j6/signals.h>
#include <j6/types.h>
#include <util/vector.h>
#include <util/deque.h>
namespace obj {
@@ -45,12 +45,14 @@ public:
inline j6_koid_t koid() const { return m_koid; }
/// Set the given signals active on this object
/// \arg s The set of signals to assert
void assert_signal(j6_signal_t s);
/// \arg s The set of signals to assert
/// \returns The previous state of the signals
j6_signal_t assert_signal(j6_signal_t s);
/// Clear the given signals on this object
/// \arg s The set of signals to deassert
void deassert_signal(j6_signal_t s);
/// \arg s The set of signals to deassert
/// \returns The previous state of the signals
j6_signal_t deassert_signal(j6_signal_t s);
/// Check if the given signals are set on this object
/// \arg s The set of signals to check
@@ -68,10 +70,10 @@ public:
}
/// Add the given thread to the list of threads waiting on this object.
inline void add_blocked_thread(thread *t) { m_blocked_threads.append(t); }
inline void add_blocked_thread(thread *t) { m_blocked_threads.push_back(t); }
/// Remove the given thread from the list of threads waiting on this object.
inline void remove_blocked_thread(thread *t) { m_blocked_threads.remove_swap(t); }
void remove_blocked_thread(thread *t);
/// Perform any cleanup actions necessary to mark this object closed
virtual void close();
@@ -93,12 +95,19 @@ private:
/// \arg result The result to pass to the observers
void notify_signal_observers();
/// Compact the blocked threads deque
void compact_blocked_threads();
j6_koid_t m_koid;
j6_signal_t m_signals;
uint16_t m_handle_count;
protected:
util::vector<thread*> m_blocked_threads;
/// Notify threads waiting on this object
/// \arg count Number of observers to wake, or -1ull for all
void notify_object_observers(size_t count = -1ull);
util::deque<thread*, 8> m_blocked_threads;
};
} // namespace obj