diff --git a/mesosphere/include/mesosphere/core/KLinkedList.hpp b/mesosphere/include/mesosphere/core/KLinkedList.hpp index 0326187eb..3b0c18353 100644 --- a/mesosphere/include/mesosphere/core/KLinkedList.hpp +++ b/mesosphere/include/mesosphere/core/KLinkedList.hpp @@ -389,6 +389,18 @@ class KLinkedList final { return nd->data; } + template< class... Args> + T *emplace_back_or_fail(Args&&... args) + { + auto *nd = new typename List::Node{std::forward(args)...}; + if (nd != nullptr) { + insert_node_after(list.last(), &nd->link); + return &nd->data; + } else { + return nullptr; + } + } + void pop_back() { auto *nd = list.last(); diff --git a/mesosphere/include/mesosphere/core/KObjectRegistry.hpp b/mesosphere/include/mesosphere/core/KObjectRegistry.hpp new file mode 100644 index 000000000..a2ba8a2f5 --- /dev/null +++ b/mesosphere/include/mesosphere/core/KObjectRegistry.hpp @@ -0,0 +1,43 @@ +#pragma once + +#include +#include +#include +#include +#include + +namespace mesosphere +{ + +class KObjectRegistry { + public: + + static KObjectRegistry &GetInstance() { return instance; } + + SharedPtr Find(const char *name) const; + Result Register(SharedPtr obj, const char *name); + Result Unregister(const char *name); + + private: + + struct Node { + SharedPtr obj{}; + char name[12] = {0}; + + Node() = default; + Node(SharedPtr &&obj, const char *name) : obj{obj} + { + std::strncpy(this->name, name, sizeof(this->name)); + } + }; + + const Node *FindImpl(const char *name) const; + Node *FindImpl(const char *name); + + KLinkedList nameNodes{}; + mutable KMutex mutex{}; + + static KObjectRegistry instance; +}; + +} \ No newline at end of file diff --git a/mesosphere/source/core/KObjectRegistry.cpp b/mesosphere/source/core/KObjectRegistry.cpp new file mode 100644 index 000000000..3ae225e12 --- /dev/null +++ b/mesosphere/source/core/KObjectRegistry.cpp @@ -0,0 +1,79 @@ +#include +#include + +namespace mesosphere +{ + +KObjectRegistry KObjectRegistry::instance{}; + +const KObjectRegistry::Node *KObjectRegistry::FindImpl(const char *name) const +{ + auto it = std::find_if( + nameNodes.cbegin(), + nameNodes.cend(), + [name](const Node &nd) { + return std::strncmp(name, nd.name, sizeof(nd.name)) == 0; + } + ); + + return it == nameNodes.cend() ? nullptr : &*it; +} + +KObjectRegistry::Node *KObjectRegistry::FindImpl(const char *name) +{ + auto it = std::find_if( + nameNodes.begin(), + nameNodes.end(), + [name](const Node &nd) { + return std::strncmp(name, nd.name, sizeof(nd.name)) == 0; + } + ); + + return it == nameNodes.end() ? nullptr : &*it; +} + +SharedPtr KObjectRegistry::Find(const char *name) const +{ + std::scoped_lock guard{mutex}; + const Node *node = FindImpl(name); + return node == nullptr ? nullptr : node->obj; +} + + +Result KObjectRegistry::Register(SharedPtr obj, const char *name) +{ + std::scoped_lock guard{mutex}; + Node *node = FindImpl(name); + if (node != nullptr) { + // Name already exists, just replace the auto object. + node->obj = std::move(obj); + return ResultSuccess(); + } else { + if (nameNodes.emplace_back_or_fail(std::move(obj), name) == nullptr) { + return ResultKernelInvalidState(); + } + return ResultSuccess(); + } +} + +Result KObjectRegistry::Unregister(const char *name) +{ + std::scoped_lock guard{mutex}; + + auto it = std::find_if( + nameNodes.cbegin(), + nameNodes.cend(), + [name](const Node &nd) { + return std::strncmp(name, nd.name, sizeof(nd.name)) == 0; + } + ); + + if (it == nameNodes.cend()) { + return ResultKernelNotFound(); + } else { + nameNodes.erase(it); + return ResultSuccess(); + } +} + +} \ No newline at end of file