diff options
| author | Felix Morgner <felix.morgner@ost.ch> | 2026-04-02 17:46:49 +0200 |
|---|---|---|
| committer | Felix Morgner <felix.morgner@ost.ch> | 2026-04-02 17:47:03 +0200 |
| commit | b2c3f25b453f1b71552fd93de8d11efbda36fcd1 (patch) | |
| tree | b9f097cbcf14e264a6818103a73c48a31830ffe4 /libs/kstd/tests/include | |
| parent | 1f010078983e6ab4e74ee3d1efcfb3284620b002 (diff) | |
| parent | c5afb5c1ce1c084c840dbb58d73af6fe2b235ec7 (diff) | |
| download | teachos-b2c3f25b453f1b71552fd93de8d11efbda36fcd1.tar.xz teachos-b2c3f25b453f1b71552fd93de8d11efbda36fcd1.zip | |
Merge branch 'fmorgner/develop-BA-FS26/pit-device' into develop-BA-FS26
This changeset introduces a central device management system. The system
comprises the following components:
- kapi::devices::bus (type)
A bus can be both a real (physically present inside the machine) or
virtual (purely conceptual) bus. Busses form a hierarchy rooted in the
virtual root_bus (accessible via `kapi::devices::get_root_bus`).
Busses are derived from `kapi::devices::device`, and own devices. This
means that a bus can be attached to another bus. This facilitates a
uniform structure for device ownership. Each device needs to be
attached to exactly one bus. Virtual devices, e.g. RAM disks, should
be attached to the root root bus (via the `add_child` member
function).
Once a device, or bus, has been attached to a bus, it will be
initialized (by means of a call to the `init` member function). Busses
are responsible to initialize their children. If a bus has already
been initialized, any newly attached children will automatically be
initialized.
During initialization, the `probe` member function of the bus under
initialization weill be invoked. This allows a bus implementation to
determine if the hardware, if any, is ready to be initialized and to
also perform any required initialization steps.
IMPORTANT: busses take ownership of their children in the form of a
`unique_ptr`.
- kapi::devices (namespace)
The functions `allocate_major_number`, `register_device`,
`unregister_device`, and `find_device` form the device manager.
The device manager is responsible for keeping a record of active
devices, allowing O(log n) lookup of devices by major and minor, and
O(n) lookup by name. Additionally, the device manager is responsible
for handing out major numbers (via `allocate_major_number`) and
keeping track of active devices. When a child is attached to a bus, it
will also automatically be registered with the device manager.
Lookup of devices via the device manager can be achieved by means of
either overload of `find_device`.
Devices should never ask the manager directly for a major number.
Instead, a controller should be used, which requests a major number
per device "class" (as in kind, not language class). For example, a
RAM disk controller may request a single major number for all RAM
disks it is going to create. When the controller creates a new device
of a given "class", e.g. a RAM disk, it should then supply that major
number to the new device instance.
IMPORTANT: the device manager does not own the active devices. Rather
it holds a `flat_map` indexed by `pair{major, minor}` and resolving to
`kstd::observer_ptr<device>`.
- kstd::observer_ptr (type)
An observer pointer is a simple vocabulary type to express the concept
of having no ownership of the pointed-to object. In essence it is
equivalent to a standard C-style pointer, but expresses semantics by
virtue of being a separate type.
Diffstat (limited to 'libs/kstd/tests/include')
| -rw-r--r-- | libs/kstd/tests/include/kstd/tests/test_types.hpp | 71 |
1 files changed, 55 insertions, 16 deletions
diff --git a/libs/kstd/tests/include/kstd/tests/test_types.hpp b/libs/kstd/tests/include/kstd/tests/test_types.hpp index 6a06311..9207ee9 100644 --- a/libs/kstd/tests/include/kstd/tests/test_types.hpp +++ b/libs/kstd/tests/include/kstd/tests/test_types.hpp @@ -11,44 +11,43 @@ namespace kstd::tests //! A type tracking copy and move operations //! //! This type is designed to test move and copy semantics of standard library containers implemented in kstd. - struct move_tracker + struct special_member_tracker { //! A value indicating that the object was moved from. constexpr auto static moved_from_v = -1; - //! A simple value to be able to track the move-from state. - int value{}; - //! A flag to track if an instance of this type was either copy constructed or copy assigned. - bool was_copied{false}; - //! A flag to track if an instance of this type was either move constructed or move assigned. - bool was_moved{false}; + constexpr special_member_tracker() + : default_constructed_count{1} + {} //! Construct a new move tracker with the given value, if any. - constexpr move_tracker(int v = 0) + constexpr special_member_tracker(int v = 0) : value{v} + , value_constructed_count{1} {} //! Construct a new move tracker by copying an existing one. - constexpr move_tracker(move_tracker const & other) + constexpr special_member_tracker(special_member_tracker const & other) : value{other.value} - , was_copied{true} + , copy_constructed_count{1} {} //! Construct a new move tracker by moving from an existing one. - constexpr move_tracker(move_tracker && other) noexcept + constexpr special_member_tracker(special_member_tracker && other) noexcept : value{other.value} - , was_moved{true} + , move_constructed_count{1} { other.value = moved_from_v; } //! Copy assign a new move tracker from an existing one. - constexpr auto operator=(move_tracker const & other) -> move_tracker & + constexpr auto operator=(special_member_tracker const & other) -> special_member_tracker & { if (this != &other) { value = other.value; - was_copied = true; + ++copy_assigned_count; + ++other.copied_from_count; } return *this; } @@ -56,16 +55,56 @@ namespace kstd::tests //! Move assign a new move tracker from an existing one. //! //! This function ensures that the moved-from state is marked. - constexpr auto operator=(move_tracker && other) noexcept -> move_tracker & + constexpr auto operator=(special_member_tracker && other) noexcept -> special_member_tracker & { if (this != &other) { value = other.value; - was_moved = true; + ++move_assigned_count; other.value = moved_from_v; + ++other.moved_from_count; } return *this; } + + ~special_member_tracker() + { + ++destroyed_count; + } + + auto reset_counts() -> void + { + default_constructed_count = 0; + copy_constructed_count = 0; + move_constructed_count = 0; + value_constructed_count = 0; + copy_assigned_count = 0; + move_assigned_count = 0; + destroyed_count = 0; + copied_from_count = 0; + moved_from_count = 0; + } + + //! A simple value to be able to track the move-from state. + int value{}; + //! A counter to track how many times an instance of this type was default constructed. + std::size_t default_constructed_count{0}; + //! A counter to track how many times an instance of this type was copy constructed. + std::size_t copy_constructed_count{0}; + //! A counter to track how many times an instance of this type was move constructed. + std::size_t move_constructed_count{0}; + //! A counter to track how many times an instance of this type was value constructed. + std::size_t value_constructed_count{0}; + //! A counter to track how many times an instance of this type was copy assigned. + std::size_t copy_assigned_count{0}; + //! A counter to track how many times an instance of this type was move assigned. + std::size_t move_assigned_count{0}; + //! A counter to track how many times an instance of this type was destroyed. + std::size_t destroyed_count{0}; + //! A counter to track how many times an instance of this type was copied from another instance. + mutable std::size_t copied_from_count{0}; + //! A counter to track how many times an instance of this type was moved from another instance. + std::size_t moved_from_count{0}; }; //! A type that is not default constructible. |
