AtomicBoolean for _closed flag

This commit is contained in:
Matej Sekoranja
2011-10-06 20:40:33 +02:00
parent 6a51e31a30
commit 0eb299b843
6 changed files with 46 additions and 40 deletions

View File

@@ -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 {

View File

@@ -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.

View File

@@ -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));

View File

@@ -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;
};
}
}

View File

@@ -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

View 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());
}