rework rwlock

This commit is contained in:
Michael Davidsaver
2019-11-09 11:47:20 -08:00
parent 12598c8679
commit 495eeaa4ac
3 changed files with 70 additions and 43 deletions
+5 -5
View File
@@ -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
View File
@@ -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
View File
@@ -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();