NBEngine/engine/NBCore/Utils.hpp
2026-06-11 04:24:06 -05:00

80 lines
1.7 KiB
C++

#pragma once
#ifndef _NB_CORE_TYPES
#define _NB_CORE_TYPES
#include <mutex>
#include <vector>
#include "Errors.hpp"
namespace nb {
using ByteVector = std::vector<uint8_t>;
class ObjectManagerError : public Error<ObjectManagerError> {
using Base = Error<ObjectManagerError>;
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 <typename T>
class ThreadsafeObjectLock;
template <typename T>
class ThreadsafeObject {
using Codes = ObjectManagerError::Codes;
public:
ThreadsafeObject(T&& obj)
: _obj(std::make_shared<T>(obj)) {}
ThreadsafeObjectLock<T> lock() {
return ThreadsafeObjectLock<T>(this);
}
friend ThreadsafeObjectLock<T>;
protected:
std::shared_ptr<T> _obj;
mutable std::recursive_mutex _mutex;
};
template <typename T>
class ThreadsafeObjectLock {
public:
ThreadsafeObjectLock(const ThreadsafeObjectLock&) = delete;
ThreadsafeObjectLock operator=(const ThreadsafeObjectLock&) = delete;
~ThreadsafeObjectLock() {
_manager->_mutex.unlock();
}
T* operator->() {
return _manager->_obj.get();
}
friend ThreadsafeObject<T>;
protected:
ThreadsafeObjectLock(
ThreadsafeObject<T>* const manager_
) : _manager(manager_) {
if (!_manager) {
using Codes = ObjectManagerError::Codes;
THROW(ObjectManagerError(Codes::NO_MANAGER));
}
_manager->_mutex.lock();
}
ThreadsafeObject<T>* const _manager;
};
} // namespace nb
#endif // _NB_CORE_TYPES