From 120b57b78455a53e8fb0116ab05916a9d1de7a97 Mon Sep 17 00:00:00 2001 From: Thiago Silva Date: Mon, 17 Apr 2023 22:23:55 -0300 Subject: [PATCH] Try thread-safe optional_ptr --- nano/lib/optional_ptr.hpp | 50 ++++++++++++++++++++++++++++++--------- 1 file changed, 39 insertions(+), 11 deletions(-) diff --git a/nano/lib/optional_ptr.hpp b/nano/lib/optional_ptr.hpp index 56695fc3ed..e5b3df4b61 100644 --- a/nano/lib/optional_ptr.hpp +++ b/nano/lib/optional_ptr.hpp @@ -1,5 +1,6 @@ #pragma once +#include #include #include @@ -16,28 +17,32 @@ namespace nano * main difference being that it's copyable. */ template -class optional_ptr +class optional_ptr final { static_assert (sizeof (T) > alignof (std::max_align_t), "Use [std|boost]::optional"); public: - optional_ptr () = default; + explicit optional_ptr () + { + nano::lock_guard lock{ mutex }; + ptr = nullptr; + } - optional_ptr (T const & value) : - ptr (new T{ value }) + explicit optional_ptr (T const & value) { + nano::lock_guard lock{ mutex }; + ptr = std::make_unique (value); } - optional_ptr (optional_ptr const & other) + explicit optional_ptr (optional_ptr const & other) { - if (other && other.ptr) - { - ptr = std::make_unique (*other.ptr); - } + nano::lock_guard lock{ mutex }; + ptr = (other && other.ptr) ? std::make_unique (*other.ptr) : nullptr; } optional_ptr & operator= (optional_ptr const & other) { + nano::lock_guard lock{ mutex }; if (other && other.ptr) { ptr = std::make_unique (*other.ptr); @@ -45,49 +50,72 @@ class optional_ptr return *this; } + optional_ptr & operator= (T const & t_object) + { + auto new_ptr = std::make_unique (t_object); + nano::lock_guard lock{ mutex }; + ptr.swap (new_ptr); + return *this; + } + + ~optional_ptr () + { + nano::lock_guard lock{ mutex }; + ptr.reset (nullptr); + } + T & operator* () { + nano::lock_guard lock{ mutex }; return *ptr; } T const & operator* () const { + nano::lock_guard lock{ mutex }; return *ptr; } T * const operator-> () { + nano::lock_guard lock{ mutex }; return ptr.operator-> (); } T const * const operator-> () const { + nano::lock_guard lock{ mutex }; return ptr.operator-> (); } T const * const get () const { + nano::lock_guard lock{ mutex }; debug_assert (is_initialized ()); return ptr.get (); } T * const get () { + nano::lock_guard lock{ mutex }; debug_assert (is_initialized ()); return ptr.get (); } explicit operator bool () const { + nano::lock_guard lock{ mutex }; return static_cast (ptr); } - bool is_initialized () const + [[nodiscard]] bool is_initialized () const { + nano::lock_guard lock{ mutex }; return static_cast (ptr); } private: - std::unique_ptr ptr{ nullptr }; + std::unique_ptr ptr; + mutable nano::mutex mutex; }; }