From d2619b2d7c0aa2d976e1fe7623d04bb8da7f5891 Mon Sep 17 00:00:00 2001 From: Valentin B Date: Tue, 27 Aug 2019 13:46:40 +0200 Subject: [PATCH 01/15] Make fix_codestyle executable under Linux and apply it to source files --- libhydrosphere/fix_codestyle | 0 libhydrosphere/include/hs/diag/diag_api.hpp | 33 +++--- libhydrosphere/include/hs/diag/diag_macro.hpp | 31 ++--- libhydrosphere/include/hs/hs_macro.hpp | 4 +- libhydrosphere/include/hs/hs_result.hpp | 11 +- libhydrosphere/include/hs/os/os_api.hpp | 1 - .../include/hs/os/os_barrier_api.hpp | 11 +- .../hs/os/os_condition_variable_api.hpp | 24 ++-- .../hs/os/os_condition_variable_impl.hpp | 26 +++-- .../include/hs/os/os_critical_section.hpp | 15 +-- .../include/hs/os/os_kernel_event_api.hpp | 22 ++-- libhydrosphere/include/hs/os/os_mutex_api.hpp | 10 +- .../include/hs/os/os_thread_api.hpp | 36 +++--- libhydrosphere/include/hs/os/os_tls.hpp | 5 +- .../include/hs/os/os_user_event_api.hpp | 12 +- libhydrosphere/include/hs/svc/svc_types.hpp | 5 +- libhydrosphere/include/hs/util/util_api.hpp | 4 +- .../include/hs/util/util_intrusive_list.hpp | 107 +++++++++++------- .../include/hs/util/util_object_storage.hpp | 15 +-- .../include/hs/util/util_optional.hpp | 20 ++-- .../include/hs/util/util_template_api.hpp | 16 +-- .../source/common/compiler/memcpy.cpp | 7 +- .../source/common/init/initialization.cpp | 2 +- .../source/common/os/detail/os_threadlist.hpp | 4 +- .../os/detail/os_virtualmemory_allocator.hpp | 4 +- .../common/os/os_condition_variable_api.cpp | 8 +- .../common/os/os_condition_variable_impl.cpp | 2 +- .../source/common/os/os_critical_section.cpp | 6 +- .../source/common/os/os_kernelevent_api.cpp | 11 +- .../source/common/os/os_thread_api.cpp | 11 +- 30 files changed, 254 insertions(+), 209 deletions(-) mode change 100644 => 100755 libhydrosphere/fix_codestyle diff --git a/libhydrosphere/fix_codestyle b/libhydrosphere/fix_codestyle old mode 100644 new mode 100755 diff --git a/libhydrosphere/include/hs/diag/diag_api.hpp b/libhydrosphere/include/hs/diag/diag_api.hpp index a591797..61bc02d 100644 --- a/libhydrosphere/include/hs/diag/diag_api.hpp +++ b/libhydrosphere/include/hs/diag/diag_api.hpp @@ -23,31 +23,38 @@ namespace hs::diag { /** * \short Causes abnormal process termination. - * - * This send abort information to an availaible logger (currently only hs::svc::OutputDebugString) before calling hs::svc::Break. - * - * \remark In the future, this will propagate the abort to an observer for better debugging capabilities. + * + * This send abort information to an availaible logger (currently only + * hs::svc::OutputDebugString) before calling hs::svc::Break. + * + * \remark In the future, this will propagate the abort to an observer for + * better debugging capabilities. */ void Abort(const char *failed_condition, const char *file_name, const char *function_name, int line_number) noexcept; /** * \short Causes abnormal process termination with a custom message. - * - * This send abort information to an availaible logger (currently only hs::svc::OutputDebugString) before calling hs::svc::Break. - * - * \remark In the future, this will propagate the abort to an observer for better debugging capabilities. + * + * This send abort information to an availaible logger (currently only + * hs::svc::OutputDebugString) before calling hs::svc::Break. + * + * \remark In the future, this will propagate the abort to an observer for + * better debugging capabilities. */ void Abort(const char *failed_condition, const char *file_name, const char *function_name, int line_number, const char *format, ...) noexcept; /** - * \short Causes abnormal process termination with a hs::Result and a custom message. - * - * This send abort information to an availaible logger (currently only hs::svc::OutputDebugString) before calling hs::svc::Break. - * - * \remark In the future, this will propagate the abort to an observer for better debugging capabilities. + * \short Causes abnormal process termination with a hs::Result and a custom + * message. + * + * This send abort information to an availaible logger (currently only + * hs::svc::OutputDebugString) before calling hs::svc::Break. + * + * \remark In the future, this will propagate the abort to an observer for + * better debugging capabilities. */ void Abort(const char *failed_condition, const char *file_name, const char *function_name, int line_number, const hs::Result *result, diff --git a/libhydrosphere/include/hs/diag/diag_macro.hpp b/libhydrosphere/include/hs/diag/diag_macro.hpp index e85324e..97a0bc5 100644 --- a/libhydrosphere/include/hs/diag/diag_macro.hpp +++ b/libhydrosphere/include/hs/diag/diag_macro.hpp @@ -22,34 +22,37 @@ /** * \def __HS_ABORT_CONDITIONAL(condition, ...) - * \short Calls hs::diag::Abort with a given formatable message if the condition evaluates to false. - * \remark The formatable message is striped out in release builds. -*/ + * \short Calls hs::diag::Abort with a given formatable message if the condition + * evaluates to false. \remark The formatable message is striped out in release + * builds. + */ /** * \def __HS_DEBUG_ASSERT(condition) - * \short Calls hs::diag::Abort if the condition evaluates to false in debug builds. -*/ + * \short Calls hs::diag::Abort if the condition evaluates to false in debug + * builds. + */ /** * \def __HS_ABORT() * \short Unconditionally calls hs::diag::Abort. -*/ + */ /** * \def __HS_ASSERT(condition) * \short Calls hs::diag::Abort if the condition evaluates to false. -*/ + */ /** * \def __HS_ABORT_UNLESS_NOT_NULL(ptr) * \short Calls hs::diag::Abort if the given ptr is null. -*/ + */ /** * \def __HS_ABORT_CONDITIONAL_RESULT(condition, result) - * \short Calls hs::diag::Abort with a given result if the condition evaluates to false. -*/ + * \short Calls hs::diag::Abort with a given result if the condition evaluates + * to false. + */ #ifdef HYDROSPHERE_DEBUG_DIAG #define __HS_ABORT_CONDITIONAL(condition, ...) \ @@ -65,14 +68,12 @@ #define __HS_DEBUG_ASSERT(condition, ...) #endif -#define __HS_ABORT() \ - __HS_ABORT_CONDITIONAL(false, "Unknown Hydrosphere abort") +#define __HS_ABORT() __HS_ABORT_CONDITIONAL(false, "Unknown Hydrosphere abort") #define __HS_ASSERT(condition) \ __HS_ABORT_CONDITIONAL(condition, "Assertion failed") -#define __HS_ABORT_UNLESS_NOT_NULL(ptr) \ - __HS_ASSERT(ptr != nullptr) +#define __HS_ABORT_UNLESS_NOT_NULL(ptr) __HS_ASSERT(ptr != nullptr) -#define __HS_ABORT_CONDITIONAL_RESULT(condition, result) \ +#define __HS_ABORT_CONDITIONAL_RESULT(condition, result) \ __HS_ABORT_CONDITIONAL(condition, &result, "Assertion failed") /** diff --git a/libhydrosphere/include/hs/hs_macro.hpp b/libhydrosphere/include/hs/hs_macro.hpp index 11db822..2fe51d3 100644 --- a/libhydrosphere/include/hs/hs_macro.hpp +++ b/libhydrosphere/include/hs/hs_macro.hpp @@ -21,8 +21,8 @@ #define __HS_ATTRIBUTE_ALIGNED(align) __attribute__((aligned(align))) #define __HS_ASM __asm__ -#define __HS_DISALLOW_COPY(TypeName) \ - /** \private */ \ +#define __HS_DISALLOW_COPY(TypeName) \ + /** \private */ \ TypeName(const TypeName&) = delete #define __HS_DISALLOW_ASSIGN(TypeName) \ /** \private */ \ diff --git a/libhydrosphere/include/hs/hs_result.hpp b/libhydrosphere/include/hs/hs_result.hpp index 6431e46..5162c42 100644 --- a/libhydrosphere/include/hs/hs_result.hpp +++ b/libhydrosphere/include/hs/hs_result.hpp @@ -22,11 +22,11 @@ class Result { */ uint32_t value; - public: + public: /** - * \short Construct a Result from a raw value. - * \param[in] value The raw result value that defines the new Result. - */ + * \short Construct a Result from a raw value. + * \param[in] value The raw result value that defines the new Result. + */ explicit Result(uint32_t value) noexcept : value(value) {} /** @@ -35,7 +35,8 @@ class Result { inline bool Ok() const noexcept { return value == Success; } /** - * \short Check if the raw result code value doesn't match the Result::Success value + * \short Check if the raw result code value doesn't match the + * Result::Success value */ inline bool Err() const noexcept { return !Ok(); } diff --git a/libhydrosphere/include/hs/os/os_api.hpp b/libhydrosphere/include/hs/os/os_api.hpp index 7ca4cb4..150942f 100644 --- a/libhydrosphere/include/hs/os/os_api.hpp +++ b/libhydrosphere/include/hs/os/os_api.hpp @@ -26,7 +26,6 @@ namespace hs::os { */ svc::Handle GetCurrentThreadHandle() noexcept; - /** * \short Get the pseudo thread handle. * \return The pseudo thread handle. diff --git a/libhydrosphere/include/hs/os/os_barrier_api.hpp b/libhydrosphere/include/hs/os/os_barrier_api.hpp index e48778d..fb02954 100644 --- a/libhydrosphere/include/hs/os/os_barrier_api.hpp +++ b/libhydrosphere/include/hs/os/os_barrier_api.hpp @@ -28,7 +28,7 @@ namespace hs::os { /** * \short This is the context of a barrier. - * + * * See \ref barrier_api "Barrier API" for usages. **/ struct Barrier { @@ -72,11 +72,12 @@ static_assert(hs::util::is_pod::value, "Barrier isn't pod"); /** * \short Initialize a Barrier for \c num_to_wait participating threads. * - * \remark The set of participating threads is the first \c num_to_wait threads to arrive at the synchronization point. + * \remark The set of participating threads is the first \c num_to_wait threads + * to arrive at the synchronization point. * * \param[in] barrier A pointer to a Barrier. * \param[in] number_to_wait The number of threads this barrier need to wait on. - * + * * \pre ``number_to_wait`` > 0 * \pre ``barrier`` is uninitialized. * \post ``barrier`` is initialized. @@ -87,7 +88,7 @@ void InitializeBarrier(Barrier *barrier, uint32_t number_to_wait) noexcept; * \short Blocks and arrive at the barrier's synchronization point. * * \param[in] barrier A pointer to a Barrier. - * + * * \pre ``barrier`` is initialized. * \post The thread arrived at the barrier's synchronization point. */ @@ -97,7 +98,7 @@ void AwaitBarrier(Barrier *barrier) noexcept; * \short Finalize a Barrier. * * \param[in] barrier A pointer to a Barrier. - * + * * \pre ``barrier`` is initialized. * \post ``barrier`` is uninitialized. */ diff --git a/libhydrosphere/include/hs/os/os_condition_variable_api.hpp b/libhydrosphere/include/hs/os/os_condition_variable_api.hpp index a3ef9f0..23371f2 100644 --- a/libhydrosphere/include/hs/os/os_condition_variable_api.hpp +++ b/libhydrosphere/include/hs/os/os_condition_variable_api.hpp @@ -28,7 +28,7 @@ namespace hs::os { /** * \short This is the context of a condition variable. - * + * * See \ref condition_variable_api "Condition Variable API" for usages. **/ struct ConditionVariable { @@ -51,7 +51,8 @@ struct ConditionVariable { }; /** - * \short Type that indicates whether a hs::os::WaitTimeoutConditionVariable returned because of a timeout or not. + * \short Type that indicates whether a hs::os::WaitTimeoutConditionVariable + * returned because of a timeout or not. */ enum class ConditionVariableStatus { /** @@ -65,10 +66,10 @@ enum class ConditionVariableStatus { }; static_assert(sizeof(ConditionVariable) == 0x8, -"invalid ConditionVariable size"); + "invalid ConditionVariable size"); static_assert(hs::util::is_pod::value, -"ConditionVariable isn't pod"); + "ConditionVariable isn't pod"); /** * \short Initialize a ConditionVariable. @@ -109,12 +110,14 @@ void BroadcastConditionVariable(ConditionVariable *condvar) noexcept; * \param[in] mutex A pointer to a locked Mutex. * \param[in] timeout The number of nanoseconds before timing out. * - * The execution of the current thread is blocked during ``timeout``, or until signaled (if the latter happens first). - * \pre ``condvar`` must be initialized and ``mutex`` must be locked. - * \post The thread was signaled and was unblocked, or, the ``timeout`` expired. + * The execution of the current thread is blocked during ``timeout``, or until + * signaled (if the latter happens first). \pre ``condvar`` must be initialized + * and ``mutex`` must be locked. \post The thread was signaled and was + * unblocked, or, the ``timeout`` expired. */ -ConditionVariableStatus WaitTimeoutConditionVariable( - ConditionVariable *condvar, Mutex *mutex, int64_t timeout) noexcept; +ConditionVariableStatus WaitTimeoutConditionVariable(ConditionVariable *condvar, + Mutex *mutex, + int64_t timeout) noexcept; /** * \short Wait until signaled. * @@ -125,8 +128,7 @@ ConditionVariableStatus WaitTimeoutConditionVariable( * \pre ``condvar`` must be initialized and ``mutex`` must be locked. * \post The thread was signaled and was unblocked. */ -void WaitConditionVariable(ConditionVariable *condvar, - Mutex *mutex) noexcept; +void WaitConditionVariable(ConditionVariable *condvar, Mutex *mutex) noexcept; /** * \short Finalize a ConditionVariable. diff --git a/libhydrosphere/include/hs/os/os_condition_variable_impl.hpp b/libhydrosphere/include/hs/os/os_condition_variable_impl.hpp index 91390a0..fc79e09 100644 --- a/libhydrosphere/include/hs/os/os_condition_variable_impl.hpp +++ b/libhydrosphere/include/hs/os/os_condition_variable_impl.hpp @@ -19,45 +19,49 @@ namespace hs::os { /** * \short Condition Variable implementation. - * - * \remark A condition variable is an object able to block the calling thread until notified to resume. + * + * \remark A condition variable is an object able to block the calling thread + * until notified to resume. */ class ConditionVariableImpl { - private: + private: uint_fast32_t image; - public: + public: /** * \short Signal one. - * + * * Unblocks one of the threads currently waiting for this condition. */ void Signal(void) noexcept; /** * \short Signal all (Broadcast). - * + * * Unblocks all threads currently waiting for this condition. */ void Broadcast(void) noexcept; /** * \short Wait until signaled. - * - * The execution of the current thread (which shall have entered the critial section) is blocked until signaled. + * + * The execution of the current thread (which shall have entered the critial + * section) is blocked until signaled. */ void Wait(CriticalSection *critical_section) noexcept; /** * \short Wait for timeout or until signaled. - * - * The execution of the current thread (which shall have entered the critial section) is blocked during \c timeout, or until signaled (if the latter happens first). + * + * The execution of the current thread (which shall have entered the critial + * section) is blocked during \c timeout, or until signaled (if the latter + * happens first). */ bool WaitTimeout(CriticalSection *critical_section, int64_t timeout) noexcept; }; static_assert(hs::util::is_pod::value, -"ConditionVariableImpl isn't pod"); + "ConditionVariableImpl isn't pod"); } // namespace hs::os diff --git a/libhydrosphere/include/hs/os/os_critical_section.hpp b/libhydrosphere/include/hs/os/os_critical_section.hpp index 069cb22..f31ab2e 100644 --- a/libhydrosphere/include/hs/os/os_critical_section.hpp +++ b/libhydrosphere/include/hs/os/os_critical_section.hpp @@ -19,14 +19,14 @@ namespace hs::os { /** * \short Critical Section implementation. - * + * * \remark CriticalSection ensures mutual exclusion of access. */ class CriticalSection { - private: + private: volatile _Atomic(uint_fast32_t) image; - public: + public: /** * \short Enter the critical section. */ @@ -42,13 +42,14 @@ class CriticalSection { */ void Leave() noexcept; - /** - * \short Returns true if the current thread owns the lock of the critical section. - */ + /** + * \short Returns true if the current thread owns the lock of the critical + * section. + */ bool IsLockedByCurrentThread() noexcept; }; static_assert(hs::util::is_pod::value, -"CriticalSection isn't pod"); + "CriticalSection isn't pod"); } // namespace hs::os diff --git a/libhydrosphere/include/hs/os/os_kernel_event_api.hpp b/libhydrosphere/include/hs/os/os_kernel_event_api.hpp index 2e32710..c0cfcd6 100644 --- a/libhydrosphere/include/hs/os/os_kernel_event_api.hpp +++ b/libhydrosphere/include/hs/os/os_kernel_event_api.hpp @@ -14,8 +14,8 @@ #include #include #include -#include #include +#include namespace hs::os { /** @@ -30,7 +30,7 @@ namespace hs::os { /** * \short This is the context of a kernel event. - * + * * See \ref kernel_event_api "Kernel Event API" for usages. **/ struct KernelEvent { @@ -42,7 +42,8 @@ struct KernelEvent { /** * \private - * \short True if the KernelEvent must be automatically cleared after a wait operation. + * \short True if the KernelEvent must be automatically cleared after a wait + * operation. */ bool is_auto_clear; @@ -66,27 +67,26 @@ struct KernelEvent { }; static_assert(sizeof(KernelEvent) == 0x14, "invalid KernelEvent size"); -static_assert(hs::util::is_pod::value, - "KernelEvent isn't pod"); +static_assert(hs::util::is_pod::value, "KernelEvent isn't pod"); /** * \short Create a KernelEvent. * * \param[in] event A pointer to a KernelEvent. - * \param[in] is_auto_clear True if the KernelEvent must be automatically cleared after a wait operation. + * \param[in] is_auto_clear True if the KernelEvent must be automatically + * cleared after a wait operation. * * \pre ``event`` is uninitialized. * \post ``event`` is initialized. */ -hs::Result CreateKernelEvent(KernelEvent *event, - bool is_auto_clear) noexcept; +hs::Result CreateKernelEvent(KernelEvent *event, bool is_auto_clear) noexcept; /** * \short Load a KernelEvent from raw handles. - * + * * \param[in] event A pointer to a KernelEvent. * \param[in] readable_handle An Optional readable handle. * \param[in] writable_handle An Optional writable handle. - * + * * \pre ``event`` is uninitialized. * \pre ``readable_handle`` or ``writable_handle`` contain a value. * \post ``event`` is initialized. @@ -108,7 +108,7 @@ void WaitKernelEvent(KernelEvent *event) noexcept; /** * \short Get the signal state of a KernelEvent. - * + * * \param[in] event A pointer to a KernelEvent. * \pre ``event`` is initialized. * \pre ``event`` contains a readable handle. diff --git a/libhydrosphere/include/hs/os/os_mutex_api.hpp b/libhydrosphere/include/hs/os/os_mutex_api.hpp index 6ada789..9b9f64d 100644 --- a/libhydrosphere/include/hs/os/os_mutex_api.hpp +++ b/libhydrosphere/include/hs/os/os_mutex_api.hpp @@ -13,8 +13,8 @@ #include #include #include -#include #include +#include namespace hs::os { /** @@ -28,7 +28,7 @@ namespace hs::os { /** * \short This is the context of a mutex. - * + * * See \ref mutex_api "Mutex API" for usages. **/ struct Mutex { @@ -87,7 +87,8 @@ void InitializeMutex(Mutex *mutex, bool is_recursive) noexcept; * \short Lock Mutex. * The calling thread locks the mutex, blocking if necessary. * - * \remark If the mutex wasn't initialized as recursive and if it is currently locked by the same thread calling this function, it produces a deadlock. + * \remark If the mutex wasn't initialized as recursive and if it is currently + * locked by the same thread calling this function, it produces a deadlock. * * \param[in] mutex A pointer to a Mutex. * @@ -104,7 +105,8 @@ void LockMutex(Mutex *mutex) noexcept; * \pre ``mutex`` is initialized. * \post The lock was acquired or is owned by another thread. * - * \return true if the function succeeds in locking the mutex for the thread. false otherwise. + * \return true if the function succeeds in locking the mutex for the thread. + * false otherwise. */ bool TryLockMutex(Mutex *mutex) noexcept; diff --git a/libhydrosphere/include/hs/os/os_thread_api.hpp b/libhydrosphere/include/hs/os/os_thread_api.hpp index 1cbb9e7..d701424 100644 --- a/libhydrosphere/include/hs/os/os_thread_api.hpp +++ b/libhydrosphere/include/hs/os/os_thread_api.hpp @@ -43,7 +43,8 @@ const size_t THREAD_NAME_SIZE = 0x20; */ enum class ThreadState { /** - * \short The Thread is uninitialized and can be initialized by using hs::os::CreateThread. + * \short The Thread is uninitialized and can be initialized by using + * hs::os::CreateThread. */ Uninitialized, /** @@ -66,7 +67,7 @@ enum class ThreadState { /** * \short This is the context of a thread. - * + * * See \ref thread_api "Thread API" for usages. **/ struct Thread : public hs::util::IntrusiveListElement<> { @@ -108,13 +109,15 @@ struct Thread : public hs::util::IntrusiveListElement<> { /** * \private - * \short The memory mirror of the ``original_thread_stack`` mapped in the Stack region. + * \short The memory mirror of the ``original_thread_stack`` mapped in the + * Stack region. */ void *mapped_thread_stack; /** * \private - * \short True if the ``original_thread_stack`` is mapped in the Stack region. + * \short True if the ``original_thread_stack`` is mapped in the Stack + * region. */ bool is_alias_thread_stack_mapped; @@ -148,11 +151,14 @@ struct Thread : public hs::util::IntrusiveListElement<> { * * \param[in] thread A pointer to a Thread. * \param[in] thread_entrypoint The entrypoint of the Thread. - * \param[in] argument The argument to pass to the entrypoint when starting the Thread. - * \param[in] stack A pointer to a memory region that will be used as a stack by the Thread. - * \param[in] stack_size The size of the stack (must be page aligned). - * \param[in] priority The priority of the Thread (0x2C is the usual priority of the main thread. 0x3B on core 0 to 2 and 0x3F on core 3 is a special priority that enables preemptive multithreading). - * \param[in] cpuid The ID of the CPU core to use (-2 means the default core of the current process). + * \param[in] argument The argument to pass to the entrypoint when starting the + * Thread. \param[in] stack A pointer to a memory region that will be used as a + * stack by the Thread. \param[in] stack_size The size of the stack (must be + * page aligned). \param[in] priority The priority of the Thread (0x2C is the + * usual priority of the main thread. 0x3B on core 0 to 2 and 0x3F on core 3 is + * a special priority that enables preemptive multithreading). \param[in] cpuid + * The ID of the CPU core to use (-2 means the default core of the current + * process). * * \pre ``thread`` state is ThreadState::Uninitialized. * \pre ``thread_entrypoint`` is not a null pointer. @@ -173,8 +179,10 @@ hs::Result CreateThread(Thread *thread, * * This function has the following behaviours: * - * - If the ``thread`` state is ThreadState::Initialized, the thread is started and signaled as ThreadState::Destroyed (The thread will imediately exit). - * - It waits for the Thread to exit and ensures that the Thread stack mirror is unmapped if needed. + * - If the ``thread`` state is ThreadState::Initialized, the thread is started + * and signaled as ThreadState::Destroyed (The thread will imediately exit). + * - It waits for the Thread to exit and ensures that the Thread stack mirror is + * unmapped if needed. * * \param[in] thread A pointer to a Thread. * \pre ``thread`` state is **not** ThreadState::Uninitialized. @@ -203,7 +211,8 @@ void WaitThread(Thread *thread) noexcept; /** * \short Yield to other threads. * - * This gives a hint to the scheduler that the current thread is willing to yield its current use of a CPU core. + * This gives a hint to the scheduler that the current thread is willing to + * yield its current use of a CPU core. */ void YieldThread(void) noexcept; @@ -228,7 +237,7 @@ Thread *GetCurrentThread(void) noexcept; /** * \short Change a Thread priority. - * + * * This return the previous thread priority. * \pre ``thread`` state is **not** ThreadState::Uninitialized. * \post ``thread`` priority is now ``priority``. @@ -242,7 +251,6 @@ int ChangeThreadPriority(Thread *thread, int priority) noexcept; */ int GetOriginalThreadPriority(Thread *thread) noexcept; - /** * \short Get the current Thread priority. * diff --git a/libhydrosphere/include/hs/os/os_tls.hpp b/libhydrosphere/include/hs/os/os_tls.hpp index 751c627..9faea09 100644 --- a/libhydrosphere/include/hs/os/os_tls.hpp +++ b/libhydrosphere/include/hs/os/os_tls.hpp @@ -23,7 +23,7 @@ namespace hs::os { * \private */ class ThreadLocalStorage { - public: + public: /** * The IPC command buffer. */ @@ -35,7 +35,6 @@ class ThreadLocalStorage { */ static ThreadLocalStorage *GetThreadLocalStorage() noexcept; - /** * Get the thread context of the current thread. */ @@ -48,7 +47,7 @@ class ThreadLocalStorage { this->context = thread_context; } - private: + private: /** * The thread context attached to this TLS storage. */ diff --git a/libhydrosphere/include/hs/os/os_user_event_api.hpp b/libhydrosphere/include/hs/os/os_user_event_api.hpp index 360404b..69e9849 100644 --- a/libhydrosphere/include/hs/os/os_user_event_api.hpp +++ b/libhydrosphere/include/hs/os/os_user_event_api.hpp @@ -29,7 +29,7 @@ namespace hs::os { /** * \short This is the context of a user event. - * + * * See \ref user_event_api "User Event API" for usages. **/ struct UserEvent { @@ -53,7 +53,8 @@ struct UserEvent { /** * \private - * \short True if the UserEvent must be automatically cleared after a wait operation. + * \short True if the UserEvent must be automatically cleared after a wait + * operation. */ bool is_auto_clear; @@ -77,8 +78,9 @@ static_assert(hs::util::is_pod::value, "UserEvent isn't pod"); * \short Create a UserEvent. * * \param[in] event A pointer to a UserEvent. - * \param[in] is_signaled_at_init True if the UserEvent must be automatically signaled after the initialization. - * \param[in] is_auto_clear True if the UserEvent must be automatically cleared after a wait operation. + * \param[in] is_signaled_at_init True if the UserEvent must be automatically + * signaled after the initialization. \param[in] is_auto_clear True if the + * UserEvent must be automatically cleared after a wait operation. * * \pre ``event`` is uninitialized. * \post ``event`` is initialized. @@ -97,7 +99,7 @@ void WaitUserEvent(UserEvent *event) noexcept; /** * \short Get the signal state of a UserEvent. - * + * * \param[in] event A pointer to a UserEvent. * \pre ``event`` is initialized. * \return true if the ``event`` has been signaled. diff --git a/libhydrosphere/include/hs/svc/svc_types.hpp b/libhydrosphere/include/hs/svc/svc_types.hpp index 01fecdd..7dd0b80 100644 --- a/libhydrosphere/include/hs/svc/svc_types.hpp +++ b/libhydrosphere/include/hs/svc/svc_types.hpp @@ -21,14 +21,14 @@ namespace svc { * \short Opaque type representing an Horizon Handle. */ class Handle { - private: + private: /** * \private * \short The raw handle value. */ uint32_t value; - public: + public: /** * \short Returns the raw handle value stored inside Handle. */ @@ -58,7 +58,6 @@ class Handle { static_assert(hs::util::is_pod::value, "Handle isn't pod"); - inline bool operator==(Handle a, Handle b) noexcept { return a.GetValue() == b.GetValue(); } diff --git a/libhydrosphere/include/hs/util/util_api.hpp b/libhydrosphere/include/hs/util/util_api.hpp index 9fe3847..68f30b5 100644 --- a/libhydrosphere/include/hs/util/util_api.hpp +++ b/libhydrosphere/include/hs/util/util_api.hpp @@ -55,7 +55,7 @@ inline int SNPrintf(char *str, size_t size, const char *format, ...) noexcept { /** * \def __HS_DEBUG_LOG(...) * \short printf helper to hs::svc::OutputDebugString -*/ + */ #define __HS_DEBUG_LOG(...) \ { \ char log_buf[0x200]; \ @@ -66,7 +66,7 @@ inline int SNPrintf(char *str, size_t size, const char *format, ...) noexcept { /** * \def __HS_DEBUG_LOG_VARGS(...) * \short vprintf helper to hs::svc::OutputDebugString -*/ + */ #define __HS_DEBUG_LOG_VARGS(format, va_args) \ { \ char log_buf[0x200]; \ diff --git a/libhydrosphere/include/hs/util/util_intrusive_list.hpp b/libhydrosphere/include/hs/util/util_intrusive_list.hpp index 4878975..8e42bc4 100644 --- a/libhydrosphere/include/hs/util/util_intrusive_list.hpp +++ b/libhydrosphere/include/hs/util/util_intrusive_list.hpp @@ -16,20 +16,22 @@ namespace hs::util { /** - * \short default_intrusive_tag as defined in [P0406-r1](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0406r1.html#list) + * \short default_intrusive_tag as defined in + * [P0406-r1](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0406r1.html#list) */ struct DefaultIntrusiveTag; /** - * \short intrusive_list_element as defined in [P0406-r1](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0406r1.html#list) + * \short intrusive_list_element as defined in + * [P0406-r1](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0406r1.html#list) */ template class IntrusiveListElement { - private: + private: IntrusiveListElement* prev; IntrusiveListElement* next; - public: + public: IntrusiveListElement() { prev = this; next = this; @@ -108,12 +110,13 @@ class IntrusiveListElement { }; /** - * \short Partial implementation of intrusive_list as defined in [P0406-r1](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0406r1.html#list) + * \short Partial implementation of intrusive_list as defined in + * [P0406-r1](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0406r1.html#list) * \remark This doesn't implement any methods related to the std namespace. */ template class IntrusiveList { - public: + public: __HS_DISALLOW_COPY(IntrusiveList); /** @@ -127,7 +130,8 @@ class IntrusiveList { typedef value_type& reference; /** - * \short The type of a const reference to an element the iterator can point to. + * \short The type of a const reference to an element the iterator can point + * to. */ typedef const value_type& const_reference; @@ -140,7 +144,8 @@ class IntrusiveList { typedef int size_type; /** - * \short Type to express the result of subtracting one iterator from another. + * \short Type to express the result of subtracting one iterator from + * another. */ typedef int difference_type; // We don't have the standard library. @@ -149,7 +154,7 @@ class IntrusiveList { // Define iterators implementation class const_iterator { - public: + public: friend class iterator; friend class IntrusiveList; @@ -201,12 +206,12 @@ class IntrusiveList { return value != target.value; } - private: + private: const_pointer value; }; class iterator { - public: + public: friend class const_iterator; friend class IntrusiveList; @@ -258,7 +263,7 @@ class IntrusiveList { return value != target.value; } - private: + private: pointer value; }; @@ -276,24 +281,28 @@ class IntrusiveList { // Iterators /** - * \short Returns an iterator pointing to the first element in the container. + * \short Returns an iterator pointing to the first element in the + * container. */ iterator begin() noexcept { return iterator(root.GetNext()); } /** - * \short Returns an const_iterator pointing to the first element in the container. + * \short Returns an const_iterator pointing to the first element in the + * container. */ const_iterator begin() const noexcept { return const_iterator(root.GetNext()); } /** - * \short Returns an iterator referring to the past-the-end element in the container. + * \short Returns an iterator referring to the past-the-end element in the + * container. */ iterator end() noexcept { return iterator(&root); } /** - * \short Returns an const_iterator referring to the past-the-end element in the container. + * \short Returns an const_iterator referring to the past-the-end element in + * the container. */ const_iterator end() const noexcept { return const_iterator(&root); } @@ -304,17 +313,21 @@ class IntrusiveList { const_reverse_iterator rend() const noexcept;*/ /** - * \short Returns a const_iterator pointing to the first element in the container. - * - * \warning If the container is empty, the returned iterator value shall not be dereferenced. + * \short Returns a const_iterator pointing to the first element in the + * container. + * + * \warning If the container is empty, the returned iterator value shall not + * be dereferenced. */ const_iterator cbegin() const noexcept { return this->begin(); } /** - * \short Returns a const_iterator pointing to the past-the-end element in the container. - * - * If the container is empty, this function returns the same as IntrusiveList::cbegin. - * \warning The value returned shall not be dereferenced. + * \short Returns a const_iterator pointing to the past-the-end element in + * the container. + * + * If the container is empty, this function returns the same as + * IntrusiveList::cbegin. \warning The value returned shall not be + * dereferenced. */ const_iterator cend() const noexcept { return this->end(); } // We don't have the standard library. @@ -341,8 +354,9 @@ class IntrusiveList { /** * \short Returns a reference to the first element in the container. * - * Unlike member IntrusiveList::begin, which returns an iterator to this same element, this function returns a direct reference. - * \warning Calling this function on an empty container causes undefined behavior. + * Unlike member IntrusiveList::begin, which returns an iterator to this + * same element, this function returns a direct reference. \warning Calling + * this function on an empty container causes undefined behavior. */ reference front() noexcept { return IntrusiveListElement::template GetElement( @@ -352,8 +366,9 @@ class IntrusiveList { /** * \short Returns a reference to the first element in the container. * - * Unlike member IntrusiveList::cbegin, which returns an iterator to this same element, this function returns a direct reference. - * \warning Calling this function on an empty container causes undefined behavior. + * Unlike member IntrusiveList::cbegin, which returns an iterator to this + * same element, this function returns a direct reference. \warning Calling + * this function on an empty container causes undefined behavior. */ const_reference front() const noexcept { return IntrusiveListElement::template GetElement( @@ -363,8 +378,9 @@ class IntrusiveList { /** * \short Returns a reference to the last element in the container. * - * Unlike member IntrusiveList::cbegin, which returns an iterator to this same element, this function returns a direct reference. - * \warning Calling this function on an empty container causes undefined behavior. + * Unlike member IntrusiveList::cbegin, which returns an iterator to this + * same element, this function returns a direct reference. \warning Calling + * this function on an empty container causes undefined behavior. */ reference back() noexcept { return IntrusiveListElement::template GetElement( @@ -374,8 +390,9 @@ class IntrusiveList { /** * \short Returns a reference to the last element in the container. * - * Unlike member IntrusiveList::cbegin, which returns an iterator to this same element, this function returns a direct reference. - * \warning Calling this function on an empty container causes undefined behavior. + * Unlike member IntrusiveList::cbegin, which returns an iterator to this + * same element, this function returns a direct reference. \warning Calling + * this function on an empty container causes undefined behavior. */ const_reference back() const noexcept { return IntrusiveListElement::template GetElement( @@ -383,31 +400,37 @@ class IntrusiveList { } /** - * \short Adds a new element at the start of the container after its current first element. - * + * \short Adds a new element at the start of the container after its current + * first element. + * * \remark This effectively increases the container size by one. */ void push_front(T& x) noexcept { this->root.LinkNext(&x); } /** - * \short Adds a new element at the end of the container after its current last element. - * + * \short Adds a new element at the end of the container after its current + * last element. + * * \remark This effectively increases the container size by one. */ void push_back(T& x) noexcept { this->root.LinkPrev(&x); } /** - * \short Removes the last element in the container, effectively reducing the container size by one. + * \short Removes the last element in the container, effectively reducing + * the container size by one. */ void pop_back() noexcept { this->root.GetPrev()->Unlink(); } /** - * \short Removes the first element in the container, effectively reducing the container size by one. + * \short Removes the first element in the container, effectively reducing + * the container size by one. */ void pop_front() noexcept { this->root.GetNext()->Unlink(); } /** - * \short The container is extended by inserting new elements before the element at the specified position, effectively increasing the container size by the number of elements inserted. + * \short The container is extended by inserting new elements before the + * element at the specified position, effectively increasing the container + * size by the number of elements inserted. */ iterator insert(const_iterator position, T& x) noexcept { T* ref = const_cast(position.value); @@ -431,7 +454,8 @@ class IntrusiveList { /** * \short Removes from the container a range of elements. ([first,last)) - * \remark This effectively reduces the container size by the number of elements removed. + * \remark This effectively reduces the container size by the number of + * elements removed. */ iterator erase(const_iterator position, const_iterator last) noexcept { if (position == last) { @@ -445,7 +469,8 @@ class IntrusiveList { // void swap(IntrusiveList&) noexcept; /** - * \short Removes all elements from the container, leaving the container with a size of 0. + * \short Removes all elements from the container, leaving the container + * with a size of 0. */ void clear() noexcept { while (!this->empty()) { @@ -478,7 +503,7 @@ class IntrusiveList { template void sort(Compare comp); void reverse() noexcept;*/ - private: + private: IntrusiveListElement root; }; } // namespace hs::util diff --git a/libhydrosphere/include/hs/util/util_object_storage.hpp b/libhydrosphere/include/hs/util/util_object_storage.hpp index 160c474..c009f98 100644 --- a/libhydrosphere/include/hs/util/util_object_storage.hpp +++ b/libhydrosphere/include/hs/util/util_object_storage.hpp @@ -14,21 +14,23 @@ namespace hs::util { /** - * \short Obtains a POD type suitable to use as storage for an object of a size of at most Len bytes, aligned as specified by Align. - * + * \short Obtains a POD type suitable to use as storage for an object of a size + * of at most Len bytes, aligned as specified by Align. + * * The obtained type is aliased as member type aligned_storage::type. - * + * * \tparam Len The size of the storage object in bytes. * \tparam Align The alignment requested in bytes. - * + * * \pre Len shall not be zero. - * + * * \remark This is identical to libcxx's aligned_storage. */ template struct aligned_storage { /** - * \short A POD type suitable to store Len bytes, aligned as specified by Align. + * \short A POD type suitable to store Len bytes, aligned as specified by + * Align. */ struct type { alignas(Align) unsigned char data[Len]; @@ -77,7 +79,6 @@ struct ObjectStorage { inline T &operator*() noexcept { return Get(); } - inline T *operator->() noexcept { return GetPointer(); } }; } // namespace hs::util diff --git a/libhydrosphere/include/hs/util/util_optional.hpp b/libhydrosphere/include/hs/util/util_optional.hpp index b99605a..02a885f 100644 --- a/libhydrosphere/include/hs/util/util_optional.hpp +++ b/libhydrosphere/include/hs/util/util_optional.hpp @@ -18,8 +18,9 @@ namespace hs::util { * \short Obtains a POD type that manages an optional contained value. * \tparam T The object type that needs to be hold. */ -template< typename T> class Optional { - private: +template +class Optional { + private: /** * \short True if the Optional contains a value. */ @@ -34,22 +35,17 @@ template< typename T> class Optional { */ ObjectStorage value; - public: - constexpr explicit operator bool() const noexcept { - return HasValue(); - } - + public: + constexpr explicit operator bool() const noexcept { return HasValue(); } /** * \short Check whether the Optional contains a value. - */ - constexpr bool HasValue() const noexcept { - return has_value; - } + */ + constexpr bool HasValue() const noexcept { return has_value; } /** * \short Store the given value in the Optional. - * + * * \param[in] new_value the new value to move inside the Optional. */ constexpr void SetValue(T new_value) noexcept { diff --git a/libhydrosphere/include/hs/util/util_template_api.hpp b/libhydrosphere/include/hs/util/util_template_api.hpp index 1f4d52c..674639f 100644 --- a/libhydrosphere/include/hs/util/util_template_api.hpp +++ b/libhydrosphere/include/hs/util/util_template_api.hpp @@ -14,9 +14,10 @@ namespace hs::util { /** * \short integral_constant wraps a static constant of specified type. * \remark This is a simple implementation of std::integral_constant. - * \remark It is the base class for the C++ type traits. + * \remark It is the base class for the C++ type traits. */ -template struct integral_constant { +template +struct integral_constant { static constexpr T value = v; typedef T value_type; // using injected-class-name @@ -27,11 +28,12 @@ template struct integral_constant { }; /** - * \short If T is a plain old data type, that is, both trivial and standard-layout, provides the member constant value equal true. For any other type, value is false. - * \remark This is a simple implementation of std::is_pod using __is_pod from clang builtins. + * \short If T is a plain old data type, that is, both trivial and + * standard-layout, provides the member constant value equal true. For any other + * type, value is false. \remark This is a simple implementation of std::is_pod + * using __is_pod from clang builtins. */ -template struct is_pod : public integral_constant -{}; +template +struct is_pod : public integral_constant {}; } // namespace hs::util - diff --git a/libhydrosphere/source/common/compiler/memcpy.cpp b/libhydrosphere/source/common/compiler/memcpy.cpp index 4df446b..371cfbb 100644 --- a/libhydrosphere/source/common/compiler/memcpy.cpp +++ b/libhydrosphere/source/common/compiler/memcpy.cpp @@ -13,8 +13,8 @@ // We define memcpy as we don't have any libraries that can provide it. // If there is any, as this is weak, it's going to be discared. -extern "C" __HS_ATTRIBUTE_WEAK void *memcpy( - void *dst, const void *src, size_t len) { +extern "C" __HS_ATTRIBUTE_WEAK void *memcpy(void *dst, const void *src, + size_t len) { const char *from = (const char *)src; char *to = reinterpret_cast(dst); @@ -22,8 +22,7 @@ extern "C" __HS_ATTRIBUTE_WEAK void *memcpy( return dst; } -extern "C" __HS_ATTRIBUTE_WEAK void *memset( - void *s, int c, size_t n) { +extern "C" __HS_ATTRIBUTE_WEAK void *memset(void *s, int c, size_t n) { unsigned char *p = reinterpret_cast(s); while (n--) *p++ = (unsigned char)c; return s; diff --git a/libhydrosphere/source/common/init/initialization.cpp b/libhydrosphere/source/common/init/initialization.cpp index cc89c34..4eea95a 100644 --- a/libhydrosphere/source/common/init/initialization.cpp +++ b/libhydrosphere/source/common/init/initialization.cpp @@ -42,7 +42,7 @@ __HS_ATTRIBUTE_VISIBILITY_HIDDEN void InitMainThread( tls_storage->SetThreadContext(&thread_list->GetMainThread()); } -extern"C" void hsMain(void); +extern "C" void hsMain(void); void hs::init::Start(uint64_t thread_handle, uintptr_t argument_address, void (*notify_exception_handler_ready)(), diff --git a/libhydrosphere/source/common/os/detail/os_threadlist.hpp b/libhydrosphere/source/common/os/detail/os_threadlist.hpp index ebb4e0f..ba7f788 100644 --- a/libhydrosphere/source/common/os/detail/os_threadlist.hpp +++ b/libhydrosphere/source/common/os/detail/os_threadlist.hpp @@ -19,12 +19,12 @@ namespace hs::os::detail { class ThreadList { - private: + private: hs::os::CriticalSection critical_section; hs::util::IntrusiveList list; hs::os::Thread main_thread; - public: + public: explicit ThreadList(hs::svc::Handle thread_handle) : critical_section(), list(), main_thread() { main_thread.thread_handle = thread_handle; diff --git a/libhydrosphere/source/common/os/detail/os_virtualmemory_allocator.hpp b/libhydrosphere/source/common/os/detail/os_virtualmemory_allocator.hpp index 6184263..7576acb 100644 --- a/libhydrosphere/source/common/os/detail/os_virtualmemory_allocator.hpp +++ b/libhydrosphere/source/common/os/detail/os_virtualmemory_allocator.hpp @@ -18,7 +18,7 @@ namespace hs::os::detail { class VirtualMemoryAllocator { - private: + private: hs::os::CriticalSection critical_section; uintptr_t address_space_start; uintptr_t address_space_end; @@ -31,7 +31,7 @@ class VirtualMemoryAllocator { (target_address < end_address); } - public: + public: VirtualMemoryAllocator(uintptr_t address_space_start, uintptr_t address_space_end, size_t guard_page_size) noexcept diff --git a/libhydrosphere/source/common/os/os_condition_variable_api.cpp b/libhydrosphere/source/common/os/os_condition_variable_api.cpp index c836285..b73198c 100644 --- a/libhydrosphere/source/common/os/os_condition_variable_api.cpp +++ b/libhydrosphere/source/common/os/os_condition_variable_api.cpp @@ -31,8 +31,9 @@ void BroadcastConditionVariable(ConditionVariable *condvar) noexcept { condvar->condition_variable.Broadcast(); } -ConditionVariableStatus WaitTimeoutConditionVariable( - ConditionVariable *condvar, Mutex *mutex, int64_t timeout) noexcept { +ConditionVariableStatus WaitTimeoutConditionVariable(ConditionVariable *condvar, + Mutex *mutex, + int64_t timeout) noexcept { if (!condvar->condition_variable.WaitTimeout(&mutex->critical_section, timeout)) { return ConditionVariableStatus::TimeOut; @@ -41,8 +42,7 @@ ConditionVariableStatus WaitTimeoutConditionVariable( return ConditionVariableStatus::NoTimeOut; } -void WaitConditionVariable(ConditionVariable *condvar, - Mutex *mutex) noexcept { +void WaitConditionVariable(ConditionVariable *condvar, Mutex *mutex) noexcept { condvar->condition_variable.Wait(&mutex->critical_section); } diff --git a/libhydrosphere/source/common/os/os_condition_variable_impl.cpp b/libhydrosphere/source/common/os/os_condition_variable_impl.cpp index 4cc6dc7..742d573 100644 --- a/libhydrosphere/source/common/os/os_condition_variable_impl.cpp +++ b/libhydrosphere/source/common/os/os_condition_variable_impl.cpp @@ -9,8 +9,8 @@ */ #include -#include #include +#include #include #include diff --git a/libhydrosphere/source/common/os/os_critical_section.cpp b/libhydrosphere/source/common/os/os_critical_section.cpp index 76fef35..54090a0 100644 --- a/libhydrosphere/source/common/os/os_critical_section.cpp +++ b/libhydrosphere/source/common/os/os_critical_section.cpp @@ -45,9 +45,9 @@ void CriticalSection::Enter() noexcept { continue; } else { hs::svc::ArbitrateLock( - hs::svc::Handle::FromRawValue(expected_value), - reinterpret_cast(&this->image), - self_thread_handle); + hs::svc::Handle::FromRawValue(expected_value), + reinterpret_cast(&this->image), + self_thread_handle); } } } diff --git a/libhydrosphere/source/common/os/os_kernelevent_api.cpp b/libhydrosphere/source/common/os/os_kernelevent_api.cpp index 11171ef..e3d19fb 100644 --- a/libhydrosphere/source/common/os/os_kernelevent_api.cpp +++ b/libhydrosphere/source/common/os/os_kernelevent_api.cpp @@ -18,12 +18,10 @@ enum KernelEventState { namespace hs::os { -hs::Result CreateKernelEvent(KernelEvent *event, - bool is_auto_clear) noexcept { +hs::Result CreateKernelEvent(KernelEvent *event, bool is_auto_clear) noexcept { svc::Handle readable_handle; svc::Handle writable_handle; - auto result = - hs::svc::CreateEvent(&writable_handle, &readable_handle); + auto result = hs::svc::CreateEvent(&writable_handle, &readable_handle); if (result.Ok()) { event->state = KernelEventState_Initialized; @@ -48,8 +46,9 @@ void WaitKernelEvent(KernelEvent *event) noexcept { int32_t index; // Wait for the event to be signaled - while (hs::svc::WaitSynchronization(&index, - event->readable_handle.GetValuePointer(), 1, -1).Err()) { + while (hs::svc::WaitSynchronization( + &index, event->readable_handle.GetValuePointer(), 1, -1) + .Err()) { } if (event->is_auto_clear) { diff --git a/libhydrosphere/source/common/os/os_thread_api.cpp b/libhydrosphere/source/common/os/os_thread_api.cpp index 3014675..0b62545 100644 --- a/libhydrosphere/source/common/os/os_thread_api.cpp +++ b/libhydrosphere/source/common/os/os_thread_api.cpp @@ -75,7 +75,7 @@ __HS_ATTRIBUTE_VISIBILITY_HIDDEN hs::Result CreateThreadUnsafe( &thread_handle, reinterpret_cast(entry_point), reinterpret_cast(thread), reinterpret_cast(thread->mapped_thread_stack) + - thread->thread_stack_size, + thread->thread_stack_size, thread->priority, cpuid); if (result.Ok()) { thread->thread_handle = thread_handle; @@ -162,8 +162,7 @@ hs::Result CreateThread(Thread *thread, reinterpret_cast(thread->mapped_thread_stack), reinterpret_cast(thread->original_thread_stack), thread->thread_stack_size); - hs::os::detail::g_StackAllocator->Free( - thread->mapped_thread_stack); + hs::os::detail::g_StackAllocator->Free(thread->mapped_thread_stack); } // TODO(Kaenbyō): incremental thread name (with the number of the thread) @@ -206,8 +205,7 @@ void DestroyThread(Thread *thread) noexcept { reinterpret_cast(thread->mapped_thread_stack), reinterpret_cast(thread->original_thread_stack), thread->thread_stack_size); - hs::os::detail::g_StackAllocator->Free( - thread->mapped_thread_stack); + hs::os::detail::g_StackAllocator->Free(thread->mapped_thread_stack); thread->is_alias_thread_stack_mapped = false; thread->mapped_thread_stack = nullptr; } @@ -241,8 +239,7 @@ void WaitThread(Thread *thread) noexcept { reinterpret_cast(thread->mapped_thread_stack), reinterpret_cast(thread->original_thread_stack), thread->thread_stack_size); - hs::os::detail::g_StackAllocator->Free( - thread->mapped_thread_stack); + hs::os::detail::g_StackAllocator->Free(thread->mapped_thread_stack); thread->is_alias_thread_stack_mapped = false; thread->mapped_thread_stack = nullptr; } From d21a73a4f3d61f5612c3f02822db65873d91ed07 Mon Sep 17 00:00:00 2001 From: Valentin B Date: Tue, 27 Aug 2019 13:55:25 +0200 Subject: [PATCH 02/15] Implement unique_ptr with zero libc++ dependencies --- libhydrosphere/meson.build | 1 + .../source/common/compiler/unique_ptr.cpp | 118 ++++++++++++++++++ 2 files changed, 119 insertions(+) create mode 100644 libhydrosphere/source/common/compiler/unique_ptr.cpp diff --git a/libhydrosphere/meson.build b/libhydrosphere/meson.build index 01a687b..70a0f04 100644 --- a/libhydrosphere/meson.build +++ b/libhydrosphere/meson.build @@ -20,6 +20,7 @@ assert(meson.is_cross_build(), 'This project is supposed to be cross compiled.') common_sources = [ 'source/common/compiler/memcpy.cpp', + 'source/common/compiler/unique_ptr.cpp', 'source/common/diag/diag_api.cpp', 'source/common/init/initialization.cpp', 'source/common/init/module_requirements.cpp', diff --git a/libhydrosphere/source/common/compiler/unique_ptr.cpp b/libhydrosphere/source/common/compiler/unique_ptr.cpp new file mode 100644 index 0000000..8263e65 --- /dev/null +++ b/libhydrosphere/source/common/compiler/unique_ptr.cpp @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2019 Hydrosphère Developers + * + * Licensed under the Apache License, Version 2.0 or the MIT license + * , at your + * option. This file may not be copied, modified, or distributed + * except according to those terms. + */ + +// Fake implementation to use in place of a C++ std::move. +// http://www.cplusplus.com/reference/utility/move/ +template +inline T &std_move(T &v) { + return v; +} + +// Fake implementation to use in place of a C++ std::swap. +// http://www.cplusplus.com/reference/utility/swap/ +template +inline void std_swap(T &a, T &b) { + T temp = std_move(a); + a = std_move(b); + b = std_move(a); +} + +template +class unique_ptr { + public: + unique_ptr() : native_ptr(nullptr) {} + + explicit unique_ptr(T *ptr) : native_ptr(ptr) {} + + unique_ptr(const unique_ptr &ptr) : native_ptr(ptr.native_ptr) { + const_cast(ptr).native_ptr = + nullptr; // const_cast to force ownership transfer. + } + + unique_ptr &operator=(unique_ptr ptr) { + swap(ptr); + return *this; + } + + inline ~unique_ptr() { destroy(); } + + inline void reset() { destroy(); } + + void reset(T *ptr) { + static_assert((nullptr == ptr) || (native_ptr != ptr), ""); + destroy(); + native_ptr = ptr; + } + + void swap(unique_ptr &ptr) { std_swap(native_ptr, ptr.native_ptr); } + + inline void release() { native_ptr = nullptr; } + + // Reference count operations: + + inline explicit operator bool() const { return nullptr != native_ptr; } + + // Underlying native_ptr operations: + + inline T &operator*() const { + static_assert(nullptr != native_ptr, ""); + return *native_ptr; + } + + inline T *operator->() const { + static_assert(nullptr != native_ptr, ""); + return native_ptr; + } + + inline T *get() const { return native_ptr; } + + private: + // Underlying native pointer to manage. + T *native_ptr; + + inline void destroy() { + delete native_ptr; + native_ptr = nullptr; + } + + inline void release() const { native_ptr = nullptr; } +}; + +// Comparison operators. + +template +inline bool operator==(const unique_ptr &l, const unique_ptr &r) { + return l.get() == r.get(); +} + +template +inline bool operator!=(const unique_ptr &l, const unique_ptr &r) { + return l.get() != r.get(); +} + +template +inline bool operator<=(const unique_ptr &l, const unique_ptr &r) { + return l.get() <= r.get(); +} + +template +inline bool operator<(const unique_ptr &l, const unique_ptr &r) { + return l.get() < r.get(); +} + +template +inline bool operator>=(const unique_ptr &l, const unique_ptr &r) { + return l.get() >= r.get(); +} + +template +inline bool operator>(const unique_ptr &l, const unique_ptr &r) { + return l.get() > r.get(); +} From 1b0e049711778b9eb741b321c99cb4a6bb7944fc Mon Sep 17 00:00:00 2001 From: Valentin B Date: Tue, 27 Aug 2019 18:00:12 +0200 Subject: [PATCH 03/15] Implement shared_ptr and apply minor improvements to unique_ptr --- .vscode/settings.json | 84 +++++++ .../source/common/compiler/shared_ptr.cpp | 214 ++++++++++++++++++ .../source/common/compiler/unique_ptr.cpp | 54 +++-- 3 files changed, 330 insertions(+), 22 deletions(-) create mode 100644 .vscode/settings.json create mode 100644 libhydrosphere/source/common/compiler/shared_ptr.cpp diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..95cd0b1 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,84 @@ +{ + "files.associations": { + "new": "cpp", + "array": "cpp", + "atomic": "cpp", + "hash_map": "cpp", + "bit": "cpp", + "*.tcc": "cpp", + "bitset": "cpp", + "cctype": "cpp", + "chrono": "cpp", + "clocale": "cpp", + "cmath": "cpp", + "codecvt": "cpp", + "condition_variable": "cpp", + "cstdarg": "cpp", + "cstddef": "cpp", + "cstdint": "cpp", + "cstdio": "cpp", + "cstdlib": "cpp", + "cstring": "cpp", + "ctime": "cpp", + "cwchar": "cpp", + "cwctype": "cpp", + "deque": "cpp", + "list": "cpp", + "map": "cpp", + "set": "cpp", + "unordered_map": "cpp", + "unordered_set": "cpp", + "vector": "cpp", + "exception": "cpp", + "algorithm": "cpp", + "functional": "cpp", + "iterator": "cpp", + "memory": "cpp", + "memory_resource": "cpp", + "numeric": "cpp", + "optional": "cpp", + "random": "cpp", + "ratio": "cpp", + "string": "cpp", + "string_view": "cpp", + "system_error": "cpp", + "tuple": "cpp", + "type_traits": "cpp", + "utility": "cpp", + "fstream": "cpp", + "initializer_list": "cpp", + "iomanip": "cpp", + "iosfwd": "cpp", + "iostream": "cpp", + "istream": "cpp", + "limits": "cpp", + "mutex": "cpp", + "ostream": "cpp", + "sstream": "cpp", + "stdexcept": "cpp", + "streambuf": "cpp", + "thread": "cpp", + "cinttypes": "cpp", + "typeinfo": "cpp", + "variant": "cpp", + "__bit_reference": "cpp", + "__config": "cpp", + "__debug": "cpp", + "__errc": "cpp", + "__functional_base": "cpp", + "__hash_table": "cpp", + "__locale": "cpp", + "__mutex_base": "cpp", + "__node_handle": "cpp", + "__nullptr": "cpp", + "__split_buffer": "cpp", + "__string": "cpp", + "__threading_support": "cpp", + "__tree": "cpp", + "__tuple": "cpp", + "ios": "cpp", + "locale": "cpp", + "queue": "cpp", + "stack": "cpp" + } +} \ No newline at end of file diff --git a/libhydrosphere/source/common/compiler/shared_ptr.cpp b/libhydrosphere/source/common/compiler/shared_ptr.cpp new file mode 100644 index 0000000..f9db435 --- /dev/null +++ b/libhydrosphere/source/common/compiler/shared_ptr.cpp @@ -0,0 +1,214 @@ +/* + * Copyright (c) 2019 Hydrosphère Developers + * + * Licensed under the Apache License, Version 2.0 or the MIT license + * , at your + * option. This file may not be copied, modified, or distributed + * except according to those terms. + */ + +#include + +// Fake implementation to use in place of a C++ std::move. +// http://www.cplusplus.com/reference/utility/move/ +template +__HS_ATTRIBUTE_WEAK inline T &std_move(T &v) { + return v; +} + +// Fake implementation to use in place of a C++ std::swap. +// http://www.cplusplus.com/reference/utility/swap/ +template +__HS_ATTRIBUTE_WEAK inline void std_swap(T &a, T &b) { + T temp = std_move(a); + a = std_move(b); + b = std_move(a); +} + +class shared_ptr_count { + public: + shared_ptr_count() : ref_count(nullptr) {} + + shared_ptr_count(const shared_ptr_count &count) + : ref_count(count.ref_count) {} + + void swap(shared_ptr_count &count) noexcept { + std_swap(ref_count, count.ref_count); + } + + long use_count() const noexcept { + return (ref_count != nullptr) ? *ref_count : 0; + } + + template + void acquire(U *ptr) { + if (ptr == nullptr) return; + + if (ref_count == nullptr) + ref_count = new long(1); // may throw std::bad_alloc (?) + else + ++(*ref_count); + } + + template + void release(U *ptr) noexcept { + if (ref_count == nullptr) return; + + --(*ref_count); + if (*ref_count <= 0) { + delete ptr; + delete ref_count; + } + ref_count = nullptr; + } + + private: + // Internal reference counter. + long *ref_count; +}; + +template +class shared_ptr { + public: + using element_type = T; + + shared_ptr() noexcept : native_ptr(nullptr), count() {} + + explicit shared_ptr(T *ptr) : count() { acquire(ptr); } + + template + shared_ptr(const shared_ptr &ptr, T *p) : count(ptr.count) { + acquire(p); + } + + template + explicit shared_ptr(const shared_ptr &ptr) noexcept : count(ptr.count) { + static_assert(ptr.native_ptr == nullptr || ptr.count.use_count() != 0, + ""); + acquire(static_cast::element_type *>( + ptr.native_ptr)); + } + + shared_ptr(const shared_ptr &ptr) noexcept : count(ptr.count) { + static_assert(ptr.native_ptr == nullptr || ptr.count.use_count() != 0, + ""); + acquire(ptr.native_ptr); + } + + inline ~shared_ptr() noexcept { release(); } + + shared_ptr &operator=(shared_ptr ptr) noexcept { + swap(ptr); + return *this; + } + + inline void reset() noexcept { release(); } + + void reset(T *p) { + static_assert(p == nullptr || native_ptr != p, ""); + release(); + acquire(p); // May throw std::bad_alloc (?) + } + + void swap(shared_ptr &ptr) noexcept { + std_swap(native_ptr, ptr.native_ptr); + count.swap(ptr.native_ptr); + } + + // Reference count operations: + + explicit operator bool() const noexcept { return 0 < count.use_count(); } + + bool unique() const noexcept { return 1 == count.use_count(); } + + long use_count() const noexcept { return count.use_count(); } + + // Underlying pointer operations: + + T &operator*() const noexcept { + static_assert(native_ptr != nullptr, ""); + return *native_ptr; + } + + T *operator->() const noexcept { + static_assert(native_ptr != nullptr, ""); + return native_ptr; + } + + T *get() const noexcept { return native_ptr; } + + private: + // Native pointer. + T *native_ptr; + // Reference counter. + shared_ptr_count count; + + // This allows pointer_cast functions to share the + // reference count between different shared_ptr types. + template + friend class shared_ptr; + + void acquire(T *p) { + count.acquire(p); // May throw std::bad_alloc (?) + native_ptr = p; + } + + void release() noexcept { + count.release(native_ptr); + native_ptr = nullptr; + } +}; + +// Comparison operators. + +template +inline bool operator==(const shared_ptr &l, + const shared_ptr &r) noexcept { + return l.get() == r.get(); +} + +template +inline bool operator!=(const shared_ptr &l, + const shared_ptr &r) noexcept { + return l.get() != r.get(); +} + +template +inline bool operator<=(const shared_ptr &l, + const shared_ptr &r) noexcept { + return l.get() <= r.get(); +} + +template +inline bool operator<(const shared_ptr &l, const shared_ptr &r) noexcept { + return l.get() < r.get(); +} + +template +inline bool operator>=(const shared_ptr &l, + const shared_ptr &r) noexcept { + return l.get() >= r.get(); +} + +template +inline bool operator>(const shared_ptr &l, const shared_ptr &r) noexcept { + return l.get() > r.get(); +} + +// Static cast of shared_ptr. +template +shared_ptr static_pointer_cast(const shared_ptr &ptr) noexcept { + return shared_ptr( + ptr, static_cast::element_type *>(ptr.get())); +} + +// Dynamic cast of shared_ptr. +template +shared_ptr dynamic_pointer_cast(const shared_ptr &ptr) noexcept { + T *p = dynamic_cast::element_type *>(ptr.get()); + if (p == nullptr) + return shared_ptr(); + else + return shared_ptr(ptr, p); +} diff --git a/libhydrosphere/source/common/compiler/unique_ptr.cpp b/libhydrosphere/source/common/compiler/unique_ptr.cpp index 8263e65..a1be27c 100644 --- a/libhydrosphere/source/common/compiler/unique_ptr.cpp +++ b/libhydrosphere/source/common/compiler/unique_ptr.cpp @@ -27,92 +27,102 @@ inline void std_swap(T &a, T &b) { template class unique_ptr { public: - unique_ptr() : native_ptr(nullptr) {} + using element_type = T; - explicit unique_ptr(T *ptr) : native_ptr(ptr) {} + unique_ptr() noexcept : native_ptr(nullptr) {} - unique_ptr(const unique_ptr &ptr) : native_ptr(ptr.native_ptr) { + explicit unique_ptr(T *ptr) noexcept : native_ptr(ptr) {} + + unique_ptr(const unique_ptr &ptr) noexcept : native_ptr(ptr.native_ptr) { const_cast(ptr).native_ptr = nullptr; // const_cast to force ownership transfer. } - unique_ptr &operator=(unique_ptr ptr) { + inline ~unique_ptr() noexcept { destroy(); } + + unique_ptr &operator=(unique_ptr ptr) noexcept { swap(ptr); return *this; } - inline ~unique_ptr() { destroy(); } - - inline void reset() { destroy(); } + inline void reset() noexcept { destroy(); } - void reset(T *ptr) { + void reset(T *ptr) noexcept { static_assert((nullptr == ptr) || (native_ptr != ptr), ""); destroy(); native_ptr = ptr; } - void swap(unique_ptr &ptr) { std_swap(native_ptr, ptr.native_ptr); } + void swap(unique_ptr &ptr) noexcept { + std_swap(native_ptr, ptr.native_ptr); + } - inline void release() { native_ptr = nullptr; } + inline void release() noexcept { native_ptr = nullptr; } // Reference count operations: - inline explicit operator bool() const { return nullptr != native_ptr; } + inline explicit operator bool() const noexcept { + return nullptr != native_ptr; + } // Underlying native_ptr operations: - inline T &operator*() const { + inline T &operator*() const noexcept { static_assert(nullptr != native_ptr, ""); return *native_ptr; } - inline T *operator->() const { + inline T *operator->() const noexcept { static_assert(nullptr != native_ptr, ""); return native_ptr; } - inline T *get() const { return native_ptr; } + inline T *get() const noexcept { return native_ptr; } private: // Underlying native pointer to manage. T *native_ptr; - inline void destroy() { + inline void destroy() noexcept { delete native_ptr; native_ptr = nullptr; } - inline void release() const { native_ptr = nullptr; } + inline void release() const noexcept { native_ptr = nullptr; } }; // Comparison operators. template -inline bool operator==(const unique_ptr &l, const unique_ptr &r) { +inline bool operator==(const unique_ptr &l, + const unique_ptr &r) noexcept { return l.get() == r.get(); } template -inline bool operator!=(const unique_ptr &l, const unique_ptr &r) { +inline bool operator!=(const unique_ptr &l, + const unique_ptr &r) noexcept { return l.get() != r.get(); } template -inline bool operator<=(const unique_ptr &l, const unique_ptr &r) { +inline bool operator<=(const unique_ptr &l, + const unique_ptr &r) noexcept { return l.get() <= r.get(); } template -inline bool operator<(const unique_ptr &l, const unique_ptr &r) { +inline bool operator<(const unique_ptr &l, const unique_ptr &r) noexcept { return l.get() < r.get(); } template -inline bool operator>=(const unique_ptr &l, const unique_ptr &r) { +inline bool operator>=(const unique_ptr &l, + const unique_ptr &r) noexcept { return l.get() >= r.get(); } template -inline bool operator>(const unique_ptr &l, const unique_ptr &r) { +inline bool operator>(const unique_ptr &l, const unique_ptr &r) noexcept { return l.get() > r.get(); } From 78f01b737f1b7dc2ce71eafa913181fbe23efc1e Mon Sep 17 00:00:00 2001 From: Valentin B Date: Tue, 27 Aug 2019 18:06:01 +0200 Subject: [PATCH 04/15] Remove vscode folder and gitignore common IDE folders --- .gitignore | 3 ++ .vscode/settings.json | 84 ------------------------------------------- 2 files changed, 3 insertions(+), 84 deletions(-) delete mode 100644 .vscode/settings.json diff --git a/.gitignore b/.gitignore index b6c550c..8634188 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,9 @@ /output /build /lib +/.vs/ +/.vscode/ +/.idea/ *.d *.a *.o diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index 95cd0b1..0000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,84 +0,0 @@ -{ - "files.associations": { - "new": "cpp", - "array": "cpp", - "atomic": "cpp", - "hash_map": "cpp", - "bit": "cpp", - "*.tcc": "cpp", - "bitset": "cpp", - "cctype": "cpp", - "chrono": "cpp", - "clocale": "cpp", - "cmath": "cpp", - "codecvt": "cpp", - "condition_variable": "cpp", - "cstdarg": "cpp", - "cstddef": "cpp", - "cstdint": "cpp", - "cstdio": "cpp", - "cstdlib": "cpp", - "cstring": "cpp", - "ctime": "cpp", - "cwchar": "cpp", - "cwctype": "cpp", - "deque": "cpp", - "list": "cpp", - "map": "cpp", - "set": "cpp", - "unordered_map": "cpp", - "unordered_set": "cpp", - "vector": "cpp", - "exception": "cpp", - "algorithm": "cpp", - "functional": "cpp", - "iterator": "cpp", - "memory": "cpp", - "memory_resource": "cpp", - "numeric": "cpp", - "optional": "cpp", - "random": "cpp", - "ratio": "cpp", - "string": "cpp", - "string_view": "cpp", - "system_error": "cpp", - "tuple": "cpp", - "type_traits": "cpp", - "utility": "cpp", - "fstream": "cpp", - "initializer_list": "cpp", - "iomanip": "cpp", - "iosfwd": "cpp", - "iostream": "cpp", - "istream": "cpp", - "limits": "cpp", - "mutex": "cpp", - "ostream": "cpp", - "sstream": "cpp", - "stdexcept": "cpp", - "streambuf": "cpp", - "thread": "cpp", - "cinttypes": "cpp", - "typeinfo": "cpp", - "variant": "cpp", - "__bit_reference": "cpp", - "__config": "cpp", - "__debug": "cpp", - "__errc": "cpp", - "__functional_base": "cpp", - "__hash_table": "cpp", - "__locale": "cpp", - "__mutex_base": "cpp", - "__node_handle": "cpp", - "__nullptr": "cpp", - "__split_buffer": "cpp", - "__string": "cpp", - "__threading_support": "cpp", - "__tree": "cpp", - "__tuple": "cpp", - "ios": "cpp", - "locale": "cpp", - "queue": "cpp", - "stack": "cpp" - } -} \ No newline at end of file From efd09eedda49b1e3187dd1f13fc0d421cc7ac8d6 Mon Sep 17 00:00:00 2001 From: Valentin B Date: Wed, 28 Aug 2019 15:18:40 +0200 Subject: [PATCH 05/15] Add shared_ptr.cpp to meson.build --- libhydrosphere/meson.build | 1 + 1 file changed, 1 insertion(+) diff --git a/libhydrosphere/meson.build b/libhydrosphere/meson.build index 70a0f04..9e4c5fd 100644 --- a/libhydrosphere/meson.build +++ b/libhydrosphere/meson.build @@ -20,6 +20,7 @@ assert(meson.is_cross_build(), 'This project is supposed to be cross compiled.') common_sources = [ 'source/common/compiler/memcpy.cpp', + 'source/common/compiler/shared_ptr.cpp', 'source/common/compiler/unique_ptr.cpp', 'source/common/diag/diag_api.cpp', 'source/common/init/initialization.cpp', From 66672e707f38922e947121a399a32ba24474f890 Mon Sep 17 00:00:00 2001 From: Valentin B Date: Wed, 28 Aug 2019 20:39:24 +0200 Subject: [PATCH 06/15] Implement memory allocation --- libhydrosphere/include/hs/svc/svc_api.hpp | 6 + libhydrosphere/include/hs/svc/svc_types.hpp | 2 + libhydrosphere/meson.build | 1 + .../source/common/compiler/allocator.cpp | 108 ++++++++++++++++++ 4 files changed, 117 insertions(+) create mode 100644 libhydrosphere/source/common/compiler/allocator.cpp diff --git a/libhydrosphere/include/hs/svc/svc_api.hpp b/libhydrosphere/include/hs/svc/svc_api.hpp index e8c1d5e..9dbdc10 100644 --- a/libhydrosphere/include/hs/svc/svc_api.hpp +++ b/libhydrosphere/include/hs/svc/svc_api.hpp @@ -21,6 +21,12 @@ namespace hs { namespace svc { + +inline hs::Result SetHeapSize(uintptr_t *out_address, + size_t heap_size) noexcept { + return hs::svc::SetHeapSize(out_address, heap_size); +} + inline hs::Result ArbitrateLock(hs::svc::Handle owner_thread_handle, uintptr_t lock_address, hs::svc::Handle requester_handle) noexcept { diff --git a/libhydrosphere/include/hs/svc/svc_types.hpp b/libhydrosphere/include/hs/svc/svc_types.hpp index 7dd0b80..2a52aa8 100644 --- a/libhydrosphere/include/hs/svc/svc_types.hpp +++ b/libhydrosphere/include/hs/svc/svc_types.hpp @@ -112,6 +112,8 @@ enum class InterruptType { // TODO(Kaenbyō): populate this enum class InfoType { + HeapRegionBaseAddr = 4, + HeapRegionSize = 5, AddressSpaceBase = 12, AddressSpaceSize = 13, StackRegionBase = 14, diff --git a/libhydrosphere/meson.build b/libhydrosphere/meson.build index 9e4c5fd..9f9f2ad 100644 --- a/libhydrosphere/meson.build +++ b/libhydrosphere/meson.build @@ -19,6 +19,7 @@ assert(cc.get_id() == 'clang', 'This project only support the Clang compiler.') assert(meson.is_cross_build(), 'This project is supposed to be cross compiled.') common_sources = [ + 'source/common/compiler/allocator.cpp', 'source/common/compiler/memcpy.cpp', 'source/common/compiler/shared_ptr.cpp', 'source/common/compiler/unique_ptr.cpp', diff --git a/libhydrosphere/source/common/compiler/allocator.cpp b/libhydrosphere/source/common/compiler/allocator.cpp new file mode 100644 index 0000000..9ea60ce --- /dev/null +++ b/libhydrosphere/source/common/compiler/allocator.cpp @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2019 Hydrosphère Developers + * + * Licensed under the Apache License, Version 2.0 or the MIT license + * , at your + * option. This file may not be copied, modified, or distributed + * except according to those terms. + */ + +#include + +#include "hs/hs_macro.hpp" +#include "hs/svc/svc_api.hpp" + +extern void *memcpy(void *dst, const void *src, size_t len); +extern void *memset(void *s, int c, size_t n); + +extern "C" __HS_ATTRIBUTE_WEAK void *sbrk(size_t increment) { + using namespace hs::svc; + + Handle handle; // How to initialize this? + size_t base_address = 0, out_address = 0; + + GetInfo(&base_address, InfoType::HeapRegionBaseAddr, handle, 0); + + size_t size_needed = increment - base_address; + size_t new_size; + + // Must be a multiple of 0x200000. + size_t remainder = size_needed % 0x200000; + if (remainder != 0) + new_size = size_needed + 0x200000 - remainder; + else + new_size = size_needed; + + SetHeapSize(&out_address, new_size); + + return (void *)(&out_address - &size_needed); +} + +struct FreeBlock { + size_t size; + FreeBlock *next; +}; + +static FreeBlock free_block_list_head = {0, nullptr}; +static const size_t align_to = 16; + +extern "C" __HS_ATTRIBUTE_WEAK void *malloc(size_t size) { + size = (size + sizeof(size_t) + (align_to - 1)) & ~(align_to - 1); + FreeBlock *block = free_block_list_head.next; + FreeBlock **head = &(free_block_list_head.next); + + while (block != nullptr) { + if (block->size >= size) { + *head = block->next; + return ((char *)block) + sizeof(size_t); + } + head = &(block->next); + block = block->next; + } + + block = (FreeBlock *)sbrk(size); + block->size = size; + + return ((char *)block) + sizeof(size_t); +} + +extern "C" __HS_ATTRIBUTE_WEAK void free(void *ptr) { + auto *block = (FreeBlock *)(((char *)ptr) - sizeof(size_t)); + block->next = free_block_list_head.next; + free_block_list_head.next = block; +} + +extern "C" __HS_ATTRIBUTE_WEAK void *calloc(size_t num, size_t nsize) { + size_t size; + void *block; + + if (!num || !nsize) return nullptr; + + size = num * nsize; + if (nsize != size / num) // Overflow check. + return nullptr; + + block = malloc(size); + if (!block) return nullptr; + + memset(block, 0, size); + return block; +} + +extern "C" __HS_ATTRIBUTE_WEAK void *realloc(void *ptr, size_t size) { + FreeBlock *block; + void *res; + + if (!ptr || !size) return malloc(size); + + block = (FreeBlock *)ptr - 1; + if (block->size >= size) return block; + + res = malloc(size); + if (res) { + memcpy(res, ptr, block->size); + free(block); + } + return res; +} From 1253214fa3e08f6f6fab5850b244699fa67c33e1 Mon Sep 17 00:00:00 2001 From: Valentin B Date: Mon, 2 Sep 2019 12:50:33 +0200 Subject: [PATCH 07/15] Redesign the memory allocator --- .../source/common/compiler/allocator.cpp | 129 +++++++----------- 1 file changed, 49 insertions(+), 80 deletions(-) diff --git a/libhydrosphere/source/common/compiler/allocator.cpp b/libhydrosphere/source/common/compiler/allocator.cpp index 9ea60ce..664cb5a 100644 --- a/libhydrosphere/source/common/compiler/allocator.cpp +++ b/libhydrosphere/source/common/compiler/allocator.cpp @@ -10,99 +10,68 @@ #include -#include "hs/hs_macro.hpp" -#include "hs/svc/svc_api.hpp" - -extern void *memcpy(void *dst, const void *src, size_t len); -extern void *memset(void *s, int c, size_t n); - -extern "C" __HS_ATTRIBUTE_WEAK void *sbrk(size_t increment) { - using namespace hs::svc; - - Handle handle; // How to initialize this? - size_t base_address = 0, out_address = 0; - - GetInfo(&base_address, InfoType::HeapRegionBaseAddr, handle, 0); - - size_t size_needed = increment - base_address; - size_t new_size; - - // Must be a multiple of 0x200000. - size_t remainder = size_needed % 0x200000; - if (remainder != 0) - new_size = size_needed + 0x200000 - remainder; - else - new_size = size_needed; - - SetHeapSize(&out_address, new_size); - - return (void *)(&out_address - &size_needed); +constexpr size_t MemoryAlign(size_t size, size_t alignment) { + return (size + alignment - 1) & ~(alignment - 1); } -struct FreeBlock { - size_t size; - FreeBlock *next; -}; - -static FreeBlock free_block_list_head = {0, nullptr}; -static const size_t align_to = 16; +class MemoryAllocator { + public: + MemoryAllocator(void *start_address, size_t region_size) noexcept + : start_address_(start_address), region_size_(region_size) { + head_ = {0, nullptr}; + used_memory_ = 0; + } -extern "C" __HS_ATTRIBUTE_WEAK void *malloc(size_t size) { - size = (size + sizeof(size_t) + (align_to - 1)) & ~(align_to - 1); - FreeBlock *block = free_block_list_head.next; - FreeBlock **head = &(free_block_list_head.next); + MemoryAllocator(void *start_address, void *end_address) noexcept + : MemoryAllocator( + start_address, + static_cast(static_cast(end_address) - + static_cast(start_address))) {} - while (block != nullptr) { - if (block->size >= size) { - *head = block->next; - return ((char *)block) + sizeof(size_t); - } - head = &(block->next); - block = block->next; - } + void *Allocate(size_t size, size_t alignment = 16) noexcept { + size = MemoryAlign(size, alignment); - block = (FreeBlock *)sbrk(size); - block->size = size; + if (size + used_memory_ > region_size_) return nullptr; - return ((char *)block) + sizeof(size_t); -} + MemoryBlock *block = head_.next; + MemoryBlock **head = &head_.next; -extern "C" __HS_ATTRIBUTE_WEAK void free(void *ptr) { - auto *block = (FreeBlock *)(((char *)ptr) - sizeof(size_t)); - block->next = free_block_list_head.next; - free_block_list_head.next = block; -} + while (block) { + if (block->size >= size) { + *head = block->next; + return reinterpret_cast(block) + sizeof(size_t); + } -extern "C" __HS_ATTRIBUTE_WEAK void *calloc(size_t num, size_t nsize) { - size_t size; - void *block; + head = &block->next; + block = block->next; + } - if (!num || !nsize) return nullptr; + block = reinterpret_cast( + static_cast(start_address_) + used_memory_); + used_memory_ += size; + block->size = size; - size = num * nsize; - if (nsize != size / num) // Overflow check. - return nullptr; + return reinterpret_cast(block) + sizeof(MemoryBlock); + } - block = malloc(size); - if (!block) return nullptr; + void Free(void *pointer) noexcept { + auto block = reinterpret_cast( + static_cast(pointer) - sizeof(MemoryBlock)); + block->next = head_.next; + head_.next = block; + } - memset(block, 0, size); - return block; -} + private: + struct MemoryBlock { + size_t size; + MemoryBlock *next; + }; -extern "C" __HS_ATTRIBUTE_WEAK void *realloc(void *ptr, size_t size) { - FreeBlock *block; - void *res; + MemoryBlock head_; - if (!ptr || !size) return malloc(size); + void *start_address_; - block = (FreeBlock *)ptr - 1; - if (block->size >= size) return block; + size_t region_size_; - res = malloc(size); - if (res) { - memcpy(res, ptr, block->size); - free(block); - } - return res; -} + size_t used_memory_; +}; From 0c9bbe262508b99c3280622ddb9586091e005e66 Mon Sep 17 00:00:00 2001 From: Valentin B Date: Sat, 14 Sep 2019 13:42:00 +0200 Subject: [PATCH 08/15] Bugfixes for the smart pointers and documentation for everything --- .../source/common/compiler/allocator.cpp | 29 ++- .../source/common/compiler/memcpy.cpp | 15 +- .../source/common/compiler/shared_ptr.cpp | 175 +++++++++++------- .../source/common/compiler/unique_ptr.cpp | 116 ++++++++---- 4 files changed, 229 insertions(+), 106 deletions(-) diff --git a/libhydrosphere/source/common/compiler/allocator.cpp b/libhydrosphere/source/common/compiler/allocator.cpp index 664cb5a..372d274 100644 --- a/libhydrosphere/source/common/compiler/allocator.cpp +++ b/libhydrosphere/source/common/compiler/allocator.cpp @@ -10,32 +10,53 @@ #include -constexpr size_t MemoryAlign(size_t size, size_t alignment) { +constexpr size_t memory_align(size_t size, size_t alignment) { return (size + alignment - 1) & ~(alignment - 1); } +/** + * \short Impelements a memory allocator that maps a given block + * of memory and manages it. + */ class MemoryAllocator { public: + /** + * \short Constructs a new MemoryAllocator. + * \param[in] start_address The start address of the memory region. + * \param[in] region_size The size of the memory region. + */ MemoryAllocator(void *start_address, size_t region_size) noexcept : start_address_(start_address), region_size_(region_size) { head_ = {0, nullptr}; used_memory_ = 0; } + /** + * \short Constructs a new MemoryAllocator. + * \param[in] start_address The start address of the memory region. + * \param[in] end_address The end address of the memory region. + */ MemoryAllocator(void *start_address, void *end_address) noexcept : MemoryAllocator( start_address, static_cast(static_cast(end_address) - static_cast(start_address))) {} + /** + * \short Allocates memory on the mapped region. + * \param[in] size The size of memory to allocate. + * \param[in] alignment The alignment to use. Defaults to 16. + * \return Pointer to the allocated memory block. + */ void *Allocate(size_t size, size_t alignment = 16) noexcept { - size = MemoryAlign(size, alignment); + size = memory_align(size, alignment); if (size + used_memory_ > region_size_) return nullptr; MemoryBlock *block = head_.next; MemoryBlock **head = &head_.next; + // Find a free memory block. while (block) { if (block->size >= size) { *head = block->next; @@ -54,6 +75,10 @@ class MemoryAllocator { return reinterpret_cast(block) + sizeof(MemoryBlock); } + /** + * \short Frees allocated memory. + * \param[in] pointer A pointer to the memory block to free. + */ void Free(void *pointer) noexcept { auto block = reinterpret_cast( static_cast(pointer) - sizeof(MemoryBlock)); diff --git a/libhydrosphere/source/common/compiler/memcpy.cpp b/libhydrosphere/source/common/compiler/memcpy.cpp index 371cfbb..7f1f6de 100644 --- a/libhydrosphere/source/common/compiler/memcpy.cpp +++ b/libhydrosphere/source/common/compiler/memcpy.cpp @@ -11,8 +11,13 @@ #include #include -// We define memcpy as we don't have any libraries that can provide it. -// If there is any, as this is weak, it's going to be discared. +/** + * \short Copies len bytes from src directly to dst. + * \param[out] dst Pointer to the destination array where the content is to be + * copied. + * \param[in] src Pointer to the source of data to be copied. \param[in] + * len Number of bytes to copy. + */ extern "C" __HS_ATTRIBUTE_WEAK void *memcpy(void *dst, const void *src, size_t len) { const char *from = (const char *)src; @@ -22,6 +27,12 @@ extern "C" __HS_ATTRIBUTE_WEAK void *memcpy(void *dst, const void *src, return dst; } +/** + * \short Sets the first n bytes of s to c (interpreted as an unsigned char). + * \param[out] s Pointer to the block of memory to fill. + * \param[in] c Value to be set. Will be casted to unsigned char. + * \param[in] n Number of bytes to be set to the value. + */ extern "C" __HS_ATTRIBUTE_WEAK void *memset(void *s, int c, size_t n) { unsigned char *p = reinterpret_cast(s); while (n--) *p++ = (unsigned char)c; diff --git a/libhydrosphere/source/common/compiler/shared_ptr.cpp b/libhydrosphere/source/common/compiler/shared_ptr.cpp index f9db435..3474eb5 100644 --- a/libhydrosphere/source/common/compiler/shared_ptr.cpp +++ b/libhydrosphere/source/common/compiler/shared_ptr.cpp @@ -8,141 +8,192 @@ * except according to those terms. */ -#include - -// Fake implementation to use in place of a C++ std::move. -// http://www.cplusplus.com/reference/utility/move/ -template -__HS_ATTRIBUTE_WEAK inline T &std_move(T &v) { - return v; -} - -// Fake implementation to use in place of a C++ std::swap. -// http://www.cplusplus.com/reference/utility/swap/ -template -__HS_ATTRIBUTE_WEAK inline void std_swap(T &a, T &b) { - T temp = std_move(a); - a = std_move(b); - b = std_move(a); -} - class shared_ptr_count { public: - shared_ptr_count() : ref_count(nullptr) {} + shared_ptr_count() : ref_count_(nullptr) {} - shared_ptr_count(const shared_ptr_count &count) - : ref_count(count.ref_count) {} + shared_ptr_count(const shared_ptr_count &count) = default; void swap(shared_ptr_count &count) noexcept { - std_swap(ref_count, count.ref_count); + auto temp = ref_count_; + ref_count_ = count.ref_count_; + count.ref_count_ = temp; } long use_count() const noexcept { - return (ref_count != nullptr) ? *ref_count : 0; + return (ref_count_ != nullptr) ? *ref_count_ : 0; } template void acquire(U *ptr) { if (ptr == nullptr) return; - if (ref_count == nullptr) - ref_count = new long(1); // may throw std::bad_alloc (?) + if (ref_count_ == nullptr) + ref_count_ = new long(1); // may throw std::bad_alloc (?) else - ++(*ref_count); + ++(*ref_count_); } template void release(U *ptr) noexcept { - if (ref_count == nullptr) return; + if (ref_count_ == nullptr) return; - --(*ref_count); - if (*ref_count <= 0) { + --(*ref_count_); + if (*ref_count_ <= 0) { delete ptr; - delete ref_count; + delete ref_count_; } - ref_count = nullptr; + ref_count_ = nullptr; } private: // Internal reference counter. - long *ref_count; + long *ref_count_; }; +/** + * \short A smart pointer that retains shared ownership of an object through a + * pointer. + */ template class shared_ptr { public: using element_type = T; - shared_ptr() noexcept : native_ptr(nullptr), count() {} - - explicit shared_ptr(T *ptr) : count() { acquire(ptr); } - + /** + * \short Constructs a new shared_ptr from a nullptr. + */ + shared_ptr() noexcept : native_ptr_(nullptr), count_() {} + + /** + * \short Constructs a new shared_ptr given a raw pointer. + * \param[in] ptr The raw pointer to manage. + */ + explicit shared_ptr(T *ptr) : count_() { acquire(ptr); } + + /** + * \short Constructs a new shared_ptr to share ownership. + * \param[in] ptr A shared_ptr to take the reference count from. + * \param[in] p The raw pointer to acquire ownership of. + * \warning This should only be used for pointer casts as it doesn't manage + * two separate and pointers! + */ template - shared_ptr(const shared_ptr &ptr, T *p) : count(ptr.count) { + shared_ptr(const shared_ptr &ptr, T *p) : count_(ptr.count_) { acquire(p); } + /** + * \short Constructs a new shared_ptr that converts from another pointer + * type. + * \param[in] ptr The shared_ptr to use. + */ template - explicit shared_ptr(const shared_ptr &ptr) noexcept : count(ptr.count) { - static_assert(ptr.native_ptr == nullptr || ptr.count.use_count() != 0, + explicit shared_ptr(const shared_ptr &ptr) noexcept + : count_(ptr.count_) { + static_assert(ptr.native_ptr_ == nullptr || ptr.count_.use_count() != 0, ""); acquire(static_cast::element_type *>( - ptr.native_ptr)); + ptr.native_ptr_)); } - shared_ptr(const shared_ptr &ptr) noexcept : count(ptr.count) { - static_assert(ptr.native_ptr == nullptr || ptr.count.use_count() != 0, + /** + * \short Constructs a new shared_ptr by the copy-and-swap idiom. + * \param[in] ptr The shared_ptr to use. + */ + shared_ptr(const shared_ptr &ptr) noexcept : count_(ptr.count_) { + static_assert(ptr.native_ptr_ == nullptr || ptr.count_.use_count() != 0, ""); - acquire(ptr.native_ptr); + acquire(ptr.native_ptr_); } + /** + * \short Destructs the owned object if no more shared_ptrs link to it. + */ inline ~shared_ptr() noexcept { release(); } + /** + * \short Assigns the shared_ptr. + * \param[in] ptr The shared_ptr that should be assigned. + */ shared_ptr &operator=(shared_ptr ptr) noexcept { swap(ptr); return *this; } + /** + * \short Releases ownership of the managed object. + */ inline void reset() noexcept { release(); } + /** + * \short Replaces the managed object. + * \param[in] p The pointer to replace the contents with. + */ void reset(T *p) { - static_assert(p == nullptr || native_ptr != p, ""); + static_assert(p == nullptr || native_ptr_ != p, ""); release(); acquire(p); // May throw std::bad_alloc (?) } + /** + * \short Swaps the managed objects. + * \param[in] ptr The pointer to exchange the contents with. + */ void swap(shared_ptr &ptr) noexcept { - std_swap(native_ptr, ptr.native_ptr); - count.swap(ptr.native_ptr); + auto temp = native_ptr_; + native_ptr_ = ptr.native_ptr_; + ptr.native_ptr_ = temp; + + count_.swap(ptr.native_ptr_); } // Reference count operations: - explicit operator bool() const noexcept { return 0 < count.use_count(); } + /** + * \short Checks if the stored pointer is not null. + */ + explicit operator bool() const noexcept { return 0 < count_.use_count(); } - bool unique() const noexcept { return 1 == count.use_count(); } + /** + * \short Checks whether the managed object is managed only by the current + * shared_ptr instance. + */ + bool unique() const noexcept { return 1 == count_.use_count(); } - long use_count() const noexcept { return count.use_count(); } + /** + * \short Returns the number of shared_ptr objects referring to the same + * managed object. + */ + long use_count() const noexcept { return count_.use_count(); } // Underlying pointer operations: + /** + * \short Dereferences the stored pointer. + */ T &operator*() const noexcept { - static_assert(native_ptr != nullptr, ""); - return *native_ptr; + static_assert(native_ptr_ != nullptr, ""); + return *native_ptr_; } + /** + * \short Provides access to the stored pointer. + */ T *operator->() const noexcept { - static_assert(native_ptr != nullptr, ""); - return native_ptr; + static_assert(native_ptr_ != nullptr, ""); + return native_ptr_; } - T *get() const noexcept { return native_ptr; } + /** + * \short Returns the stored pointer. + */ + T *get() const noexcept { return native_ptr_; } private: - // Native pointer. - T *native_ptr; - // Reference counter. - shared_ptr_count count; + T *native_ptr_; + + shared_ptr_count count_; // This allows pointer_cast functions to share the // reference count between different shared_ptr types. @@ -150,13 +201,13 @@ class shared_ptr { friend class shared_ptr; void acquire(T *p) { - count.acquire(p); // May throw std::bad_alloc (?) - native_ptr = p; + count_.acquire(p); // May throw std::bad_alloc (?) + native_ptr_ = p; } void release() noexcept { - count.release(native_ptr); - native_ptr = nullptr; + count_.release(native_ptr_); + native_ptr_ = nullptr; } }; diff --git a/libhydrosphere/source/common/compiler/unique_ptr.cpp b/libhydrosphere/source/common/compiler/unique_ptr.cpp index a1be27c..e3eddd7 100644 --- a/libhydrosphere/source/common/compiler/unique_ptr.cpp +++ b/libhydrosphere/source/common/compiler/unique_ptr.cpp @@ -8,87 +8,123 @@ * except according to those terms. */ -// Fake implementation to use in place of a C++ std::move. -// http://www.cplusplus.com/reference/utility/move/ -template -inline T &std_move(T &v) { - return v; -} - -// Fake implementation to use in place of a C++ std::swap. -// http://www.cplusplus.com/reference/utility/swap/ -template -inline void std_swap(T &a, T &b) { - T temp = std_move(a); - a = std_move(b); - b = std_move(a); -} - +/** + * \short A smart pointer that owns and manages another object through a pointer + * and disposes of that object when the unique_ptr goes out of scope. + */ template class unique_ptr { public: using element_type = T; - unique_ptr() noexcept : native_ptr(nullptr) {} - - explicit unique_ptr(T *ptr) noexcept : native_ptr(ptr) {} - - unique_ptr(const unique_ptr &ptr) noexcept : native_ptr(ptr.native_ptr) { - const_cast(ptr).native_ptr = + /** + * \short Constructs a new unique_ptr from a nullptr. + */ + unique_ptr() noexcept : native_ptr_(nullptr) {} + + /** + * \short Constructs a new unique_ptr given a raw pointer. + * \param[in] ptr The pointer to be wrapped. + */ + explicit unique_ptr(T *ptr) noexcept : native_ptr_(ptr) {} + + /** + * \short Constructs a new unique_ptr from an existing unique_ptr. + * \param[in] ptr The unique_ptr to use. + */ + unique_ptr(const unique_ptr &ptr) noexcept : native_ptr_(ptr.native_ptr_) { + const_cast(ptr).native_ptr_ = nullptr; // const_cast to force ownership transfer. } + /** + * \short Destructs the managed object if such is present. + */ inline ~unique_ptr() noexcept { destroy(); } + /** + * \short Assigns the unique_ptr. + * \param[in] ptr The unique_ptr that should be assigned. + */ unique_ptr &operator=(unique_ptr ptr) noexcept { swap(ptr); return *this; } + /** + * \short Destroys the managed object. + */ inline void reset() noexcept { destroy(); } + /** + * \short Replaces the managed object. + * \param[in] ptr The pointer to replace the contents with. + */ void reset(T *ptr) noexcept { - static_assert((nullptr == ptr) || (native_ptr != ptr), ""); + static_assert((nullptr == ptr) || (native_ptr_ != ptr), ""); destroy(); - native_ptr = ptr; + native_ptr_ = ptr; } + /** + * Swaps the managed objects. + * \param[in] ptr The pointer to exchange the contents with. + */ void swap(unique_ptr &ptr) noexcept { - std_swap(native_ptr, ptr.native_ptr); + auto temp = native_ptr_; + native_ptr_ = ptr.native_ptr_; + ptr.native_ptr_ = temp; } - inline void release() noexcept { native_ptr = nullptr; } - - // Reference count operations: + /** + * \short Returns a pointer to the managed object and releases the + * ownership. + */ + inline T *release() noexcept { + T *temp = native_ptr_; + native_ptr_ = nullptr; + return temp; + } + /** + * \short Checks if there is an associated managed object. + */ inline explicit operator bool() const noexcept { - return nullptr != native_ptr; + return nullptr != native_ptr_; } - // Underlying native_ptr operations: + // Underlying native_ptr_ operations: + /** + * \short Dereferences pointer to the managed object. + */ inline T &operator*() const noexcept { - static_assert(nullptr != native_ptr, ""); - return *native_ptr; + static_assert(nullptr != native_ptr_, ""); + return *native_ptr_; } + /** + * \short Provides access to a pointer to managed object. + */ inline T *operator->() const noexcept { - static_assert(nullptr != native_ptr, ""); - return native_ptr; + static_assert(nullptr != native_ptr_, ""); + return native_ptr_; } - inline T *get() const noexcept { return native_ptr; } + /** + * \short Returns a pointer to the managed object. + */ + inline T *get() const noexcept { return native_ptr_; } private: - // Underlying native pointer to manage. - T *native_ptr; + T *native_ptr_; inline void destroy() noexcept { - delete native_ptr; - native_ptr = nullptr; + delete native_ptr_; + native_ptr_ = nullptr; } - inline void release() const noexcept { native_ptr = nullptr; } + inline void release() const noexcept { native_ptr_ = nullptr; } }; // Comparison operators. From 6437c87bf3c7078d80b3fb116ad005601e04bc43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kaenby=C5=8D?= <52895153+Kaenbyo@users.noreply.github.com> Date: Sat, 14 Sep 2019 15:02:07 +0200 Subject: [PATCH 09/15] Fix codestyle after clang-format --- libhydrosphere/include/hs/hs_result.hpp | 2 +- .../include/hs/os/os_condition_variable_impl.hpp | 4 ++-- .../include/hs/os/os_critical_section.hpp | 4 ++-- libhydrosphere/include/hs/os/os_tls.hpp | 4 ++-- libhydrosphere/include/hs/svc/svc_types.hpp | 4 ++-- .../include/hs/util/util_intrusive_list.hpp | 16 ++++++++-------- libhydrosphere/include/hs/util/util_optional.hpp | 4 ++-- .../source/common/compiler/allocator.cpp | 4 ++-- .../source/common/compiler/shared_ptr.cpp | 8 ++++---- .../source/common/compiler/unique_ptr.cpp | 4 ++-- .../source/common/os/detail/os_threadlist.hpp | 4 ++-- .../os/detail/os_virtualmemory_allocator.hpp | 4 ++-- 12 files changed, 31 insertions(+), 31 deletions(-) diff --git a/libhydrosphere/include/hs/hs_result.hpp b/libhydrosphere/include/hs/hs_result.hpp index 5162c42..6a06b79 100644 --- a/libhydrosphere/include/hs/hs_result.hpp +++ b/libhydrosphere/include/hs/hs_result.hpp @@ -22,7 +22,7 @@ class Result { */ uint32_t value; - public: + public: /** * \short Construct a Result from a raw value. * \param[in] value The raw result value that defines the new Result. diff --git a/libhydrosphere/include/hs/os/os_condition_variable_impl.hpp b/libhydrosphere/include/hs/os/os_condition_variable_impl.hpp index fc79e09..4b78f4a 100644 --- a/libhydrosphere/include/hs/os/os_condition_variable_impl.hpp +++ b/libhydrosphere/include/hs/os/os_condition_variable_impl.hpp @@ -24,10 +24,10 @@ namespace hs::os { * until notified to resume. */ class ConditionVariableImpl { - private: + private: uint_fast32_t image; - public: + public: /** * \short Signal one. * diff --git a/libhydrosphere/include/hs/os/os_critical_section.hpp b/libhydrosphere/include/hs/os/os_critical_section.hpp index f31ab2e..bfe8579 100644 --- a/libhydrosphere/include/hs/os/os_critical_section.hpp +++ b/libhydrosphere/include/hs/os/os_critical_section.hpp @@ -23,10 +23,10 @@ namespace hs::os { * \remark CriticalSection ensures mutual exclusion of access. */ class CriticalSection { - private: + private: volatile _Atomic(uint_fast32_t) image; - public: + public: /** * \short Enter the critical section. */ diff --git a/libhydrosphere/include/hs/os/os_tls.hpp b/libhydrosphere/include/hs/os/os_tls.hpp index 9faea09..41d258e 100644 --- a/libhydrosphere/include/hs/os/os_tls.hpp +++ b/libhydrosphere/include/hs/os/os_tls.hpp @@ -23,7 +23,7 @@ namespace hs::os { * \private */ class ThreadLocalStorage { - public: + public: /** * The IPC command buffer. */ @@ -47,7 +47,7 @@ class ThreadLocalStorage { this->context = thread_context; } - private: + private: /** * The thread context attached to this TLS storage. */ diff --git a/libhydrosphere/include/hs/svc/svc_types.hpp b/libhydrosphere/include/hs/svc/svc_types.hpp index 2a52aa8..36ff2b5 100644 --- a/libhydrosphere/include/hs/svc/svc_types.hpp +++ b/libhydrosphere/include/hs/svc/svc_types.hpp @@ -21,14 +21,14 @@ namespace svc { * \short Opaque type representing an Horizon Handle. */ class Handle { - private: + private: /** * \private * \short The raw handle value. */ uint32_t value; - public: + public: /** * \short Returns the raw handle value stored inside Handle. */ diff --git a/libhydrosphere/include/hs/util/util_intrusive_list.hpp b/libhydrosphere/include/hs/util/util_intrusive_list.hpp index 8e42bc4..3cd60bb 100644 --- a/libhydrosphere/include/hs/util/util_intrusive_list.hpp +++ b/libhydrosphere/include/hs/util/util_intrusive_list.hpp @@ -27,11 +27,11 @@ struct DefaultIntrusiveTag; */ template class IntrusiveListElement { - private: + private: IntrusiveListElement* prev; IntrusiveListElement* next; - public: + public: IntrusiveListElement() { prev = this; next = this; @@ -116,7 +116,7 @@ class IntrusiveListElement { */ template class IntrusiveList { - public: + public: __HS_DISALLOW_COPY(IntrusiveList); /** @@ -154,7 +154,7 @@ class IntrusiveList { // Define iterators implementation class const_iterator { - public: + public: friend class iterator; friend class IntrusiveList; @@ -206,12 +206,12 @@ class IntrusiveList { return value != target.value; } - private: + private: const_pointer value; }; class iterator { - public: + public: friend class const_iterator; friend class IntrusiveList; @@ -263,7 +263,7 @@ class IntrusiveList { return value != target.value; } - private: + private: pointer value; }; @@ -503,7 +503,7 @@ class IntrusiveList { template void sort(Compare comp); void reverse() noexcept;*/ - private: + private: IntrusiveListElement root; }; } // namespace hs::util diff --git a/libhydrosphere/include/hs/util/util_optional.hpp b/libhydrosphere/include/hs/util/util_optional.hpp index 02a885f..a8abcdc 100644 --- a/libhydrosphere/include/hs/util/util_optional.hpp +++ b/libhydrosphere/include/hs/util/util_optional.hpp @@ -20,7 +20,7 @@ namespace hs::util { */ template class Optional { - private: + private: /** * \short True if the Optional contains a value. */ @@ -35,7 +35,7 @@ class Optional { */ ObjectStorage value; - public: + public: constexpr explicit operator bool() const noexcept { return HasValue(); } /** diff --git a/libhydrosphere/source/common/compiler/allocator.cpp b/libhydrosphere/source/common/compiler/allocator.cpp index 372d274..4fca7bf 100644 --- a/libhydrosphere/source/common/compiler/allocator.cpp +++ b/libhydrosphere/source/common/compiler/allocator.cpp @@ -19,7 +19,7 @@ constexpr size_t memory_align(size_t size, size_t alignment) { * of memory and manages it. */ class MemoryAllocator { - public: + public: /** * \short Constructs a new MemoryAllocator. * \param[in] start_address The start address of the memory region. @@ -86,7 +86,7 @@ class MemoryAllocator { head_.next = block; } - private: + private: struct MemoryBlock { size_t size; MemoryBlock *next; diff --git a/libhydrosphere/source/common/compiler/shared_ptr.cpp b/libhydrosphere/source/common/compiler/shared_ptr.cpp index 3474eb5..e1ddeed 100644 --- a/libhydrosphere/source/common/compiler/shared_ptr.cpp +++ b/libhydrosphere/source/common/compiler/shared_ptr.cpp @@ -9,7 +9,7 @@ */ class shared_ptr_count { - public: + public: shared_ptr_count() : ref_count_(nullptr) {} shared_ptr_count(const shared_ptr_count &count) = default; @@ -46,7 +46,7 @@ class shared_ptr_count { ref_count_ = nullptr; } - private: + private: // Internal reference counter. long *ref_count_; }; @@ -57,7 +57,7 @@ class shared_ptr_count { */ template class shared_ptr { - public: + public: using element_type = T; /** @@ -190,7 +190,7 @@ class shared_ptr { */ T *get() const noexcept { return native_ptr_; } - private: + private: T *native_ptr_; shared_ptr_count count_; diff --git a/libhydrosphere/source/common/compiler/unique_ptr.cpp b/libhydrosphere/source/common/compiler/unique_ptr.cpp index e3eddd7..094344a 100644 --- a/libhydrosphere/source/common/compiler/unique_ptr.cpp +++ b/libhydrosphere/source/common/compiler/unique_ptr.cpp @@ -14,7 +14,7 @@ */ template class unique_ptr { - public: + public: using element_type = T; /** @@ -116,7 +116,7 @@ class unique_ptr { */ inline T *get() const noexcept { return native_ptr_; } - private: + private: T *native_ptr_; inline void destroy() noexcept { diff --git a/libhydrosphere/source/common/os/detail/os_threadlist.hpp b/libhydrosphere/source/common/os/detail/os_threadlist.hpp index ba7f788..ebb4e0f 100644 --- a/libhydrosphere/source/common/os/detail/os_threadlist.hpp +++ b/libhydrosphere/source/common/os/detail/os_threadlist.hpp @@ -19,12 +19,12 @@ namespace hs::os::detail { class ThreadList { - private: + private: hs::os::CriticalSection critical_section; hs::util::IntrusiveList list; hs::os::Thread main_thread; - public: + public: explicit ThreadList(hs::svc::Handle thread_handle) : critical_section(), list(), main_thread() { main_thread.thread_handle = thread_handle; diff --git a/libhydrosphere/source/common/os/detail/os_virtualmemory_allocator.hpp b/libhydrosphere/source/common/os/detail/os_virtualmemory_allocator.hpp index 7576acb..6184263 100644 --- a/libhydrosphere/source/common/os/detail/os_virtualmemory_allocator.hpp +++ b/libhydrosphere/source/common/os/detail/os_virtualmemory_allocator.hpp @@ -18,7 +18,7 @@ namespace hs::os::detail { class VirtualMemoryAllocator { - private: + private: hs::os::CriticalSection critical_section; uintptr_t address_space_start; uintptr_t address_space_end; @@ -31,7 +31,7 @@ class VirtualMemoryAllocator { (target_address < end_address); } - public: + public: VirtualMemoryAllocator(uintptr_t address_space_start, uintptr_t address_space_end, size_t guard_page_size) noexcept From 1cd85bba391bfa73e422b6ce7ff026d81f8a58f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kaenby=C5=8D?= <52895153+Kaenbyo@users.noreply.github.com> Date: Sat, 14 Sep 2019 15:06:34 +0200 Subject: [PATCH 10/15] Disable runtime/int cpplint rule --- libhydrosphere/CPPLINT.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libhydrosphere/CPPLINT.cfg b/libhydrosphere/CPPLINT.cfg index 99eb05d..7d5a16f 100644 --- a/libhydrosphere/CPPLINT.cfg +++ b/libhydrosphere/CPPLINT.cfg @@ -8,5 +8,5 @@ set noparent -filter=-runtime/references +filter=-runtime/references,-runtime/int exclude_files=external|build From 1ff1e05dc6ec26930b8da1b5991067a2720efc61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kaenby=C5=8D?= <52895153+Kaenbyo@users.noreply.github.com> Date: Sat, 14 Sep 2019 15:30:11 +0200 Subject: [PATCH 11/15] Move memory related implementation to the mem namespace --- libhydrosphere/CPPLINT.cfg | 2 +- libhydrosphere/include/hs/mem.hpp | 15 +++++++++++++++ .../hs/mem/allocator.hpp} | 11 +++++++---- .../hs/mem/shared_ptr.hpp} | 4 ++++ .../hs/mem/unique_ptr.hpp} | 4 ++++ libhydrosphere/include/hs/svc/svc_api.hpp | 3 ++- libhydrosphere/meson.build | 5 +---- 7 files changed, 34 insertions(+), 10 deletions(-) create mode 100644 libhydrosphere/include/hs/mem.hpp rename libhydrosphere/{source/common/compiler/allocator.cpp => include/hs/mem/allocator.hpp} (94%) rename libhydrosphere/{source/common/compiler/shared_ptr.cpp => include/hs/mem/shared_ptr.hpp} (99%) rename libhydrosphere/{source/common/compiler/unique_ptr.cpp => include/hs/mem/unique_ptr.hpp} (98%) diff --git a/libhydrosphere/CPPLINT.cfg b/libhydrosphere/CPPLINT.cfg index 7d5a16f..e4ef613 100644 --- a/libhydrosphere/CPPLINT.cfg +++ b/libhydrosphere/CPPLINT.cfg @@ -8,5 +8,5 @@ set noparent -filter=-runtime/references,-runtime/int +filter=-runtime/references,-runtime/int,-build/include_what_you_use exclude_files=external|build diff --git a/libhydrosphere/include/hs/mem.hpp b/libhydrosphere/include/hs/mem.hpp new file mode 100644 index 0000000..41fd987 --- /dev/null +++ b/libhydrosphere/include/hs/mem.hpp @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2019 Hydrosphère Developers + * + * Licensed under the Apache License, Version 2.0 or the MIT license + * , at your + * option. This file may not be copied, modified, or distributed + * except according to those terms. + */ + +#pragma once + +#include +#include +#include diff --git a/libhydrosphere/source/common/compiler/allocator.cpp b/libhydrosphere/include/hs/mem/allocator.hpp similarity index 94% rename from libhydrosphere/source/common/compiler/allocator.cpp rename to libhydrosphere/include/hs/mem/allocator.hpp index 4fca7bf..e895a06 100644 --- a/libhydrosphere/source/common/compiler/allocator.cpp +++ b/libhydrosphere/include/hs/mem/allocator.hpp @@ -8,12 +8,10 @@ * except according to those terms. */ +#pragma once #include -constexpr size_t memory_align(size_t size, size_t alignment) { - return (size + alignment - 1) & ~(alignment - 1); -} - +namespace hs::mem { /** * \short Impelements a memory allocator that maps a given block * of memory and manages it. @@ -99,4 +97,9 @@ class MemoryAllocator { size_t region_size_; size_t used_memory_; + + constexpr size_t memory_align(size_t size, size_t alignment) { + return (size + alignment - 1) & ~(alignment - 1); + } }; +} // namespace hs::mem diff --git a/libhydrosphere/source/common/compiler/shared_ptr.cpp b/libhydrosphere/include/hs/mem/shared_ptr.hpp similarity index 99% rename from libhydrosphere/source/common/compiler/shared_ptr.cpp rename to libhydrosphere/include/hs/mem/shared_ptr.hpp index e1ddeed..e94146a 100644 --- a/libhydrosphere/source/common/compiler/shared_ptr.cpp +++ b/libhydrosphere/include/hs/mem/shared_ptr.hpp @@ -8,6 +8,9 @@ * except according to those terms. */ +#pragma once + +namespace hs::mem { class shared_ptr_count { public: shared_ptr_count() : ref_count_(nullptr) {} @@ -263,3 +266,4 @@ shared_ptr dynamic_pointer_cast(const shared_ptr &ptr) noexcept { else return shared_ptr(ptr, p); } +} // namespace hs::mem diff --git a/libhydrosphere/source/common/compiler/unique_ptr.cpp b/libhydrosphere/include/hs/mem/unique_ptr.hpp similarity index 98% rename from libhydrosphere/source/common/compiler/unique_ptr.cpp rename to libhydrosphere/include/hs/mem/unique_ptr.hpp index 094344a..8ac0d48 100644 --- a/libhydrosphere/source/common/compiler/unique_ptr.cpp +++ b/libhydrosphere/include/hs/mem/unique_ptr.hpp @@ -8,6 +8,9 @@ * except according to those terms. */ +#pragma once + +namespace hs::mem { /** * \short A smart pointer that owns and manages another object through a pointer * and disposes of that object when the unique_ptr goes out of scope. @@ -162,3 +165,4 @@ template inline bool operator>(const unique_ptr &l, const unique_ptr &r) noexcept { return l.get() > r.get(); } +} // namespace hs::mem diff --git a/libhydrosphere/include/hs/svc/svc_api.hpp b/libhydrosphere/include/hs/svc/svc_api.hpp index 9dbdc10..a92c484 100644 --- a/libhydrosphere/include/hs/svc/svc_api.hpp +++ b/libhydrosphere/include/hs/svc/svc_api.hpp @@ -24,7 +24,8 @@ namespace svc { inline hs::Result SetHeapSize(uintptr_t *out_address, size_t heap_size) noexcept { - return hs::svc::SetHeapSize(out_address, heap_size); + return hs::svc::HYDROSPHERE_TARGET_ARCH_NAME::SetHeapSize(out_address, + heap_size); } inline hs::Result ArbitrateLock(hs::svc::Handle owner_thread_handle, diff --git a/libhydrosphere/meson.build b/libhydrosphere/meson.build index 91ddf04..da1dedd 100644 --- a/libhydrosphere/meson.build +++ b/libhydrosphere/meson.build @@ -19,10 +19,7 @@ assert(cc.get_id() == 'clang', 'This project only support the Clang compiler.') assert(meson.is_cross_build(), 'This project is supposed to be cross compiled.') common_sources = [ - 'source/common/compiler/allocator.cpp', 'source/common/compiler/memcpy.cpp', - 'source/common/compiler/shared_ptr.cpp', - 'source/common/compiler/unique_ptr.cpp', 'source/common/diag/diag_api.cpp', 'source/common/init/initialization.cpp', 'source/common/init/module_requirements.cpp', @@ -124,7 +121,7 @@ else cdata.set('HAVE_DOT', 'NO') endif - subdir('doc') + #subdir('doc') endif # Extra install From d7f9c7f77e4fa1ca5f470edb03ffee14b9a333f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kaenby=C5=8D?= <52895153+Kaenbyo@users.noreply.github.com> Date: Sat, 14 Sep 2019 18:27:42 +0200 Subject: [PATCH 12/15] Rewrite memory allocator Somehow git mv hasn't catch the rename huh? --- libhydrosphere/include/hs/hs_config.hpp | 2 + libhydrosphere/include/hs/mem.hpp | 2 +- libhydrosphere/include/hs/mem/allocator.hpp | 105 --------- .../include/hs/mem/memory_allocator.hpp | 209 ++++++++++++++++++ .../include/hs/util/util_intrusive_list.hpp | 12 +- 5 files changed, 222 insertions(+), 108 deletions(-) delete mode 100644 libhydrosphere/include/hs/mem/allocator.hpp create mode 100644 libhydrosphere/include/hs/mem/memory_allocator.hpp diff --git a/libhydrosphere/include/hs/hs_config.hpp b/libhydrosphere/include/hs/hs_config.hpp index 71a7f63..223cf24 100644 --- a/libhydrosphere/include/hs/hs_config.hpp +++ b/libhydrosphere/include/hs/hs_config.hpp @@ -12,9 +12,11 @@ #ifdef __aarch64__ #define HYDROSPHERE_TARGET_ARCH_NAME aarch64 #define HYDROSPHERE_TARGET_AARCH64 1 +#define __HS_CPU_PTR_ALIGN 0x10 #elif __arm__ #define HYDROSPHERE_TARGET_ARCH_NAME aarch32 #define HYDROSPHERE_TARGET_AARCH32 1 +#define __HS_CPU_PTR_ALIGN 0x4 #else #error "Cannot determine the target architecture!" #endif diff --git a/libhydrosphere/include/hs/mem.hpp b/libhydrosphere/include/hs/mem.hpp index 41fd987..71d4f35 100644 --- a/libhydrosphere/include/hs/mem.hpp +++ b/libhydrosphere/include/hs/mem.hpp @@ -10,6 +10,6 @@ #pragma once -#include +#include #include #include diff --git a/libhydrosphere/include/hs/mem/allocator.hpp b/libhydrosphere/include/hs/mem/allocator.hpp deleted file mode 100644 index e895a06..0000000 --- a/libhydrosphere/include/hs/mem/allocator.hpp +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (c) 2019 Hydrosphère Developers - * - * Licensed under the Apache License, Version 2.0 or the MIT license - * , at your - * option. This file may not be copied, modified, or distributed - * except according to those terms. - */ - -#pragma once -#include - -namespace hs::mem { -/** - * \short Impelements a memory allocator that maps a given block - * of memory and manages it. - */ -class MemoryAllocator { - public: - /** - * \short Constructs a new MemoryAllocator. - * \param[in] start_address The start address of the memory region. - * \param[in] region_size The size of the memory region. - */ - MemoryAllocator(void *start_address, size_t region_size) noexcept - : start_address_(start_address), region_size_(region_size) { - head_ = {0, nullptr}; - used_memory_ = 0; - } - - /** - * \short Constructs a new MemoryAllocator. - * \param[in] start_address The start address of the memory region. - * \param[in] end_address The end address of the memory region. - */ - MemoryAllocator(void *start_address, void *end_address) noexcept - : MemoryAllocator( - start_address, - static_cast(static_cast(end_address) - - static_cast(start_address))) {} - - /** - * \short Allocates memory on the mapped region. - * \param[in] size The size of memory to allocate. - * \param[in] alignment The alignment to use. Defaults to 16. - * \return Pointer to the allocated memory block. - */ - void *Allocate(size_t size, size_t alignment = 16) noexcept { - size = memory_align(size, alignment); - - if (size + used_memory_ > region_size_) return nullptr; - - MemoryBlock *block = head_.next; - MemoryBlock **head = &head_.next; - - // Find a free memory block. - while (block) { - if (block->size >= size) { - *head = block->next; - return reinterpret_cast(block) + sizeof(size_t); - } - - head = &block->next; - block = block->next; - } - - block = reinterpret_cast( - static_cast(start_address_) + used_memory_); - used_memory_ += size; - block->size = size; - - return reinterpret_cast(block) + sizeof(MemoryBlock); - } - - /** - * \short Frees allocated memory. - * \param[in] pointer A pointer to the memory block to free. - */ - void Free(void *pointer) noexcept { - auto block = reinterpret_cast( - static_cast(pointer) - sizeof(MemoryBlock)); - block->next = head_.next; - head_.next = block; - } - - private: - struct MemoryBlock { - size_t size; - MemoryBlock *next; - }; - - MemoryBlock head_; - - void *start_address_; - - size_t region_size_; - - size_t used_memory_; - - constexpr size_t memory_align(size_t size, size_t alignment) { - return (size + alignment - 1) & ~(alignment - 1); - } -}; -} // namespace hs::mem diff --git a/libhydrosphere/include/hs/mem/memory_allocator.hpp b/libhydrosphere/include/hs/mem/memory_allocator.hpp new file mode 100644 index 0000000..957926a --- /dev/null +++ b/libhydrosphere/include/hs/mem/memory_allocator.hpp @@ -0,0 +1,209 @@ +/* + * Copyright (c) 2019 Hydrosphère Developers + * + * Licensed under the Apache License, Version 2.0 or the MIT license + * , at your + * option. This file may not be copied, modified, or distributed + * except according to those terms. + */ + +#pragma once +#include + +#include +#include +#include +#include + +namespace hs::mem { +/** + * \short Impelements a memory allocator that maps a given block + * of memory and manages it. + */ +class MemoryAllocator { + public: + /** + * \short Constructs a new MemoryAllocator. + * \param[in] start_address The start address of the memory region. + * \param[in] region_size The size of the memory region. + */ + MemoryAllocator(void *start_address, size_t region_size) noexcept + : free_list(), start_address_(start_address), + region_size_(region_size) { + used_memory_ = 0; + + MemoryBlock *first_block = reinterpret_cast( + start_address); + // Enforce the constructor is called to avoid using uninialized data. + new (first_block) MemoryBlock(); + + first_block->size = region_size - sizeof(MemoryBlock); + free_list.push_front(*first_block); + } + + /** + * \short Constructs a new MemoryAllocator. + * \param[in] start_address The start address of the memory region. + * \param[in] end_address The end address of the memory region. + */ + MemoryAllocator(void *start_address, void *end_address) noexcept + : MemoryAllocator( + start_address, + static_cast(static_cast(end_address) - + static_cast(start_address))) {} + + /** + * \short Allocates memory on the mapped region. + * \param[in] size The size of memory to allocate. + * \param[in] alignment The alignment to use. Defaults to 16. + * \return Pointer to the allocated memory block. + */ + void *Allocate(size_t size, size_t alignment = __HS_CPU_PTR_ALIGN) + noexcept { + if (size == 0 || alignment == 0) { + return nullptr; + } + + // Ensure CPU ptr alignment + size = memory_align(memory_align(size, alignment), __HS_CPU_PTR_ALIGN); + + void *ptr = nullptr; + + for (auto it = free_list.begin(); it != free_list.end(); ++it) { + // FIXME: Really really dirty, change this! + hs::util::IntrusiveList::const_iterator cit = + hs::util::IntrusiveList::const_iterator(it); + + MemoryBlock &free_block = *it; + + __HS_DEBUG_ASSERT(free_block.size != 0); + + if (free_block.size < size) { + continue; + } + + size_t remaining_bytes = free_block.size - size; + + // Found a block that fit corectly. + if (remaining_bytes >= sizeof(MemoryBlock) || + remaining_bytes >= 0) { + char *block_data_start = reinterpret_cast(&free_block) + + sizeof(MemoryBlock); + + if (remaining_bytes > sizeof(MemoryBlock)) { + // We have enough space for the block and data, we split + // our block. + free_block.size -= remaining_bytes; + + MemoryBlock *new_block = reinterpret_cast( + block_data_start + free_block.size); + // Enforce the constructor is called to avoid using + // uninialized data. + new (new_block) MemoryBlock(); + new_block->size = remaining_bytes - sizeof(MemoryBlock); + + free_list.insert(cit, *new_block); + } + + ptr = block_data_start; + free_list.remove(*cit); + break; + } + } + + return ptr; + } + + /** + * \short Frees allocated memory. + * \param[in] pointer A pointer to the memory block to free. + */ + void Free(void *pointer) noexcept { + if (pointer == nullptr) { + return; + } + + MemoryBlock *block = GetMemoryBlockFromUserAddress(pointer); + + // If the free list is empty, add the block to it! + if (free_list.empty()) { + free_list.push_front(*block); + } else { + MemoryBlock *front_free_block = &free_list.front(); + + // If the block is before the first element of the free list + if (front_free_block < block) { + // If our block is just before the first element, we replace + // the first element + if (block->IsJustAfterMemoryBlock(front_free_block)) { + block->size += front_free_block->size; + free_list.remove(*front_free_block); + } + + free_list.push_front(*block); + + return; + } + + // Search for the position to insert ourself. + auto target_position = free_list.cbegin(); + + for (; target_position != free_list.cend(); ++target_position) { + const MemoryBlock *tmp = &*target_position; + if (tmp > block) { + break; + } + } + + // Insert the our block in the free list. + free_list.insert(target_position, *block); + + // If our block is just before the our target position, we replace + // the first element. + // TODO(Kaenbyō): Also try to merge chunk before the block that is + // being freed. + if (block->IsJustAfterMemoryBlock(&*target_position)) { + block->size += front_free_block->size; + free_list.erase(target_position); + } + } + } + + private: + struct MemoryBlock : public hs::util::IntrusiveListElement<> { + size_t size; + char reserved[4]; + + bool IsJustAfterMemoryBlock(const MemoryBlock *other) const { + const char *other_raw = reinterpret_cast(other); + const char *this_raw = reinterpret_cast(this); + + return other_raw + other->size == this_raw; + } + }; + + #if HYDROSPHERE_TARGET_AARCH64 + static_assert(sizeof(MemoryBlock) == 0x20, "MemoryBlock size isn't right"); + #elif HYDROSPHERE_TARGET_AARCH32 + static_assert(sizeof(MemoryBlock) == 0x10, "MemoryBlock size isn't right"); + #endif + + hs::util::IntrusiveList free_list; + + void *start_address_; + + size_t region_size_; + + size_t used_memory_; + + constexpr size_t memory_align(size_t size, size_t alignment) { + return (size + alignment - 1) & ~(alignment - 1); + } + + MemoryBlock *GetMemoryBlockFromUserAddress(void *pointer) noexcept { + return reinterpret_cast( + static_cast(pointer) - sizeof(MemoryBlock)); + } +}; +} // namespace hs::mem diff --git a/libhydrosphere/include/hs/util/util_intrusive_list.hpp b/libhydrosphere/include/hs/util/util_intrusive_list.hpp index 3cd60bb..1118f62 100644 --- a/libhydrosphere/include/hs/util/util_intrusive_list.hpp +++ b/libhydrosphere/include/hs/util/util_intrusive_list.hpp @@ -459,7 +459,7 @@ class IntrusiveList { */ iterator erase(const_iterator position, const_iterator last) noexcept { if (position == last) { - return last; + return iterator(last); } iterator temp = iterator(position); @@ -490,7 +490,15 @@ class IntrusiveList { void splice(const_iterator position, IntrusiveList&& x, const_iterator first, const_iterator last) noexcept;*/ - // void remove(const T& value); + void remove(const T& value) { + const_iterator v = cbegin(); + for (; v != cend(); ++v) { + if (&value == &*v) { + erase(v); + break; + } + } + } // template void remove_if(Predicate pred); // maybe uneeded as we don't have the standard library. From 8f337314ed71a1f2fc6854d85e24b0231a85f0e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kaenby=C5=8D?= <52895153+Kaenbyo@users.noreply.github.com> Date: Sat, 14 Sep 2019 18:35:52 +0200 Subject: [PATCH 13/15] Add some sanity checks in MemoryAllocator::Free --- .../include/hs/mem/memory_allocator.hpp | 48 ++++++++++++------- 1 file changed, 31 insertions(+), 17 deletions(-) diff --git a/libhydrosphere/include/hs/mem/memory_allocator.hpp b/libhydrosphere/include/hs/mem/memory_allocator.hpp index 957926a..bdb45f9 100644 --- a/libhydrosphere/include/hs/mem/memory_allocator.hpp +++ b/libhydrosphere/include/hs/mem/memory_allocator.hpp @@ -29,7 +29,7 @@ class MemoryAllocator { * \param[in] region_size The size of the memory region. */ MemoryAllocator(void *start_address, size_t region_size) noexcept - : free_list(), start_address_(start_address), + : free_list_(), start_address_(start_address), region_size_(region_size) { used_memory_ = 0; @@ -39,7 +39,7 @@ class MemoryAllocator { new (first_block) MemoryBlock(); first_block->size = region_size - sizeof(MemoryBlock); - free_list.push_front(*first_block); + free_list_.push_front(*first_block); } /** @@ -70,7 +70,7 @@ class MemoryAllocator { void *ptr = nullptr; - for (auto it = free_list.begin(); it != free_list.end(); ++it) { + for (auto it = free_list_.begin(); it != free_list_.end(); ++it) { // FIXME: Really really dirty, change this! hs::util::IntrusiveList::const_iterator cit = hs::util::IntrusiveList::const_iterator(it); @@ -103,11 +103,11 @@ class MemoryAllocator { new (new_block) MemoryBlock(); new_block->size = remaining_bytes - sizeof(MemoryBlock); - free_list.insert(cit, *new_block); + free_list_.insert(cit, *new_block); } ptr = block_data_start; - free_list.remove(*cit); + free_list_.remove(*cit); break; } } @@ -126,11 +126,16 @@ class MemoryAllocator { MemoryBlock *block = GetMemoryBlockFromUserAddress(pointer); + // Invalid pointer + if (block == nullptr) { + return; + } + // If the free list is empty, add the block to it! - if (free_list.empty()) { - free_list.push_front(*block); + if (free_list_.empty()) { + free_list_.push_front(*block); } else { - MemoryBlock *front_free_block = &free_list.front(); + MemoryBlock *front_free_block = &free_list_.front(); // If the block is before the first element of the free list if (front_free_block < block) { @@ -138,18 +143,18 @@ class MemoryAllocator { // the first element if (block->IsJustAfterMemoryBlock(front_free_block)) { block->size += front_free_block->size; - free_list.remove(*front_free_block); + free_list_.remove(*front_free_block); } - free_list.push_front(*block); + free_list_.push_front(*block); return; } // Search for the position to insert ourself. - auto target_position = free_list.cbegin(); + auto target_position = free_list_.cbegin(); - for (; target_position != free_list.cend(); ++target_position) { + for (; target_position != free_list_.cend(); ++target_position) { const MemoryBlock *tmp = &*target_position; if (tmp > block) { break; @@ -157,7 +162,7 @@ class MemoryAllocator { } // Insert the our block in the free list. - free_list.insert(target_position, *block); + free_list_.insert(target_position, *block); // If our block is just before the our target position, we replace // the first element. @@ -165,7 +170,7 @@ class MemoryAllocator { // being freed. if (block->IsJustAfterMemoryBlock(&*target_position)) { block->size += front_free_block->size; - free_list.erase(target_position); + free_list_.erase(target_position); } } } @@ -189,7 +194,7 @@ class MemoryAllocator { static_assert(sizeof(MemoryBlock) == 0x10, "MemoryBlock size isn't right"); #endif - hs::util::IntrusiveList free_list; + hs::util::IntrusiveList free_list_; void *start_address_; @@ -202,8 +207,17 @@ class MemoryAllocator { } MemoryBlock *GetMemoryBlockFromUserAddress(void *pointer) noexcept { - return reinterpret_cast( - static_cast(pointer) - sizeof(MemoryBlock)); + char *block_position = static_cast(pointer) - + sizeof(MemoryBlock); + char *start_address = static_cast(start_address_); + + // Check the pointer sanity before accepting it + if (start_address_ < block_position || + block_position > start_address + region_size_) { + return nullptr; + } + + return reinterpret_cast(block_position); } }; } // namespace hs::mem From d6680530fbb104e96ea1dda479c42a85c4c1428c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kaenby=C5=8D?= <52895153+Kaenbyo@users.noreply.github.com> Date: Sat, 14 Sep 2019 22:46:26 +0200 Subject: [PATCH 14/15] Implement allocate_unique This permit to get ride of the usage of the default delete keyword and the usage of a custom allocator. --- libhydrosphere/include/hs/mem.hpp | 2 + .../include/hs/mem/memory_allocator.hpp | 2 +- libhydrosphere/include/hs/mem/memory_api.hpp | 54 +++++++++++++++++++ .../include/hs/mem/memory_default_delete.hpp | 24 +++++++++ libhydrosphere/include/hs/mem/unique_ptr.hpp | 38 +++++++++---- .../include/hs/util/util_std_new.hpp | 2 +- .../include/hs/util/util_template_api.hpp | 12 +++++ 7 files changed, 121 insertions(+), 13 deletions(-) create mode 100644 libhydrosphere/include/hs/mem/memory_api.hpp create mode 100644 libhydrosphere/include/hs/mem/memory_default_delete.hpp diff --git a/libhydrosphere/include/hs/mem.hpp b/libhydrosphere/include/hs/mem.hpp index 71d4f35..63131e5 100644 --- a/libhydrosphere/include/hs/mem.hpp +++ b/libhydrosphere/include/hs/mem.hpp @@ -11,5 +11,7 @@ #pragma once #include +#include +#include #include #include diff --git a/libhydrosphere/include/hs/mem/memory_allocator.hpp b/libhydrosphere/include/hs/mem/memory_allocator.hpp index bdb45f9..966144c 100644 --- a/libhydrosphere/include/hs/mem/memory_allocator.hpp +++ b/libhydrosphere/include/hs/mem/memory_allocator.hpp @@ -202,7 +202,7 @@ class MemoryAllocator { size_t used_memory_; - constexpr size_t memory_align(size_t size, size_t alignment) { + constexpr size_t memory_align(size_t size, size_t alignment) const { return (size + alignment - 1) & ~(alignment - 1); } diff --git a/libhydrosphere/include/hs/mem/memory_api.hpp b/libhydrosphere/include/hs/mem/memory_api.hpp new file mode 100644 index 0000000..6bd84fe --- /dev/null +++ b/libhydrosphere/include/hs/mem/memory_api.hpp @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2019 Hydrosphère Developers + * + * Licensed under the Apache License, Version 2.0 or the MIT license + * , at your + * option. This file may not be copied, modified, or distributed + * except according to those terms. + */ + +#pragma once + +#include +#include +#include +#include +#include + +namespace hs::mem { +template struct memory_allocator_delete { + Alloc &allocator; + // Default constructor + constexpr explicit memory_allocator_delete(Alloc &allocator) noexcept : + allocator(allocator) {} + + template memory_allocator_delete( + const memory_allocator_delete& d) noexcept : + allocator(d.allocator) {} + + void operator()(T* ptr) const { + ptr->~T(); + allocator.Free(ptr); + } +}; + +template + unique_ptr> allocate_unique(Alloc& a, + Args&&... args) { + + // First we allocate T. + T *data = reinterpret_cast(a.Allocate(sizeof(T))); + + // Allocation might fail so assert in that case. + __HS_ASSERT(data != nullptr); + + // Then we call the constructor using args sent by the user. + new (data) T(hs::util::forward(args)...); + + // Finally construct the unique_ptr. + return unique_ptr>(data, + memory_allocator_delete(a)); +} + +} // namespace hs::mem diff --git a/libhydrosphere/include/hs/mem/memory_default_delete.hpp b/libhydrosphere/include/hs/mem/memory_default_delete.hpp new file mode 100644 index 0000000..aa2e890 --- /dev/null +++ b/libhydrosphere/include/hs/mem/memory_default_delete.hpp @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2019 Hydrosphère Developers + * + * Licensed under the Apache License, Version 2.0 or the MIT license + * , at your + * option. This file may not be copied, modified, or distributed + * except according to those terms. + */ + +#pragma once + +namespace hs::mem { +template struct default_delete { + // Default constructor + constexpr default_delete() noexcept = default; + + template default_delete(const default_delete& d) noexcept; + + void operator()(T* ptr) const { + delete ptr; + } +}; +} // namespace hs::mem diff --git a/libhydrosphere/include/hs/mem/unique_ptr.hpp b/libhydrosphere/include/hs/mem/unique_ptr.hpp index 8ac0d48..45934fd 100644 --- a/libhydrosphere/include/hs/mem/unique_ptr.hpp +++ b/libhydrosphere/include/hs/mem/unique_ptr.hpp @@ -10,32 +10,46 @@ #pragma once +#include + namespace hs::mem { /** * \short A smart pointer that owns and manages another object through a pointer * and disposes of that object when the unique_ptr goes out of scope. */ -template +template > class unique_ptr { public: - using element_type = T; + typedef T* pointer; + typedef T element_type; + typedef Deleter deleter_type; /** * \short Constructs a new unique_ptr from a nullptr. */ - unique_ptr() noexcept : native_ptr_(nullptr) {} + unique_ptr() noexcept : native_ptr_(nullptr), deleter_() {} /** * \short Constructs a new unique_ptr given a raw pointer. * \param[in] ptr The pointer to be wrapped. */ - explicit unique_ptr(T *ptr) noexcept : native_ptr_(ptr) {} + explicit unique_ptr(T *ptr) noexcept : native_ptr_(ptr), deleter_() {} + + /** + * \short Constructs a new unique_ptr given a raw pointer. + * \param[in] ptr The pointer to be wrapped. + * \param[in] d The destructor to use when disposing of the pointer. + */ + explicit unique_ptr(T *ptr, Deleter d) noexcept : native_ptr_(ptr), + deleter_(d) {} /** * \short Constructs a new unique_ptr from an existing unique_ptr. * \param[in] ptr The unique_ptr to use. */ - unique_ptr(const unique_ptr &ptr) noexcept : native_ptr_(ptr.native_ptr_) { + unique_ptr(const unique_ptr &ptr) noexcept : native_ptr_(ptr.native_ptr_), + deleter_(ptr.deleter_) { const_cast(ptr).native_ptr_ = nullptr; // const_cast to force ownership transfer. } @@ -63,7 +77,7 @@ class unique_ptr { * \short Replaces the managed object. * \param[in] ptr The pointer to replace the contents with. */ - void reset(T *ptr) noexcept { + void reset(pointer ptr) noexcept { static_assert((nullptr == ptr) || (native_ptr_ != ptr), ""); destroy(); native_ptr_ = ptr; @@ -83,8 +97,8 @@ class unique_ptr { * \short Returns a pointer to the managed object and releases the * ownership. */ - inline T *release() noexcept { - T *temp = native_ptr_; + inline pointer release() noexcept { + pointer temp = native_ptr_; native_ptr_ = nullptr; return temp; } @@ -117,13 +131,15 @@ class unique_ptr { /** * \short Returns a pointer to the managed object. */ - inline T *get() const noexcept { return native_ptr_; } + inline pointer get() const noexcept { return native_ptr_; } private: - T *native_ptr_; + pointer native_ptr_; + deleter_type deleter_; inline void destroy() noexcept { - delete native_ptr_; + deleter_(native_ptr_); + native_ptr_ = nullptr; } diff --git a/libhydrosphere/include/hs/util/util_std_new.hpp b/libhydrosphere/include/hs/util/util_std_new.hpp index 8c211f6..9e5ef42 100644 --- a/libhydrosphere/include/hs/util/util_std_new.hpp +++ b/libhydrosphere/include/hs/util/util_std_new.hpp @@ -17,5 +17,5 @@ inline void* operator new(size_t, void* __p) throw() { return __p; } inline void* operator new[](size_t, void* __p) throw() { return __p; } // Default placement versions of operator delete. -inline void operator delete(void*, void*)throw() {} +inline void operator delete(void*, void*) throw() {} inline void operator delete[](void*, void*) throw() {} diff --git a/libhydrosphere/include/hs/util/util_template_api.hpp b/libhydrosphere/include/hs/util/util_template_api.hpp index 674639f..8583c31 100644 --- a/libhydrosphere/include/hs/util/util_template_api.hpp +++ b/libhydrosphere/include/hs/util/util_template_api.hpp @@ -36,4 +36,16 @@ struct integral_constant { template struct is_pod : public integral_constant {}; +template< class T > struct remove_reference {typedef T type;}; +template< class T > struct remove_reference {typedef T type;}; +template< class T > struct remove_reference {typedef T type;}; + +template T&& forward(typename remove_reference::type& t) noexcept { + return static_cast(t); +} +template T&& forward(typename remove_reference::type&& t) + noexcept { + return static_cast(t); +} + } // namespace hs::util From 61adfd3137b2a32a9ecc43af1a504c370fc0e002 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kaenby=C5=8D?= <52895153+Kaenbyo@users.noreply.github.com> Date: Sun, 15 Sep 2019 13:31:53 +0200 Subject: [PATCH 15/15] Implement allocate_shared --- libhydrosphere/include/hs/mem/memory_api.hpp | 27 +++++ libhydrosphere/include/hs/mem/shared_ptr.hpp | 103 +++++++++++++------ libhydrosphere/include/hs/mem/unique_ptr.hpp | 5 +- libhydrosphere/meson.build | 2 +- 4 files changed, 103 insertions(+), 34 deletions(-) diff --git a/libhydrosphere/include/hs/mem/memory_api.hpp b/libhydrosphere/include/hs/mem/memory_api.hpp index 6bd84fe..7f53d0a 100644 --- a/libhydrosphere/include/hs/mem/memory_api.hpp +++ b/libhydrosphere/include/hs/mem/memory_api.hpp @@ -12,6 +12,7 @@ #include #include +#include #include #include #include @@ -51,4 +52,30 @@ template memory_allocator_delete(a)); } +template + shared_ptr< + T, + memory_allocator_delete, + memory_allocator_delete + > allocate_shared(Alloc& a, Args&&... args) { + // First we allocate T. + T *data = reinterpret_cast(a.Allocate(sizeof(T))); + + // Allocation might fail so assert in that case. + __HS_ASSERT(data != nullptr); + + // Then we call the constructor using args sent by the user. + new (data) T(hs::util::forward(args)...); + + // Finally construct the shared_ptr. + return shared_ptr, + memory_allocator_delete>( + data, + memory_allocator_delete(a), + memory_allocator_delete(a), + a); +} + + + } // namespace hs::mem diff --git a/libhydrosphere/include/hs/mem/shared_ptr.hpp b/libhydrosphere/include/hs/mem/shared_ptr.hpp index e94146a..5ee644b 100644 --- a/libhydrosphere/include/hs/mem/shared_ptr.hpp +++ b/libhydrosphere/include/hs/mem/shared_ptr.hpp @@ -10,17 +10,32 @@ #pragma once +#include + +#include +#include + namespace hs::mem { +template class shared_ptr_count { public: - shared_ptr_count() : ref_count_(nullptr) {} + shared_ptr_count(long *ref_count, DeleterRefCount &d) : + ref_count_(ref_count), deleter_ref_count_(d) { + if (ref_count_ != nullptr) { + *ref_count_ = 0; + } + } - shared_ptr_count(const shared_ptr_count &count) = default; + shared_ptr_count(const shared_ptr_count &count) = default; - void swap(shared_ptr_count &count) noexcept { + void swap(shared_ptr_count &count) noexcept { auto temp = ref_count_; ref_count_ = count.ref_count_; count.ref_count_ = temp; + + auto temp_deleter = deleter_ref_count_; + deleter_ref_count_ = count.deleter_ref_count_; + count.deleter_ref_count_ = deleter_ref_count_; } long use_count() const noexcept { @@ -31,20 +46,22 @@ class shared_ptr_count { void acquire(U *ptr) { if (ptr == nullptr) return; + // If the ref_count isn't allocated, we are always sure that we don't + // have some custom allocator so we use the standard new. if (ref_count_ == nullptr) ref_count_ = new long(1); // may throw std::bad_alloc (?) else ++(*ref_count_); } - template - void release(U *ptr) noexcept { + template + void release(D &deleter, U *ptr) noexcept { if (ref_count_ == nullptr) return; --(*ref_count_); if (*ref_count_ <= 0) { - delete ptr; - delete ref_count_; + deleter(ptr); + deleter_ref_count_(ref_count_); } ref_count_ = nullptr; } @@ -52,27 +69,58 @@ class shared_ptr_count { private: // Internal reference counter. long *ref_count_; + DeleterRefCount &deleter_ref_count_; }; /** * \short A smart pointer that retains shared ownership of an object through a * pointer. */ -template +template , + class DeleterRefCount = hs::mem::default_delete> class shared_ptr { public: - using element_type = T; + typedef T* pointer; + typedef T element_type; + typedef Deleter deleter_type; /** * \short Constructs a new shared_ptr from a nullptr. */ - shared_ptr() noexcept : native_ptr_(nullptr), count_() {} + shared_ptr() noexcept : native_ptr_(nullptr), deleter_(), count_(nullptr) {} /** * \short Constructs a new shared_ptr given a raw pointer. * \param[in] ptr The raw pointer to manage. */ - explicit shared_ptr(T *ptr) : count_() { acquire(ptr); } + explicit shared_ptr(pointer ptr) : deleter_(), count_(nullptr) { + acquire(ptr); + } + + /** + * \short Constructs a new shared_ptr given a raw pointer and a destructor. + * \param[in] ptr The raw pointer to manage. + * \param[in] d The destructor to use when disposing of the pointer. + */ + explicit shared_ptr(pointer ptr, Deleter d) + : deleter_(d), count_(nullptr) { + acquire(ptr); + } + + /** + * \short Constructs a new shared_ptr given a raw pointer, a destructor and an allocator. + * \param[in] ptr The raw pointer to manage. + * \param[in] d The destructor to use when disposing of the pointer. + * \param[in] d2 The destructor to use when disposing of the refcount. + * \param[in] alloc The allocator to use when allocating the refcount. + */ + template + shared_ptr(pointer ptr, Deleter d, DeleterRefCount d2, Alloc &alloc) + : deleter_(d), + count_(reinterpret_cast(alloc.Allocate(sizeof(long))), d2) { + acquire(ptr); + } /** * \short Constructs a new shared_ptr to share ownership. @@ -82,7 +130,8 @@ class shared_ptr { * two separate and pointers! */ template - shared_ptr(const shared_ptr &ptr, T *p) : count_(ptr.count_) { + shared_ptr(const shared_ptr &ptr, pointer p) + : deleter_(ptr.deleter_), count_(ptr.count_) { acquire(p); } @@ -93,20 +142,17 @@ class shared_ptr { */ template explicit shared_ptr(const shared_ptr &ptr) noexcept - : count_(ptr.count_) { - static_assert(ptr.native_ptr_ == nullptr || ptr.count_.use_count() != 0, - ""); + : deleter_(ptr.deleter_), count_(ptr.count_) { acquire(static_cast::element_type *>( ptr.native_ptr_)); } /** - * \short Constructs a new shared_ptr by the copy-and-swap idiom. + * \short Constructs a new sàhared_ptr by the copy-and-swap idiom. * \param[in] ptr The shared_ptr to use. */ - shared_ptr(const shared_ptr &ptr) noexcept : count_(ptr.count_) { - static_assert(ptr.native_ptr_ == nullptr || ptr.count_.use_count() != 0, - ""); + shared_ptr(const shared_ptr &ptr) noexcept + : deleter_(ptr.deleter_), count_(ptr.count_) { acquire(ptr.native_ptr_); } @@ -133,8 +179,7 @@ class shared_ptr { * \short Replaces the managed object. * \param[in] p The pointer to replace the contents with. */ - void reset(T *p) { - static_assert(p == nullptr || native_ptr_ != p, ""); + void reset(pointer p) { release(); acquire(p); // May throw std::bad_alloc (?) } @@ -176,7 +221,6 @@ class shared_ptr { * \short Dereferences the stored pointer. */ T &operator*() const noexcept { - static_assert(native_ptr_ != nullptr, ""); return *native_ptr_; } @@ -184,32 +228,33 @@ class shared_ptr { * \short Provides access to the stored pointer. */ T *operator->() const noexcept { - static_assert(native_ptr_ != nullptr, ""); return native_ptr_; } /** * \short Returns the stored pointer. */ - T *get() const noexcept { return native_ptr_; } + pointer get() const noexcept { return native_ptr_; } private: - T *native_ptr_; + pointer native_ptr_; + deleter_type deleter_; + + shared_ptr_count count_; - shared_ptr_count count_; // This allows pointer_cast functions to share the // reference count between different shared_ptr types. - template + template friend class shared_ptr; - void acquire(T *p) { + void acquire(pointer p) { count_.acquire(p); // May throw std::bad_alloc (?) native_ptr_ = p; } void release() noexcept { - count_.release(native_ptr_); + count_.release(deleter_, native_ptr_); native_ptr_ = nullptr; } }; diff --git a/libhydrosphere/include/hs/mem/unique_ptr.hpp b/libhydrosphere/include/hs/mem/unique_ptr.hpp index 45934fd..dd25be0 100644 --- a/libhydrosphere/include/hs/mem/unique_ptr.hpp +++ b/libhydrosphere/include/hs/mem/unique_ptr.hpp @@ -37,7 +37,7 @@ class unique_ptr { explicit unique_ptr(T *ptr) noexcept : native_ptr_(ptr), deleter_() {} /** - * \short Constructs a new unique_ptr given a raw pointer. + * \short Constructs a new unique_ptr given a raw pointer and a destructor. * \param[in] ptr The pointer to be wrapped. * \param[in] d The destructor to use when disposing of the pointer. */ @@ -78,7 +78,6 @@ class unique_ptr { * \param[in] ptr The pointer to replace the contents with. */ void reset(pointer ptr) noexcept { - static_assert((nullptr == ptr) || (native_ptr_ != ptr), ""); destroy(); native_ptr_ = ptr; } @@ -116,7 +115,6 @@ class unique_ptr { * \short Dereferences pointer to the managed object. */ inline T &operator*() const noexcept { - static_assert(nullptr != native_ptr_, ""); return *native_ptr_; } @@ -124,7 +122,6 @@ class unique_ptr { * \short Provides access to a pointer to managed object. */ inline T *operator->() const noexcept { - static_assert(nullptr != native_ptr_, ""); return native_ptr_; } diff --git a/libhydrosphere/meson.build b/libhydrosphere/meson.build index da1dedd..95b66a2 100644 --- a/libhydrosphere/meson.build +++ b/libhydrosphere/meson.build @@ -121,7 +121,7 @@ else cdata.set('HAVE_DOT', 'NO') endif - #subdir('doc') + subdir('doc') endif # Extra install