Files
OpenVulkano/openVulkanoCpp/Data/Concurent/MutexProtectedObject.hpp
2023-10-03 19:52:23 +02:00

112 lines
2.3 KiB
C++

/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#pragma once
#include "Spintex.hpp"
#include <mutex>
#include <shared_mutex>
namespace OpenVulkano
{
template<typename T, typename MUTEX = std::mutex>
class MutexProtectedObject
{
protected:
T object;
MUTEX mutex;
public:
class Accessor
{
std::unique_lock<MUTEX> lock;
T& ref;
public:
Accessor(MUTEX& m, T& obj)
: lock(m), ref(obj)
{}
T* operator->() { return &ref; }
T& Get() { return ref; }
};
MutexProtectedObject() = default;
MutexProtectedObject(const T& initValue) : object(initValue) {}
template<typename... Args>
MutexProtectedObject(Args&&... args)
: object(std::forward<Args>(args)...)
{}
MutexProtectedObject(const MutexProtectedObject&) = delete;
Accessor Access()
{
return Accessor(mutex, object);
}
MutexProtectedObject& operator =(const T& value)
{
Accessor accessor = Access();
object = value;
return *this;
}
operator T()
{
Accessor accessor = Access();
return accessor.Get();
}
const T& UnsafeAccess() const { return object; }
};
template<typename T> using SpintexProtectedObject = MutexProtectedObject<T, Spintex>;
template<typename T, typename MUTEX = std::shared_mutex>
class SharedMutexProtectedObject : public MutexProtectedObject<T, MUTEX>
{
public:
class SharedAccessor
{
std::shared_lock<MUTEX> lock;
T& ref;
public:
SharedAccessor(MUTEX& m, T& obj)
: lock(m), ref(obj)
{}
const T* operator->() const { return &ref; }
const T& Get() const { return ref; }
T* operator->() { return &ref; }
T& Get() { return ref; }
};
SharedMutexProtectedObject() = default;
SharedMutexProtectedObject(const T& initValue) : MutexProtectedObject<T, MUTEX>(initValue) {}
template<typename... Args>
SharedMutexProtectedObject(Args&&... args)
: MutexProtectedObject<T, MUTEX>(std::forward<Args>(args)...)
{}
SharedMutexProtectedObject(const SharedMutexProtectedObject&) = delete;
SharedAccessor SharedAccess()
{
return SharedAccessor(MutexProtectedObject<T, MUTEX>::mutex, MutexProtectedObject<T, MUTEX>::object);
}
};
}