From 1a6d41362447531a2ea5ee344c15b9aaa6c2090a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sun, 9 Mar 2025 16:52:17 +0000 Subject: Adjust comments and implement remaining interface for STL classes. --- arch/x86_64/include/arch/stl/shared_pointer.hpp | 142 ++++++++++++++---------- arch/x86_64/include/arch/stl/unique_pointer.hpp | 96 +++++++++++----- arch/x86_64/include/arch/stl/vector.hpp | 18 +-- arch/x86_64/src/memory/main.cpp | 5 +- 4 files changed, 163 insertions(+), 98 deletions(-) (limited to 'arch/x86_64') diff --git a/arch/x86_64/include/arch/stl/shared_pointer.hpp b/arch/x86_64/include/arch/stl/shared_pointer.hpp index 80ca7fe..1ddc182 100644 --- a/arch/x86_64/include/arch/stl/shared_pointer.hpp +++ b/arch/x86_64/include/arch/stl/shared_pointer.hpp @@ -6,10 +6,14 @@ namespace teachos::arch::stl { /** - * @brief A simple implementation of a shared pointer. - * - * This class provides reference counting and automatic resource management - * for dynamically allocated objects. + * @brief Shared_pointer is a smart pointer that retains shared ownership of an object through a pointer. Several + * shared_pointer objects may own the same object. The object is destroyed and its memory deallocated when either of + * the following happens: the last remaining shared_pointer owning the object is destroyed; the last remaining + * shared_pointer owning the object is assigned another pointer via operator= or reset(). A + * shared_pointer can share ownership of an object while storing a pointer to another object. This feature can be used + * to point to member objects while owning the object they belong to. The stored pointer is the one accessed by get(), + * the dereference and the comparison operators. The managed pointer is the one passed to the deleter when use count + * reaches zero. * * @tparam T The type of the managed object. */ @@ -17,14 +21,15 @@ namespace teachos::arch::stl struct shared_pointer { /** - * @brief Constructs a shared pointer. + * @brief Constructor. * - * @param pointer Raw pointer to manage (default is nullptr). + * @param pointer A pointer to an object to manage (default is nullptr). */ explicit shared_pointer(T * pointer = nullptr) : pointer(pointer) - , ref_count(new std::atomic(pointer != nullptr ? 1 : 0)) + , ref_count(new std::atomic(pointer != nullptr ? 1 : 0)) { + // Nothing to do. } /** @@ -56,10 +61,12 @@ namespace teachos::arch::stl } /** - * @brief Copy assignment operator. + * @brief Copy assignment operator. Replaces the managed object with the one managed by r. Shares ownership of the + * object managed by r. If r manages no object, *this manages no object too. Equivalent to + * shared_ptr(r).swap(*this). * - * @param other The shared_pointer to copy from. - * @return Reference to this shared_pointer. + * @param other Another smart pointer to share the ownership with. + * @return Reference to this shared pointer. */ shared_pointer & operator=(const shared_pointer & other) { @@ -79,10 +86,11 @@ namespace teachos::arch::stl } /** - * @brief Move assignment operator. + * @brief Move assignment operator. Move-assigns a shared_ptr from r. After the assignment, *this contains a copy of + * the previous state of r, and r is empty. Equivalent to shared_ptr(std::move(r)).swap(*this). * - * @param other The shared_pointer to move from. - * @return Reference to this shared_pointer. + * @param other Another smart pointer to acquire the ownership from. + * @return Reference to this shared pointer. */ shared_pointer & operator=(shared_pointer && other) noexcept { @@ -104,31 +112,20 @@ namespace teachos::arch::stl ~shared_pointer() { cleanup(); } /** - * @brief Releases ownership and deletes the object if necessary. - */ - void cleanup() - { - if (pointer != nullptr && ref_count != nullptr && --(*ref_count) == 0) - { - delete pointer; - delete ref_count; - } - } - - /** - * @brief Resets the shared pointer with a new raw pointer. + * @brief Replaces the managed object. * - * @param p New raw pointer (default is nullptr). + * @param ptr Pointer to a new object to manage (default = nullptr). */ - void reset(T * p = nullptr) + void reset(T * ptr = nullptr) { cleanup(); - pointer = p; - ref_count = new std::atomic(p != nullptr ? 1 : 0); + pointer = ptr; + ref_count = new std::atomic(ptr != nullptr ? 1 : 0); } /** - * @brief Swaps the contents of this shared pointer with another. + * @brief Exchanges the stored pointer values and the ownerships of *this and r. Reference counts, if any, are not + * adjusted. * * @param other The shared_pointer to swap with. */ @@ -139,32 +136,38 @@ namespace teachos::arch::stl } /** - * @brief Dereference operator. + * @brief Dereference operator. If get() is a null pointer, the behavior is undefined. * - * @return Reference to the managed object. + * @return Returns the object owned by *this, equivalent to *get(). */ - T & operator*() const { return *pointer; } + auto operator*() const -> T & { return *pointer; } /** * @brief Member access operator. * - * @return Pointer to the managed object. + * @return Returns a pointer to the object owned by *this, i.e. get(). */ - T * operator->() const { return pointer; } + auto operator->() const -> T * { return pointer; } /** - * @brief Returns the raw pointer. + * @brief Returns a pointer to the managed object or nullptr if no object is owned. * - * @return Pointer to the managed object. + * @return Pointer to the managed object or nullptr if no object is owned. */ - T * get() const { return pointer; } + auto get() const -> T * { return pointer; } /** - * @brief Returns the reference count. + * @brief Returns the number of different shared_pointer instances (*this included) managing the current object. If + * there is no managed object, ​0​ is returned. * - * @return Number of shared_pointer instances managing the same object. + * @note Common use cases include comparison with ​0​. If use_count returns zero, the shared pointer is empty + * and manages no objects (whether or not its stored pointer is nullptr). Comparison with 1. If use_count returns 1, + * there are no other owners. + * + * @return The number of Shared_pointer instances managing the current object or ​0​ if there is no managed + * object. */ - int use_count() const + auto use_count() const -> std::size_t { if (pointer != nullptr) { @@ -175,34 +178,59 @@ namespace teachos::arch::stl } /** - * @brief Checks if this is the only shared pointer managing the object. + * @brief Checks whether *this owns an object, i.e. whether get() != nullptr. * - * @return True if the use count is 1, otherwise false. + * @return true if *this owns an object, false otherwise. */ - bool unique() const { return use_count() == 1; } + explicit operator bool() const { return pointer != nullptr; } /** - * @brief Checks if the shared pointer is not empty. - * - * @return True if the pointer is not null, otherwise false. + * @brief Defaulted three-way comparator operator. */ - explicit operator bool() const { return pointer != nullptr; } + auto operator<=>(const shared_pointer & other) const = default; private: - T * pointer; ///< The managed object. - std::atomic * ref_count; ///< Reference count. + /** + * @brief Releases ownership and deletes the object if this was the last ereference to the owned managed object. + */ + auto cleanup() -> void + { + if (pointer != nullptr && ref_count != nullptr && --(*ref_count) == 0) + { + delete pointer; + delete ref_count; + } + } + + T * pointer; ///< The managed object. + std::atomic * ref_count; ///< Reference count. }; /** - * @brief Creates a shared pointer instance. + * @brief Specializes the std::swap algorithm for stl::unique_ptr. Swaps the contents of lhs and rhs. Calls + * lhs.swap(rhs). + * + * @tparam T Type of the managed object. + * @param lhs, rhs Smart pointers whose contents to swap. + */ + template + auto swap(shared_pointer & lhs, shared_pointer & rhs) -> void + { + lhs.swap(rhs); + } + + /** + * @brief Constructs an object of type T and wraps it in a shared_pointer. Constructs a non-array type T. The + * arguments args are passed to the constructor of T. This overload participates in overload resolution only if T is + * not an array type. The function is equivalent to: shared_pointer(new T(std::forward(args)...)). * - * @tparam T The type of object to allocate. - * @tparam Args Argument types for the constructor of T. - * @param args Arguments for the constructor of T. - * @return A shared_pointer instance managing a newly created object. + * @tparam T Type of the managed object. + * @tparam Args Argument types for T's constructor. + * @param args List of arguments with which an instance of T will be constructed. + * @returns Shared_pointer of an instance of type T. */ template - shared_pointer make_shared(Args &&... args) + auto make_shared(Args &&... args) -> shared_pointer { return shared_pointer(new T(std::forward(args)...)); } diff --git a/arch/x86_64/include/arch/stl/unique_pointer.hpp b/arch/x86_64/include/arch/stl/unique_pointer.hpp index 08c862d..899a35b 100644 --- a/arch/x86_64/include/arch/stl/unique_pointer.hpp +++ b/arch/x86_64/include/arch/stl/unique_pointer.hpp @@ -4,7 +4,8 @@ namespace teachos::arch::stl { /** - * @brief A simple unique pointer implementation. + * @brief Unique_pointer is a smart pointer that owns (is responsible for) and manages another object via a pointer + * and subsequently disposes of that object when the unique_pointer goes out of scope. * * @tparam T Type of the managed object. */ @@ -12,13 +13,14 @@ namespace teachos::arch::stl struct unique_pointer { /** - * @brief Constructs a unique pointer. + * @brief Constructor. * - * @param ptr Pointer to manage, default is nullptr. + * @param ptr A pointer to an object to manage (default is nullptr). */ explicit unique_pointer(T * ptr = nullptr) : pointer(ptr) { + // Nothing to do. } /** @@ -34,7 +36,7 @@ namespace teachos::arch::stl /** * @brief Deleted copy assignment operator to enforce unique ownership. */ - unique_pointer & operator=(const unique_pointer &) = delete; + auto operator=(const unique_pointer &) -> unique_pointer & = delete; /** * @brief Move constructor. @@ -48,12 +50,12 @@ namespace teachos::arch::stl } /** - * @brief Move assignment operator. + * @brief Move assignment operator. Transfers ownership from other to *this as if by calling reset(r.release()). * - * @param other Unique pointer to move from. + * @param other Smart pointer from which ownership will be transferred. * @return Reference to this unique pointer. */ - unique_pointer & operator=(unique_pointer && other) noexcept + auto operator=(unique_pointer && other) noexcept -> unique_pointer & { if (this != &other) { @@ -65,32 +67,42 @@ namespace teachos::arch::stl } /** - * @brief Dereference operator. + * @brief Dereference operator. If get() is a null pointer, the behavior is undefined. * - * @return Reference to the managed object. + * @return Returns the object owned by *this, equivalent to *get(). */ - T & operator*() const { return *pointer; } + auto operator*() const -> T & { return *pointer; } /** * @brief Member access operator. * - * @return Pointer to the managed object. + * @return Returns a pointer to the object owned by *this, i.e. get(). + */ + auto operator->() const -> T * { return pointer; } + + /** + * @brief Returns a pointer to the managed object or nullptr if no object is owned. + * + * @return Pointer to the managed object or nullptr if no object is owned. */ - T * operator->() const { return pointer; } + auto get() const -> T * { return pointer; } /** - * @brief Gets the raw pointer. + * @brief Checks whether *this owns an object, i.e. whether get() != nullptr. * - * @return The managed pointer. + * @return true if *this owns an object, false otherwise. */ - T * get() const { return pointer; } + explicit operator bool() const noexcept { return pointer != nullptr; } /** - * @brief Releases ownership of the managed object. + * @brief Releases the ownership of the managed object, if any. + * get() returns nullptr after the call. + * The caller is responsible for cleaning up the object (e.g. by use of get_deleter()). * - * @return The raw pointer and sets internal pointer to nullptr. + * @return Pointer to the managed object or nullptr if there was no managed object, i.e. the value which would be + * returned by get() before the call. */ - T * release() + auto release() -> T * { T * temp = pointer; pointer = nullptr; @@ -98,37 +110,65 @@ namespace teachos::arch::stl } /** - * @brief Resets the managed object. + * @brief Replaces the managed object. * - * @param ptr New pointer to manage (default is nullptr). + * @note A test for self-reset, i.e. whether ptr points to an object already managed by *this, is not performed, + * except where provided as a compiler extension or as a debugging assert. Note that code such as + * p.reset(p.release()) does not involve self-reset, only code like p.reset(p.get()) does. + * + * @param ptr Pointer to a new object to manage (default = nullptr). */ - void reset(T * ptr = nullptr) + auto reset(T * ptr = nullptr) -> void { delete pointer; pointer = ptr; } /** - * @brief Swaps the managed object with another unique pointer. + * @brief Swaps the managed objects and associated deleters of *this and another unique_ptr object other. * - * @param other Unique pointer to swap with. + * @param other Another unique_ptr object to swap the managed object and the deleter with. */ - void swap(unique_pointer & other) { std::swap(pointer, other.pointer); } + auto swap(unique_pointer & other) -> void + { + using std::swap; + swap(pointer, other.pointer); + } + + /** + * @brief Defaulted three-way comparator operator. + */ + auto operator<=>(const unique_pointer & other) const = default; private: T * pointer; ///< The managed pointer. }; /** - * @brief Creates a unique pointer instance. + * @brief Specializes the std::swap algorithm for stl::unique_ptr. Swaps the contents of lhs and rhs. Calls + * lhs.swap(rhs). + * + * @tparam T Type of the managed object. + * @param lhs, rhs Smart pointers whose contents to swap. + */ + template + auto swap(unique_pointer & lhs, unique_pointer & rhs) -> void + { + lhs.swap(rhs); + } + + /** + * @brief Constructs an object of type T and wraps it in a unique_pointer. Constructs a non-array type T. The + * arguments args are passed to the constructor of T. This overload participates in overload resolution only if T is + * not an array type. The function is equivalent to: unique_pointer(new T(std::forward(args)...)). * * @tparam T Type of the managed object. * @tparam Args Argument types for T's constructor. - * @param args Arguments for T's constructor. - * @return A unique pointer managing a newly created T object. + * @param args List of arguments with which an instance of T will be constructed. + * @returns Unique_pointer of an instance of type T. */ template - unique_pointer make_unique(Args &&... args) + auto make_unique(Args &&... args) -> unique_pointer { return unique_pointer(new T(std::forward(args)...)); } diff --git a/arch/x86_64/include/arch/stl/vector.hpp b/arch/x86_64/include/arch/stl/vector.hpp index 5bebf62..b8bedf3 100644 --- a/arch/x86_64/include/arch/stl/vector.hpp +++ b/arch/x86_64/include/arch/stl/vector.hpp @@ -29,7 +29,7 @@ namespace teachos::arch::stl * @param capacity Amount of elements we want to create and set the given value for. * @param initial Inital value of all elements in the underlying data array. */ - explicit vector(size_t capacity, T initial = T{}) + explicit vector(std::size_t capacity, T initial = T{}) : _size(capacity) , _capacity(capacity) , _data(new T[_capacity]{}) @@ -113,7 +113,7 @@ namespace teachos::arch::stl * * @return Current amount of elements. */ - size_t size() const { return _size; } + std::size_t size() const { return _size; } /** * @brief Amount of space the vector currently has, can be different than the size, because we allocate more than we @@ -121,7 +121,7 @@ namespace teachos::arch::stl * * @return Current amount of space the vector has for elements. */ - size_t capacity() const { return _capacity; } + std::size_t capacity() const { return _capacity; } /** * @brief Array indexing operator. Allowing to access element at the given index. @@ -131,7 +131,7 @@ namespace teachos::arch::stl * @param index Index we want to access elements at. * @return Reference to the underlying element. */ - T & operator[](size_t index) { return _data[index]; } + T & operator[](std::size_t index) { return _data[index]; } /** * @brief Array indexing operator. Allowing to access element at the given index. @@ -141,7 +141,7 @@ namespace teachos::arch::stl * @param index Index we want to access elements at. * @return Reference to the underlying element. */ - T & at(size_t index) + T & at(std::size_t index) { if (index >= _size) { @@ -357,7 +357,7 @@ namespace teachos::arch::stl * * @param new_capacity New capacity of the vector, in number of elements */ - void reserve(size_t new_capacity) + void reserve(std::size_t new_capacity) { if (new_capacity <= _capacity) { @@ -392,9 +392,9 @@ namespace teachos::arch::stl } private: - size_t _size = {}; ///< Amount of elements in the underlying data container - size_t _capacity = {}; ///< Amount of space for elements in the underlying data container - T * _data = {}; ///< Pointer to the first element in the underlying data container + std::size_t _size = {}; ///< Amount of elements in the underlying data container + std::size_t _capacity = {}; ///< Amount of space for elements in the underlying data container + T * _data = {}; ///< Pointer to the first element in the underlying data container }; } // namespace teachos::arch::stl diff --git a/arch/x86_64/src/memory/main.cpp b/arch/x86_64/src/memory/main.cpp index 15e89c0..a6f91d9 100644 --- a/arch/x86_64/src/memory/main.cpp +++ b/arch/x86_64/src/memory/main.cpp @@ -7,9 +7,6 @@ #include "arch/memory/heap/heap_allocator.hpp" #include "arch/memory/paging/active_page_table.hpp" #include "arch/memory/paging/kernel_mapper.hpp" -#include "arch/stl/shared_pointer.hpp" -#include "arch/stl/unique_pointer.hpp" -#include "arch/stl/vector.hpp" namespace teachos::arch::memory { @@ -53,4 +50,4 @@ namespace teachos::arch::memory video::vga::text::write("Heap remapping successful", video::vga::text::common_attributes::green_on_black); video::vga::text::newline(); } -} // namespace teachos::arch::memory \ No newline at end of file +} // namespace teachos::arch::memory -- cgit v1.2.3