#pragma once #ifndef _NB_CORE_TYPES #define _NB_CORE_TYPES #include #include #include "Errors.hpp" namespace nb { using ByteVector = std::vector; class ObjectManagerError : public Error { using Base = Error; public: using Base::Base; enum Codes : unsigned int { UNDEFINED, NO_MANAGER, MANAGER_MISMATCH, LOCK_OVERFLOW, BAD_THREAD }; static const std::string type; static const ErrorCodeMap ErrorMessages; }; template class ThreadsafeObjectLock; template class ThreadsafeObject { using Codes = ObjectManagerError::Codes; public: ThreadsafeObject(T&& obj) : _obj(std::make_shared(obj)) {} ThreadsafeObjectLock lock() { return ThreadsafeObjectLock(this); } friend ThreadsafeObjectLock; protected: std::shared_ptr _obj; mutable std::recursive_mutex _mutex; }; template class ThreadsafeObjectLock { public: ThreadsafeObjectLock(const ThreadsafeObjectLock&) = delete; ThreadsafeObjectLock operator=(const ThreadsafeObjectLock&) = delete; ~ThreadsafeObjectLock() { _manager->_mutex.unlock(); } T* operator->() { return _manager->_obj.get(); } friend ThreadsafeObject; protected: ThreadsafeObjectLock( ThreadsafeObject* const manager_ ) : _manager(manager_) { if (!_manager) { using Codes = ObjectManagerError::Codes; THROW(ObjectManagerError(Codes::NO_MANAGER)); } _manager->_mutex.lock(); } ThreadsafeObject* const _manager; }; } // namespace nb #endif // _NB_CORE_TYPES