Files
pvxs/ioc/dbmanylocker.h
T
2023-05-09 10:17:32 -07:00

116 lines
2.6 KiB
C++

/*
* Copyright - See the COPYRIGHT that is included with this distribution.
* pvxs is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*
* Author George S. McIntyre <george@level-n.com>, 2023
*
*/
#ifndef PVXS_DBMANYLOCKER_H
#define PVXS_DBMANYLOCKER_H
#include <vector>
#include <dbCommon.h>
#include <dbLock.h>
namespace pvxs {
namespace ioc {
/**
* A lock that can lock multiple DB records simultaneously. To be used with DBManyLocker
*
* e.g.
* DBManyLock lock = DBManyLock(channels);
*/
class DBManyLock {
public:
dbLocker* pLocker{};
/**
* Empty lock
*/
DBManyLock()
:pLocker(nullptr) {
}
/**
* Create a many lock from a list of channels
*
* @param channels the list of channels to lock
* @param flags the lock flags to be passed on to dbLockerAlloc()
*/
explicit DBManyLock(const std::vector<dbCommon*>& channels, unsigned flags = 0) {
pLocker = dbLockerAlloc(channels.data(), channels.size(), flags);
if (!pLocker) {
throw std::invalid_argument("Failed to create locker");
}
}
/**
* When the lock goes out of scope, then free the lock
*/
~DBManyLock() {
if (pLocker) {
dbLockerFree(pLocker);
pLocker = nullptr;
}
}
explicit operator dbLocker*() const {
return pLocker;
}
DBManyLock(DBManyLock&& other) noexcept
:pLocker(other.pLocker) {
other.pLocker = nullptr;
}
DBManyLock& operator=(DBManyLock&& other) noexcept {
if (pLocker) {
dbLockerFree(pLocker);
}
pLocker = other.pLocker;
other.pLocker = nullptr;
return *this;
}
// Prevent copy construction and assignment
DBManyLock(const DBManyLock&) = delete;
DBManyLock& operator=(const DBManyLock& other) = delete;
};
/**
* To lock access to multiple DB records simultaneously.
* Use by creating a new object. It will lock the records locked by the constructor parameter while the object is
* in scope. First you need to create a lock using the DBManyLock().
*
* e.g.
* {
* DBManyLock lock = DBManyLock(channels);
* DBManyLocker F(lock); // Lock all channels
* for ( auto& pDbChannel: channels ) {
* IOCSource::put(pDbChannel, ...);
* }
* ...
* } // Unlocked
*/
class DBManyLocker {
public:
const DBManyLock& lock;
explicit DBManyLocker(DBManyLock& L)
:lock(L) {
dbScanLockMany(lock.pLocker);
}
~DBManyLocker() {
dbScanUnlockMany(lock.pLocker);
}
};
} // pvxs
} // ioc
#endif //PVXS_DBMANYLOCKER_H