new class: Semaphore, smal fixes

master
Denes Matetelki 14 years ago
parent 64efcfd9da
commit a87978afef

1
.gitignore vendored

@ -5,6 +5,7 @@
*.a
*.so
*/a.out
test.out
*/cov
*/lcov.info
*/lcov2.info

@ -29,7 +29,7 @@ inline timespec intIntervalTotimespec(const int & interval)
abs_time.tv_sec += 1;
}
return abs_time;
};
}
#endif // COMMON_HPP

@ -21,7 +21,7 @@ class ConcurrentQueue {
ConcurrentQueue()
: m_cancelled(false)
, m_mutex()
, m_condition(m_mutex)
, m_condVar(m_mutex)
{
TRACE(this);
}
@ -38,7 +38,7 @@ class ConcurrentQueue {
ScopedLock sl(m_mutex);
if (m_cancelled) throw CancelledException();
m_queue.push( task );
m_condition.signal();
m_condVar.signal();
}
@ -61,7 +61,7 @@ class ConcurrentQueue {
ScopedLock sl(m_mutex);
while ( m_queue.empty() and not m_cancelled) {
m_condition.wait();
m_condVar.wait();
}
if (m_cancelled) throw CancelledException();
@ -85,7 +85,7 @@ class ConcurrentQueue {
TRACE(this);
ScopedLock sl(m_mutex);
m_cancelled = true;
m_condition.broadcast();
m_condVar.broadcast();
}
private:
@ -95,8 +95,8 @@ class ConcurrentQueue {
std::queue<T> m_queue;
bool m_cancelled;
Mutex m_mutex;
ConditionVariable m_condition;
mutable Mutex m_mutex;
ConditionVariable m_condVar;
};

@ -0,0 +1,28 @@
#ifndef SEMAPHORE_HPP
#define SEMAPHORE_HPP
#include "Mutex.hpp"
#include "ConditionVariable.hpp"
class Semaphore
{
public:
Semaphore( int maxCount = 1 );
~Semaphore( void );
bool lock( int interval = 0 );
bool unLock( void );
int getCount( void ) const;
private:
int m_maxCount;
int m_count;
mutable Mutex m_mutex;
ConditionVariable m_condVar;
};
#endif // SEMAPHORE_HPP

@ -24,21 +24,25 @@ int ConditionVariable::wait(const int interval)
TRACE(this);
if ( interval == 0 ) {
return pthread_cond_wait( &m_condVar,
m_mutex.getPThreadMutex() );
m_mutex.getPThreadMutex() );
} else {
timespec tspec = intIntervalTotimespec(interval);
TRACE("interval: " << interval << " tspec.tv_sec: " << tspec.tv_sec << " tspec.tv_nsec: " << tspec.tv_nsec );
return pthread_cond_timedwait( &m_condVar,
m_mutex.getPThreadMutex(),
&tspec);
}
}
int ConditionVariable::signal()
{
TRACE(this);
return pthread_cond_signal( &m_condVar );
}
int ConditionVariable::broadcast()
{
TRACE(this);

@ -0,0 +1,54 @@
#include "Semaphore.hpp"
#include "ScopedLock.hpp"
#include "Common.hpp"
Semaphore::Semaphore( int maxCount )
: m_maxCount( maxCount )
, m_count( maxCount )
, m_mutex()
, m_condVar(m_mutex)
{
TRACE(this);
}
Semaphore::~Semaphore( void )
{
TRACE(this);
}
bool Semaphore::lock( int interval )
{
TRACE(this);
ScopedLock sl(m_mutex);
if ( m_count == 0 ) {
if ( m_condVar.wait(interval) != 0 ) {
return false;
}
}
m_count -= 1;
return true;
}
bool Semaphore::unLock( void )
{
TRACE(this);
ScopedLock sc(m_mutex);
if ( m_count == m_maxCount ) {
return false;
}
m_count += 1;
m_condVar.signal();
return true;
}
int Semaphore::getCount( void ) const
{
TRACE(this);
ScopedLock sc(m_mutex);
return m_count;
}

@ -15,6 +15,7 @@ test_ScopedLock.hpp
test_ConditionalVariable.hpp
test_Thread.hpp
test_ThreadPool.hpp
test_Semaphore.hpp
)
target_link_libraries(test CppUtils gcov)
endif()

@ -45,7 +45,7 @@ valgrind \
--malloc-fill=0xaa \
--free-fill=0xdd \
--suppressions=valgrind.supp \
$test | tee $test.out; retval=$PIPESTATUS; (( $retval == 0 ));
$test | tee $test.out; retval=$PIPESTATUS
# retval is 0 on success
# or the number of failed cases

@ -0,0 +1,105 @@
#include <cxxtest/TestSuite.h>
#include "Semaphore.hpp"
#include "Thread.hpp"
#include "Common.hpp"
class TestSemaphore : public CxxTest::TestSuite
{
public:
void testBasic( void )
{
Semaphore s;
TS_ASSERT_EQUALS( s.getCount(), 1 );
TS_ASSERT_EQUALS( s.lock(), true );
TS_ASSERT_EQUALS( s.getCount(), 0 );
TS_ASSERT_EQUALS( s.unLock(), true );
TS_ASSERT_EQUALS( s.getCount(), 1 );
}
private:
class ThreadClassWithSemaphore : public Thread
{
public:
ThreadClassWithSemaphore(Semaphore &semaphore)
: m_semaphore(semaphore)
{
TRACE(this);
}
~ThreadClassWithSemaphore() {
TRACE(this);
}
bool use( int timeout = 0 ) {
TRACE(this);
bool retval = m_semaphore.lock(timeout);
return retval;
}
bool release( void ) {
TRACE(this);
return m_semaphore.unLock();
}
private:
void* run( void ) {
TRACE(this);
while (m_isRunning) {
sleep(1);
}
return 0;
}
Semaphore &m_semaphore;
}; // class ThreadClassWithSemaphore
public:
void testWithTwoThreads( void )
{
Semaphore semaphore(2);
TS_ASSERT_EQUALS( semaphore.getCount(), 2 );
ThreadClassWithSemaphore *t1 = new ThreadClassWithSemaphore(semaphore);
ThreadClassWithSemaphore *t2 = new ThreadClassWithSemaphore(semaphore);
t1->start();
t2->start();
sleep(1);
TS_ASSERT_EQUALS( t1->use(), true );
TS_ASSERT_EQUALS( semaphore.getCount(), 1 );
TS_ASSERT_EQUALS( t1->use(), true );
TS_ASSERT_EQUALS( semaphore.getCount(), 0 );
TS_ASSERT_EQUALS( t1->use(1), false );
TS_ASSERT_EQUALS( t2->use(1), false );
TS_ASSERT_EQUALS( semaphore.getCount(), 0 );
TS_ASSERT_EQUALS( t1->release(), true );
TS_ASSERT_EQUALS( semaphore.getCount(), 1 );
TS_ASSERT_EQUALS( t2->use(1), true );
TS_ASSERT_EQUALS( semaphore.getCount(), 0 );
TS_ASSERT_EQUALS( t2->release(), true );
TS_ASSERT_EQUALS( semaphore.getCount(), 1 );
TS_ASSERT_EQUALS( t2->release(), true );
TS_ASSERT_EQUALS( semaphore.getCount(), 2 );
TS_ASSERT_EQUALS( t2->release(), false );
t1->stop();
t2->stop();
t1->join();
t2->join();
delete t1;
delete t2;
}
};

@ -56,6 +56,7 @@ private:
class ThreadClassWithSignal : public Thread
{
public:
ThreadClassWithSignal() {
@ -75,7 +76,7 @@ private:
/** @note the function will get stopped before it finishes sleeping
* If signal arrives after malloc, it will be a memory leak.
*/
sleep(32);
sleep(665);
void* retVal = malloc(sizeof(int));
*((int*)retVal) = 15;
@ -93,7 +94,9 @@ private:
pthread_exit(retVal);
}
}
};
}; // class ThreadClassWithSignal
public:
@ -101,7 +104,7 @@ public:
{
ThreadClassWithSignal *m2 = new ThreadClassWithSignal;
m2->start();
sleep(3);
sleep(1);
m2->sendSignal(SIGINT);
void *retVal = m2->join();

Loading…
Cancel
Save