rework rwlock
This commit is contained in:
+5
-5
@@ -117,7 +117,7 @@ Server& Server::addSource(const std::string& name,
|
||||
if(!src)
|
||||
throw std::logic_error(SB()<<"Attempt to add NULL Source "<<name<<" at "<<order);
|
||||
{
|
||||
epicsGuard<RWLock::Writer> G(pvt->sourcesLock.writer());
|
||||
auto G(pvt->sourcesLock.lockWriter());
|
||||
|
||||
auto& ent = pvt->sources[std::make_pair(order, name)];
|
||||
if(ent)
|
||||
@@ -132,7 +132,7 @@ std::shared_ptr<Source> Server::removeSource(const std::string& name, int order
|
||||
if(!pvt)
|
||||
throw std::logic_error("NULL Server");
|
||||
|
||||
epicsGuard<RWLock::Writer> G(pvt->sourcesLock.writer());
|
||||
auto G(pvt->sourcesLock.lockWriter());
|
||||
|
||||
std::shared_ptr<Source> ret;
|
||||
auto it = pvt->sources.find(std::make_pair(order, name));
|
||||
@@ -149,7 +149,7 @@ std::shared_ptr<Source> Server::getSource(const std::string& name, int order)
|
||||
if(!pvt)
|
||||
throw std::logic_error("NULL Server");
|
||||
|
||||
epicsGuard<RWLock::Reader> G(pvt->sourcesLock.reader());
|
||||
auto G(pvt->sourcesLock.lockReader());
|
||||
|
||||
std::shared_ptr<Source> ret;
|
||||
auto it = pvt->sources.find(std::make_pair(order, name));
|
||||
@@ -167,7 +167,7 @@ void Server::listSource(std::vector<std::pair<std::string, int> > &names)
|
||||
|
||||
names.clear();
|
||||
|
||||
epicsGuard<RWLock::Reader> G(pvt->sourcesLock.reader());
|
||||
auto G(pvt->sourcesLock.lockReader());
|
||||
|
||||
names.reserve(pvt->sources.size());
|
||||
|
||||
@@ -475,7 +475,7 @@ void Server::Pvt::onSearch(const UDPManager::Search& msg)
|
||||
}
|
||||
|
||||
{
|
||||
epicsGuard<RWLock::Reader> G(sourcesLock.reader());
|
||||
auto G(sourcesLock.lockReader());
|
||||
for(const auto& pair : sources) {
|
||||
try {
|
||||
pair.second->onSearch(searchOp);
|
||||
|
||||
+16
-2
@@ -177,11 +177,10 @@ void ServerConn::handle_Search()
|
||||
void ServerConn::handle_CreateChan()
|
||||
{
|
||||
const bool be = EPICS_BYTE_ORDER==EPICS_ENDIAN_BIG;
|
||||
(void)evbuffer_drain(txBody.get(), evbuffer_get_length(txBody.get()));
|
||||
|
||||
EvInBuf M(peerBE, segBuf.get(), 16);
|
||||
|
||||
epicsGuard<RWLock::Reader> G(iface->server->sourcesLock.reader()); // could move this into loop, only guards server->sources
|
||||
auto G(iface->server->sourcesLock.lockReader());
|
||||
|
||||
uint16_t count = 0;
|
||||
from_wire(M, count);
|
||||
@@ -253,6 +252,8 @@ void ServerConn::handle_CreateChan()
|
||||
sts.trace = "pvx:serv:nosource:";
|
||||
}
|
||||
|
||||
(void)evbuffer_drain(txBody.get(), evbuffer_get_length(txBody.get()));
|
||||
|
||||
EvOutBuf R(be, txBody.get());
|
||||
to_wire(R, cid);
|
||||
to_wire(R, sid);
|
||||
@@ -304,10 +305,23 @@ void ServerConn::handle_DestroyChan()
|
||||
chanBySID.erase(it);
|
||||
// ServerChannel is delete'd
|
||||
|
||||
{
|
||||
auto tx = bufferevent_get_output(bev.get());
|
||||
constexpr bool be = EPICS_BYTE_ORDER==EPICS_ENDIAN_BIG;
|
||||
EvOutBuf R(be, tx);
|
||||
to_wire(R, Header{pva_app_msg::DestroyChan, pva_flags::Server, 8});
|
||||
// yes, CID and SID really are reversed from from the Request
|
||||
to_wire(R, cid);
|
||||
to_wire(R, sid);
|
||||
}
|
||||
|
||||
} else {
|
||||
log_printf(connsetup, PLVL_DEBUG, "Client %s DestroyChan non-existant sid=%d cid=%d\n", peerName.c_str(),
|
||||
unsigned(sid), unsigned(cid));
|
||||
}
|
||||
|
||||
if(!M.good())
|
||||
bev.reset();
|
||||
}
|
||||
|
||||
void ServerConn::handle_GetOp()
|
||||
|
||||
+49
-36
@@ -13,6 +13,7 @@
|
||||
# include <pthread.h>
|
||||
#endif
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
|
||||
@@ -58,7 +59,12 @@ template <typename I>
|
||||
struct Range {
|
||||
I a, b;
|
||||
|
||||
struct iterator : std::iterator_traits<std::forward_iterator_tag> {
|
||||
struct iterator {
|
||||
typedef std::forward_iterator_tag iterator_category;
|
||||
typedef I value_type;
|
||||
typedef ptrdiff_t difference_type;
|
||||
typedef I* pointer;
|
||||
typedef I& reference;
|
||||
I val;
|
||||
explicit constexpr iterator(I val) :val(val) {}
|
||||
EPICS_ALWAYS_INLINE I operator*() const { return val; }
|
||||
@@ -81,53 +87,60 @@ constexpr detail::Range<I> range(I end) { return detail::Range<I>{I(0), end}; }
|
||||
template<typename I>
|
||||
constexpr detail::Range<I> range(I begin, I end) { return detail::Range<I>{begin, end}; }
|
||||
|
||||
#ifdef _WIN32
|
||||
# define RWLOCK_TYPE SRWLOCK
|
||||
# define RWLOCK_INIT(PLOCK) InitializeSRWLock(PLOCK)
|
||||
# define RWLOCK_DTOR(PLOCK) do{(void)(PLOCK);}while(0)
|
||||
# define RWLOCK_WLOCK(PLOCK) AcquireSRWLockExclusive(PLOCK)
|
||||
# define RWLOCK_WUNLOCK(PLOCK) ReleaseSRWLockExclusive(PLOCK)
|
||||
# define RWLOCK_RLOCK(PLOCK) AcquireSRWLockShared(PLOCK)
|
||||
# define RWLOCK_RUNLOCK(PLOCK) ReleaseSRWLockShared(PLOCK)
|
||||
#else
|
||||
# define RWLOCK_TYPE pthread_rwlock_t
|
||||
# define RWLOCK_INIT(PLOCK) pthread_rwlock_init(PLOCK, nullptr)
|
||||
# define RWLOCK_DTOR(PLOCK) pthread_rwlock_destroy(PLOCK)
|
||||
# define RWLOCK_WLOCK(PLOCK) pthread_rwlock_wrlock(PLOCK)
|
||||
# define RWLOCK_WUNLOCK(PLOCK) pthread_rwlock_unlock(PLOCK)
|
||||
# define RWLOCK_RLOCK(PLOCK) pthread_rwlock_rdlock(PLOCK)
|
||||
# define RWLOCK_RUNLOCK(PLOCK) pthread_rwlock_unlock(PLOCK)
|
||||
#endif
|
||||
|
||||
class RWLock
|
||||
{
|
||||
#ifdef _WIN32
|
||||
SRWLOCK lock;
|
||||
RWLOCK_TYPE lock;
|
||||
public:
|
||||
inline RWLock() :_reader(*this), _writer(*this) { InitializeSRWLock(&lock); }
|
||||
#else
|
||||
pthread_rwlock_t lock;
|
||||
public:
|
||||
inline RWLock() :_reader(*this), _writer(*this) { pthread_rwlock_init(&lock, nullptr); }
|
||||
inline ~RWLock() { pthread_rwlock_destroy(&lock); }
|
||||
#endif
|
||||
inline RWLock() { RWLOCK_INIT(&lock); }
|
||||
inline ~RWLock() { RWLOCK_DTOR(&lock); }
|
||||
|
||||
RWLock(const RWLock&) = delete;
|
||||
RWLock(RWLock&&) = delete;
|
||||
RWLock& operator=(const RWLock&) = delete;
|
||||
RWLock& operator=(RWLock&&) = delete;
|
||||
|
||||
class Reader {
|
||||
RWLock& rw;
|
||||
public:
|
||||
Reader(RWLock& rw) : rw(rw) {}
|
||||
#ifdef _WIN32
|
||||
inline void lock() { AcquireSRWLockShared(&rw.lock); }
|
||||
inline void unlock() { ReleaseSRWLockShared(&rw.lock); }
|
||||
#else
|
||||
inline void lock() { pthread_rwlock_rdlock(&rw.lock); }
|
||||
inline void unlock() { pthread_rwlock_unlock(&rw.lock); }
|
||||
#endif
|
||||
} _reader;
|
||||
inline Reader& reader() { return _reader; }
|
||||
struct UnlockReader {
|
||||
inline void operator()(RWLock *plock) { RWLOCK_RUNLOCK(&plock->lock); }
|
||||
};
|
||||
inline std::unique_ptr<RWLock, UnlockReader> lockReader() {
|
||||
RWLOCK_RLOCK(&lock);
|
||||
return std::unique_ptr<RWLock, UnlockReader>{this};
|
||||
}
|
||||
|
||||
class Writer {
|
||||
RWLock& rw;
|
||||
public:
|
||||
Writer(RWLock& rw) : rw(rw) {}
|
||||
#ifdef _WIN32
|
||||
inline void lock() { AcquireSRWLockExclusive(&rw.lock); }
|
||||
inline void unlock() { ReleaseSRWLockExclusive(&rw.lock); }
|
||||
#else
|
||||
inline void lock() { pthread_rwlock_wrlock(&rw.lock); }
|
||||
inline void unlock() { pthread_rwlock_unlock(&rw.lock); }
|
||||
#endif
|
||||
} _writer;
|
||||
inline Writer& writer() { return _writer; }
|
||||
struct UnlockWriter {
|
||||
inline void operator()(RWLock *plock) { RWLOCK_WUNLOCK(&plock->lock); }
|
||||
};
|
||||
inline std::unique_ptr<RWLock, UnlockWriter> lockWriter() {
|
||||
RWLOCK_WLOCK(&lock);
|
||||
return std::unique_ptr<RWLock, UnlockWriter>{this};
|
||||
}
|
||||
};
|
||||
|
||||
#undef RWLOCK_TYPE
|
||||
#undef RWLOCK_INIT
|
||||
#undef RWLOCK_DTOR
|
||||
#undef RWLOCK_WLOCK
|
||||
#undef RWLOCK_WUNLOCK
|
||||
#undef RWLOCK_RLOCK
|
||||
#undef RWLOCK_RUNLOCK
|
||||
|
||||
void logger_shutdown();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user