2eb5d3c3ff
Changed methods insert in Vertices and Edges to be valid even if exception occurs.
60 lines
1.2 KiB
C++
60 lines
1.2 KiB
C++
#pragma once
|
|
|
|
#include <cassert>
|
|
#include <memory>
|
|
#include <vector>
|
|
#include "storage/locking/lock_status.hpp"
|
|
|
|
namespace tx
|
|
{
|
|
|
|
template <class T>
|
|
class LockStore
|
|
{
|
|
class LockHolder
|
|
{
|
|
public:
|
|
LockHolder() noexcept = default;
|
|
|
|
template <class... Args>
|
|
LockHolder(T *lock, Args &&... args) noexcept : lock(lock)
|
|
{
|
|
assert(lock != nullptr);
|
|
auto status = lock->lock(std::forward<Args>(args)...);
|
|
|
|
if (status != LockStatus::Acquired) lock = nullptr;
|
|
}
|
|
|
|
LockHolder(const LockHolder &) = delete;
|
|
LockHolder(LockHolder &&other) noexcept : lock(other.lock)
|
|
{
|
|
other.lock = nullptr;
|
|
}
|
|
|
|
~LockHolder()
|
|
{
|
|
if (lock != nullptr) lock->unlock();
|
|
}
|
|
|
|
bool active() const noexcept { return lock != nullptr; }
|
|
|
|
private:
|
|
T *lock{nullptr};
|
|
};
|
|
|
|
public:
|
|
template <class... Args>
|
|
void take(T *lock, Args &&... args)
|
|
{
|
|
auto holder = LockHolder(lock, std::forward<Args>(args)...);
|
|
|
|
if (!holder.active()) return;
|
|
|
|
locks.emplace_back(LockHolder(lock, std::forward<Args>(args)...));
|
|
}
|
|
|
|
private:
|
|
std::vector<LockHolder> locks;
|
|
};
|
|
};
|