diff options
| author | Felix Morgner <felix.morgner@ost.ch> | 2026-03-31 22:22:25 +0200 |
|---|---|---|
| committer | Felix Morgner <felix.morgner@ost.ch> | 2026-04-02 11:28:08 +0200 |
| commit | 77473afe9d5acb9450443b07b56d3dbc2f0639a6 (patch) | |
| tree | a314bedf8ec1f59aa7bc1f49309fa87bdf22329a | |
| parent | e7abfb7bf87ac605b2168891973d7e04a84d627e (diff) | |
| download | teachos-77473afe9d5acb9450443b07b56d3dbc2f0639a6.tar.xz teachos-77473afe9d5acb9450443b07b56d3dbc2f0639a6.zip | |
kstd: introduce observer_ptr
| -rw-r--r-- | kapi/include/kapi/devices/bus.hpp | 3 | ||||
| -rw-r--r-- | libs/kstd/include/kstd/observer_ptr | 154 |
2 files changed, 156 insertions, 1 deletions
diff --git a/kapi/include/kapi/devices/bus.hpp b/kapi/include/kapi/devices/bus.hpp index cf8d090..0b25ac1 100644 --- a/kapi/include/kapi/devices/bus.hpp +++ b/kapi/include/kapi/devices/bus.hpp @@ -4,6 +4,7 @@ #include "kapi/devices/device.hpp" #include <kstd/memory> +#include <kstd/observer_ptr> #include <kstd/string> #include <kstd/vector> @@ -33,7 +34,7 @@ namespace kapi::devices //! Get a list of all child devices attached to this bus. //! //! @return A reference to list of child devices of this bus. - [[nodiscard]] virtual auto children() const -> kstd::vector<device *> const & = 0; + [[nodiscard]] virtual auto children() const -> kstd::vector<kstd::observer_ptr<device>> const & = 0; }; } // namespace kapi::devices diff --git a/libs/kstd/include/kstd/observer_ptr b/libs/kstd/include/kstd/observer_ptr new file mode 100644 index 0000000..d3d24b4 --- /dev/null +++ b/libs/kstd/include/kstd/observer_ptr @@ -0,0 +1,154 @@ +#ifndef KSTD_OBSERVER_PTR_HPP +#define KSTD_OBSERVER_PTR_HPP + +#include "kstd/os/error.hpp" + +#include <compare> +#include <concepts> +#include <cstddef> +#include <utility> + +namespace kstd +{ + + template<typename ElementType> + struct observer_ptr + { + //! The type of the element being pointed to. + using element_type = ElementType; + + //! Construct an empty observer pointer. + constexpr observer_ptr() noexcept = default; + + //! Construct an empty observer pointer from a null pointer. + constexpr observer_ptr(std::nullptr_t) noexcept {} + + //! Construct an observer pointer from a raw pointer. + constexpr explicit observer_ptr(element_type * pointer) + : m_ptr{pointer} + {} + + //! Construct an observer pointer from another observer pointer. + template<typename OtherElementType> + requires std::convertible_to<OtherElementType *, ElementType *> + constexpr observer_ptr(observer_ptr<OtherElementType> other) noexcept + : m_ptr{other.get()} + {} + + //! Copy construct an observer pointer. + constexpr observer_ptr(observer_ptr const & other) noexcept = default; + + //! Move construct an observer pointer. + constexpr observer_ptr(observer_ptr && other) noexcept = default; + + //! Stop watching the the watched object. + //! + //! @return The currently watched object, or nullptr if no object is being watched. + [[nodiscard]] constexpr auto release() noexcept -> element_type * + { + return std::exchange(m_ptr, nullptr); + } + + //! Reset the observer pointer. + //! + //! @param pointer The new object to watch. + constexpr auto reset(element_type * pointer) noexcept -> void + { + m_ptr = pointer; + } + + //! Swap the observer pointer with another observer pointer. + //! + //! @param other The other observer pointer to swap with. + constexpr auto swap(observer_ptr & other) noexcept -> void + { + std::swap(m_ptr, other.m_ptr); + } + + //! Get the currently watched object. + //! + //! @return The currently watched object, or nullptr if no object is being watched. + [[nodiscard]] constexpr auto get() const noexcept -> element_type * + { + return m_ptr; + } + + //! Check if the observer pointer is watching an object. + //! + //! @return True if the observer pointer is watching an object, false otherwise. + [[nodiscard]] constexpr explicit operator bool() const noexcept + { + return m_ptr != nullptr; + } + + //! Get the currently watched object. + //! + //! @return A reference to the currently watched object. + [[nodiscard]] constexpr auto operator*() const noexcept -> element_type & + { + throw_on_null(); + return *m_ptr; + } + + //! Get the currently watched object. + //! + //! @return A pointer to the currently watched object. + [[nodiscard]] constexpr auto operator->() const noexcept -> element_type * + { + throw_on_null(); + return m_ptr; + } + + //! Convert the observer pointer to a raw pointer. + //! + //! @return A pointer to the currently watched object. + constexpr explicit operator element_type *() const noexcept + { + return m_ptr; + } + + //! Compare the observer pointer with another observer pointer. + //! + //! @param other The other observer pointer to compare with. + //! @return The result of the comparison. + constexpr auto operator<=>(observer_ptr const & other) const noexcept -> std::strong_ordering = default; + + private: + //! Throw an exception if the observer pointer is null. + //! + //! @throws std::runtime_error if the observer pointer is null. + constexpr auto throw_on_null() const noexcept -> void + { + if (m_ptr == nullptr) + { + os::panic("[kstd:observer_ptr] Dereferencing a null observer pointer"); + } + } + + //! The raw pointer to the watched object. + ElementType * m_ptr; + }; + + //! Swap two observer pointers. + //! + //! @param lhs The first observer pointer to swap. + //! @param rhs The second observer pointer to swap. + template<typename ElementType> + constexpr auto swap(observer_ptr<ElementType> & lhs, observer_ptr<ElementType> & rhs) noexcept -> void + { + lhs.swap(rhs); + } + + //! Create an observer pointer from a raw pointer. + //! + //! @param pointer The raw pointer to create an observer pointer from. + //! @return An observer pointer to the given raw pointer. + template<typename ElementType> + constexpr auto make_observer(ElementType * pointer) noexcept -> observer_ptr<ElementType> + { + return observer_ptr<ElementType>{pointer}; + } + +} // namespace kstd + +#endif
\ No newline at end of file |
