AtomicBoolean for _closed flag
This commit is contained in:
@@ -39,29 +39,6 @@ using epics::pvData::int64;
|
||||
namespace epics {
|
||||
namespace pvAccess {
|
||||
|
||||
struct null_deleter
|
||||
{
|
||||
void operator()(void const *) const {}
|
||||
};
|
||||
|
||||
// standard performance on set/clear, use of tr1::shared_ptr lock-free counter for get
|
||||
// alternative is to use boost::atomic
|
||||
class AtomicBoolean
|
||||
{
|
||||
public:
|
||||
AtomicBoolean() : counter(static_cast<void*>(0), null_deleter()) {};
|
||||
|
||||
void set() { mutex.lock(); setp = counter; mutex.unlock(); }
|
||||
void clear() { mutex.lock(); setp.reset(); mutex.unlock(); }
|
||||
|
||||
bool get() const { return counter.use_count() == 2; }
|
||||
private:
|
||||
std::tr1::shared_ptr<void> counter;
|
||||
std::tr1::shared_ptr<void> setp;
|
||||
epics::pvData::Mutex mutex;
|
||||
};
|
||||
|
||||
|
||||
//class MonitorSender;
|
||||
|
||||
enum ReceiveStage {
|
||||
|
||||
@@ -54,8 +54,7 @@ namespace epics {
|
||||
virtual ~BlockingUDPTransport();
|
||||
|
||||
virtual bool isClosed() {
|
||||
epics::pvData::Lock guard(_mutex);
|
||||
return _closed;
|
||||
return _closed.get();
|
||||
}
|
||||
|
||||
virtual const osiSockAddr* getRemoteAddress() const {
|
||||
@@ -210,7 +209,7 @@ namespace epics {
|
||||
}
|
||||
|
||||
protected:
|
||||
bool _closed;
|
||||
AtomicBoolean _closed;
|
||||
|
||||
/**
|
||||
* Response handler.
|
||||
|
||||
@@ -44,7 +44,7 @@ namespace epics {
|
||||
auto_ptr<ResponseHandler>& responseHandler, SOCKET channel,
|
||||
osiSockAddr& bindAddress,
|
||||
short remoteTransportRevision) :
|
||||
_closed(false),
|
||||
_closed(),
|
||||
_responseHandler(responseHandler),
|
||||
_channel(channel),
|
||||
_bindAddress(bindAddress),
|
||||
@@ -108,8 +108,8 @@ namespace epics {
|
||||
void BlockingUDPTransport::close(bool forced, bool waitForThreadToComplete) {
|
||||
{
|
||||
Lock guard(_mutex);
|
||||
if(_closed) return;
|
||||
_closed = true;
|
||||
if(_closed.get()) return;
|
||||
_closed.set();
|
||||
|
||||
LOG(logLevelDebug,
|
||||
"UDP socket %s closed.",
|
||||
@@ -178,14 +178,8 @@ namespace epics {
|
||||
|
||||
try {
|
||||
|
||||
while(true)
|
||||
while(!_closed.get())
|
||||
{
|
||||
_mutex.lock();
|
||||
bool closed = _closed;
|
||||
_mutex.unlock();
|
||||
if (unlikely(closed))
|
||||
break;
|
||||
|
||||
// we poll to prevent blocking indefinitely
|
||||
|
||||
// data ready to be read
|
||||
@@ -237,10 +231,7 @@ namespace epics {
|
||||
continue;
|
||||
|
||||
// log a 'recvfrom' error
|
||||
_mutex.lock();
|
||||
closed = _closed;
|
||||
_mutex.unlock();
|
||||
if(!closed)
|
||||
if(!_closed.get())
|
||||
{
|
||||
char errStr[64];
|
||||
epicsSocketConvertErrnoToString(errStr, sizeof(errStr));
|
||||
|
||||
@@ -596,6 +596,28 @@ namespace epics {
|
||||
};
|
||||
|
||||
|
||||
struct AtomicBoolean_null_deleter
|
||||
{
|
||||
void operator()(void const *) const {}
|
||||
};
|
||||
|
||||
// standard performance on set/clear, use of tr1::shared_ptr lock-free counter for get
|
||||
// alternative is to use boost::atomic
|
||||
class AtomicBoolean
|
||||
{
|
||||
public:
|
||||
AtomicBoolean() : counter(static_cast<void*>(0), AtomicBoolean_null_deleter()) {};
|
||||
|
||||
void set() { mutex.lock(); setp = counter; mutex.unlock(); }
|
||||
void clear() { mutex.lock(); setp.reset(); mutex.unlock(); }
|
||||
|
||||
bool get() const { return counter.use_count() == 2; }
|
||||
private:
|
||||
std::tr1::shared_ptr<void> counter;
|
||||
std::tr1::shared_ptr<void> setp;
|
||||
epics::pvData::Mutex mutex;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ PROD_HOST += testUtils
|
||||
testUtils_SRCS += hexDumpTest.cpp
|
||||
testUtils_SRCS += wildcharMatcherTest.cpp
|
||||
testUtils_SRCS += inetAddressUtilsTest.cpp
|
||||
testUtils_SRCS += atomicBooleanTest.cpp
|
||||
testUtils_LIBS += pvAccess pvData Com gtest_main
|
||||
endif
|
||||
|
||||
|
||||
16
testApp/utils/atomicBooleanTest.cpp
Normal file
16
testApp/utils/atomicBooleanTest.cpp
Normal file
@@ -0,0 +1,16 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <remote.h>
|
||||
|
||||
using namespace epics::pvAccess;
|
||||
|
||||
TEST(atomicBooleanTest, atomicBoolean)
|
||||
{
|
||||
AtomicBoolean ab;
|
||||
|
||||
EXPECT_FALSE(ab.get());
|
||||
ab.set();
|
||||
EXPECT_TRUE(ab.get());
|
||||
ab.clear();
|
||||
EXPECT_FALSE(ab.get());
|
||||
}
|
||||
Reference in New Issue
Block a user