summaryrefslogtreecommitdiffhomepage
path: root/include/ocl/memory
diff options
context:
space:
mode:
authorAmlal El Mahrouss <amlal@nekernel.org>2025-11-23 20:16:02 -0500
committerGitHub <noreply@github.com>2025-11-23 20:16:02 -0500
commit85f89ee4bb137100cbeffcbc10168eb8ea52e6cc (patch)
treef6e2063319ceaaa02f523fb5c289e4f37411a2df /include/ocl/memory
parent9a70f32ddaec0eef99efbf7ff5597c2adf08f45a (diff)
parent65a8349aa5526d071b18cd4d42586c46faaa3823 (diff)
Merge pull request #18 from amlel-el-mahrouss/developv1.0.48
OCL v1.0.48
Diffstat (limited to 'include/ocl/memory')
-rw-r--r--include/ocl/memory/allocator_system.hpp74
-rw-r--r--include/ocl/memory/tracked_ptr.hpp241
2 files changed, 315 insertions, 0 deletions
diff --git a/include/ocl/memory/allocator_system.hpp b/include/ocl/memory/allocator_system.hpp
new file mode 100644
index 0000000..67e3266
--- /dev/null
+++ b/include/ocl/memory/allocator_system.hpp
@@ -0,0 +1,74 @@
+/*
+ * File: core/allocator_system.hpp
+ * Purpose: Allocator System container.
+ * Author: Amlal El Mahrouss (amlal@nekernel.org)
+ * Copyright 2025, Amlal El Mahrouss, Licensed under the Boost Software License. Licensed under the BSL 1.0 license
+ */
+
+#ifndef _OCL_ALLOCATOR_SYSTEM_HPP
+#define _OCL_ALLOCATOR_SYSTEM_HPP
+
+#include <core/includes.hpp>
+#include <memory>
+
+namespace ocl
+{
+ template <typename type>
+ struct new_op final
+ {
+ inline auto operator()() -> type*
+ {
+ return new type;
+ }
+
+ template <typename... var_type>
+ inline auto var_alloc(var_type... args) -> type*
+ {
+ return new type{args...};
+ }
+ };
+
+ template <typename type>
+ struct delete_op final
+ {
+ inline auto operator()(type* t) -> void
+ {
+ delete t;
+ }
+ };
+
+ template <typename ret_type, typename allocator_new, typename allocator_delete>
+ class allocator_system
+ {
+ allocator_new m_alloc_{};
+ allocator_delete m_free_{};
+
+ public:
+ allocator_system() = default;
+ ~allocator_system() = default;
+
+ allocator_system& operator=(const allocator_system&) = delete;
+ allocator_system(const allocator_system&) = delete;
+
+ ret_type* claim() noexcept
+ {
+ return m_alloc_();
+ }
+
+ template <typename... var_type>
+ auto construct(var_type... args) -> std::shared_ptr<ret_type>
+ {
+ return std::shared_ptr<ret_type>(m_alloc_.template var_alloc<var_type...>(args...), allocator_delete{});
+ }
+
+ void unclaim(ret_type* ptr)
+ {
+ m_free_(ptr);
+ }
+ };
+
+ template <typename type>
+ using standard_allocator_type = allocator_system<type, new_op<type>, delete_op<type>>;
+} // namespace ocl
+
+#endif // ifndef _OCL_ALLOCATOR_SYSTEM_HPP \ No newline at end of file
diff --git a/include/ocl/memory/tracked_ptr.hpp b/include/ocl/memory/tracked_ptr.hpp
new file mode 100644
index 0000000..fcaf898
--- /dev/null
+++ b/include/ocl/memory/tracked_ptr.hpp
@@ -0,0 +1,241 @@
+/*
+ * File: memory/tracked_ptr.hpp
+ * Purpose: Custom smart pointer implementation in C++
+ * Author: Amlal El Mahrouss (amlal@nekernel.org)
+ * Copyright 2025, Amlal El Mahrouss, licensed under the Boost Software License.
+ */
+
+#pragma once
+
+#include <cstddef>
+#include <utility>
+#include <new>
+#include <atomic>
+
+#include <sys/types.h>
+#include <unistd.h>
+#include <signal.h>
+
+namespace ocl::memory
+{
+ template <typename T>
+ class tracked_allocator;
+
+ template <typename T>
+ class tracked_mgr;
+
+ template <typename T, typename Mgr>
+ class tracked_ptr;
+
+ template <typename T>
+ class tracked_allocator
+ {
+ public:
+ std::atomic<size_t> allocated_count_ = 0;
+ std::atomic<size_t> deallocated_count_ = 0;
+
+ public:
+ explicit tracked_allocator() = default;
+ virtual ~tracked_allocator() = default;
+
+ tracked_allocator& operator=(const tracked_allocator&) = default;
+ tracked_allocator(const tracked_allocator&) = default;
+
+ public:
+ using pointer_type = T*;
+
+ template <typename... U>
+ void retain(pointer_type& ptr, U&&... args)
+ {
+ ptr = new T(std::forward<U>(args)...);
+
+ if (ptr)
+ {
+ ++allocated_count_;
+ return;
+ }
+
+ throw std::bad_alloc();
+ }
+
+ template <typename... U>
+ void must_retain(pointer_type& ptr, U&&... args) noexcept
+ {
+ this->retain(ptr, args...);
+ }
+
+ void dispose(pointer_type& ptr) noexcept
+ {
+ if (ptr)
+ {
+ if (allocated_count_)
+ --allocated_count_;
+
+ ++deallocated_count_;
+
+ delete ptr;
+ ptr = nullptr;
+ }
+ }
+ };
+
+ template <typename T>
+ class tracked_mgr
+ {
+ private:
+ tracked_allocator<T> allocator_;
+
+ public:
+ explicit tracked_mgr() = default;
+ virtual ~tracked_mgr() = default;
+
+ tracked_mgr& operator=(const tracked_mgr&) = default;
+ tracked_mgr(const tracked_mgr&) = default;
+
+ public:
+ using pointer_type = T*;
+
+ const tracked_allocator<T>& allocator() noexcept
+ {
+ return allocator_;
+ }
+
+ template <typename... U>
+ pointer_type retain(U&&... args)
+ {
+ pointer_type ptr = nullptr;
+ allocator_.retain(ptr, std::forward<U>(args)...);
+
+ return ptr;
+ }
+
+ template <typename... U>
+ pointer_type must_retain(U&&... args) noexcept
+ {
+ return this->retain(std::forward<U>(args)...);
+ }
+
+ void dispose(pointer_type& ptr) noexcept
+ {
+ allocator_.dispose(ptr);
+ }
+ };
+
+ template <typename T, typename Mgr = tracked_mgr<T>>
+ class tracked_ptr
+ {
+ public:
+ static Mgr& manager() noexcept
+ {
+ static Mgr mgr;
+ return mgr;
+ }
+
+ public:
+ template <typename... U>
+ tracked_ptr(U&&... args)
+ : ptr_(nullptr)
+ {
+ ptr_ = tracked_ptr::manager().retain(std::forward<U>(args)...);
+ }
+
+ virtual ~tracked_ptr() noexcept
+ {
+ this->reset();
+ }
+
+ tracked_ptr(const tracked_ptr&) = delete;
+ tracked_ptr& operator=(const tracked_ptr&) = delete;
+
+ public:
+ using pointer_type = T*;
+
+ void reset()
+ {
+ if (ptr_)
+ {
+ tracked_ptr::manager().dispose(ptr_);
+ }
+ }
+
+ pointer_type get() const
+ {
+ return ptr_;
+ }
+
+ pointer_type data()
+ {
+ return ptr_;
+ }
+
+ T& operator*() const
+ {
+ return *ptr_;
+ }
+
+ pointer_type operator->() const
+ {
+ return ptr_;
+ }
+
+ explicit operator bool() const
+ {
+ return ptr_ != nullptr;
+ }
+
+ void swap(tracked_ptr& other)
+ {
+ std::swap(ptr_, other.ptr_);
+ }
+
+ public:
+ tracked_ptr(tracked_ptr&& other) noexcept
+ : ptr_(other.ptr_)
+ {
+ other.ptr_ = nullptr;
+ }
+
+ tracked_ptr& operator=(tracked_ptr&& other) noexcept
+ {
+ if (this != &other)
+ {
+ this->reset();
+ ptr_ = other.ptr_;
+ other.ptr_ = nullptr;
+ }
+
+ return *this;
+ }
+
+ private:
+ pointer_type ptr_{nullptr};
+ };
+
+ template <typename T>
+ inline auto make_tracked() -> tracked_ptr<T>
+ {
+ return tracked_ptr<T>();
+ }
+
+ template <typename U, typename... T>
+ inline auto make_tracked(T&&... arg) -> tracked_ptr<U>
+ {
+ return tracked_ptr<U>(std::forward<T>(arg)...);
+ }
+
+ template <typename T>
+ inline void swap(tracked_ptr<T>& a, tracked_ptr<T>& b)
+ {
+ a.swap(b);
+ }
+
+ /// @brief a Must Pass function is a standard way to verify a container' validity, inspired from NeKernel/VMKernel.
+ template <typename T, typename error_handler>
+ inline void must_pass(tracked_ptr<T>& ptr, error_handler handler)
+ {
+ if (ptr.manager().allocator().allocated_count_ < ptr.manager().allocator().deallocated_count_)
+ {
+ handler.template error<true>("Invalid TrackedPtr detected: Deallocated count exceeds allocated count.");
+ }
+ }
+} // namespace ocl::memory