commit
9c347897b3
@ -0,0 +1,134 @@
|
||||
#ifndef CONCURRENTQUEUE_HPP
|
||||
#define CONCURRENTQUEUE_HPP
|
||||
|
||||
#include <deque>
|
||||
#include <algorithm>
|
||||
#include <type_traits>
|
||||
|
||||
#include "Mutex.hpp"
|
||||
#include "ConditionVariable.hpp"
|
||||
#include "ScopedLock.hpp"
|
||||
#include "Common.hpp"
|
||||
|
||||
|
||||
|
||||
class CancelledException {};
|
||||
|
||||
|
||||
template <typename T>
|
||||
class ConcurrentDeque
|
||||
{
|
||||
public:
|
||||
|
||||
ConcurrentDeque()
|
||||
: m_queue()
|
||||
, m_cancelled(false)
|
||||
, m_mutex()
|
||||
, m_condVar(m_mutex)
|
||||
{
|
||||
TRACE;
|
||||
}
|
||||
|
||||
~ConcurrentDeque()
|
||||
{
|
||||
TRACE;
|
||||
freeDeque();
|
||||
}
|
||||
|
||||
|
||||
void push(const T value)
|
||||
{
|
||||
TRACE;
|
||||
ScopedLock sl(m_mutex);
|
||||
if (m_cancelled) throw CancelledException();
|
||||
m_queue.push_back( value );
|
||||
m_condVar.signal();
|
||||
}
|
||||
|
||||
|
||||
bool tryPop(T &popped_value)
|
||||
{
|
||||
TRACE;
|
||||
ScopedLock sl(m_mutex);
|
||||
if (m_cancelled) throw CancelledException();
|
||||
if ( m_queue.empty() ) return false;
|
||||
|
||||
popped_value = m_queue.front();
|
||||
m_queue.pop_front();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
T waitAndPop()
|
||||
{
|
||||
TRACE;
|
||||
ScopedLock sl(m_mutex);
|
||||
|
||||
while ( m_queue.empty() and not m_cancelled) {
|
||||
m_condVar.wait();
|
||||
}
|
||||
if (m_cancelled) throw CancelledException();
|
||||
|
||||
T retVal = m_queue.front(); // cctor
|
||||
m_queue.pop_front();
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
||||
bool empty() const
|
||||
{
|
||||
TRACE;
|
||||
ScopedLock sl(m_mutex);
|
||||
if (m_cancelled) throw CancelledException();
|
||||
return m_queue.empty();
|
||||
}
|
||||
|
||||
void cancel()
|
||||
{
|
||||
TRACE;
|
||||
ScopedLock sl(m_mutex);
|
||||
m_cancelled = true;
|
||||
m_condVar.broadcast();
|
||||
freeDeque();
|
||||
}
|
||||
|
||||
template<class U = T>
|
||||
typename std::enable_if< std::is_pointer<U>::value >::type
|
||||
freeDeque()
|
||||
{
|
||||
TRACE;
|
||||
typename std::deque<T>::iterator it;
|
||||
for ( it = m_queue.begin(); it != m_queue.end(); ++it )
|
||||
delete *it;
|
||||
|
||||
m_queue.clear();
|
||||
}
|
||||
|
||||
template<class U = T>
|
||||
typename std::enable_if< !(std::is_pointer<U>::value) >::type
|
||||
freeDeque()
|
||||
{
|
||||
TRACE;
|
||||
m_queue.clear();
|
||||
}
|
||||
|
||||
bool cancelled()
|
||||
{
|
||||
TRACE;
|
||||
return m_cancelled;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
|
||||
ConcurrentDeque& operator=( const ConcurrentDeque& );
|
||||
ConcurrentDeque( const ConcurrentDeque& );
|
||||
|
||||
std::deque<T> m_queue;
|
||||
bool m_cancelled;
|
||||
mutable Mutex m_mutex;
|
||||
ConditionVariable m_condVar;
|
||||
|
||||
};
|
||||
|
||||
#endif // CONCURRENTQUEUE_HPP
|
@ -1,105 +0,0 @@
|
||||
#ifndef CONCURRENTQUEUE_HPP
|
||||
#define CONCURRENTQUEUE_HPP
|
||||
|
||||
#include <queue>
|
||||
|
||||
#include "Mutex.hpp"
|
||||
#include "ConditionVariable.hpp"
|
||||
#include "ScopedLock.hpp"
|
||||
#include "Common.hpp"
|
||||
|
||||
|
||||
|
||||
class CancelledException {};
|
||||
|
||||
|
||||
template <typename T>
|
||||
class ConcurrentQueue {
|
||||
|
||||
public:
|
||||
|
||||
|
||||
ConcurrentQueue()
|
||||
: m_queue()
|
||||
, m_cancelled(false)
|
||||
, m_mutex()
|
||||
, m_condVar(m_mutex)
|
||||
{
|
||||
TRACE;
|
||||
}
|
||||
|
||||
~ConcurrentQueue()
|
||||
{
|
||||
TRACE;
|
||||
}
|
||||
|
||||
|
||||
void push(const T task)
|
||||
{
|
||||
TRACE;
|
||||
ScopedLock sl(m_mutex);
|
||||
if (m_cancelled) throw CancelledException();
|
||||
m_queue.push( task );
|
||||
m_condVar.signal();
|
||||
}
|
||||
|
||||
|
||||
bool tryPop(T &popped_value)
|
||||
{
|
||||
TRACE;
|
||||
ScopedLock sl(m_mutex);
|
||||
if (m_cancelled) throw CancelledException();
|
||||
if ( m_queue.empty() ) return false;
|
||||
|
||||
popped_value = m_queue.front();
|
||||
m_queue.pop();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
T waitAndPop()
|
||||
{
|
||||
TRACE;
|
||||
ScopedLock sl(m_mutex);
|
||||
|
||||
while ( m_queue.empty() and not m_cancelled) {
|
||||
m_condVar.wait();
|
||||
}
|
||||
if (m_cancelled) throw CancelledException();
|
||||
|
||||
T retVal = m_queue.front(); // cctor
|
||||
m_queue.pop();
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
||||
bool empty() const
|
||||
{
|
||||
TRACE;
|
||||
ScopedLock sl(m_mutex);
|
||||
if (m_cancelled) throw CancelledException();
|
||||
return m_queue.empty();
|
||||
}
|
||||
|
||||
|
||||
void cancel()
|
||||
{
|
||||
TRACE;
|
||||
ScopedLock sl(m_mutex);
|
||||
m_cancelled = true;
|
||||
m_condVar.broadcast();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
ConcurrentQueue& operator=( const ConcurrentQueue& );
|
||||
ConcurrentQueue( const ConcurrentQueue& );
|
||||
|
||||
std::queue<T> m_queue;
|
||||
bool m_cancelled;
|
||||
mutable Mutex m_mutex;
|
||||
ConditionVariable m_condVar;
|
||||
|
||||
};
|
||||
|
||||
#endif // CONCURRENTQUEUE_HPP
|
@ -0,0 +1,35 @@
|
||||
#ifndef MYSQL_CONNECTION_POOL_HPP
|
||||
#define MYSQL_CONNECTION_POOL_HPP
|
||||
|
||||
#include "ObjectPool.hpp"
|
||||
#include "MysqlClient.hpp"
|
||||
|
||||
|
||||
class MysqlConnectionPool : public ObjectPool<MysqlClient *>
|
||||
{
|
||||
public:
|
||||
|
||||
MysqlConnectionPool( const char *host = NULL,
|
||||
const char *user = NULL,
|
||||
const char *passwd = NULL,
|
||||
const char *db = NULL );
|
||||
~MysqlConnectionPool();
|
||||
|
||||
void create();
|
||||
|
||||
void clear();
|
||||
|
||||
private:
|
||||
|
||||
MysqlConnectionPool(const MysqlConnectionPool&);
|
||||
MysqlConnectionPool& operator=(const MysqlConnectionPool&);
|
||||
|
||||
const char *m_host;
|
||||
const char *m_user;
|
||||
const char *m_passwd;
|
||||
const char *m_db;
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif // MYSQL_CONNECTION_POOL_HPP
|
@ -0,0 +1,81 @@
|
||||
#ifndef OBJECT_POOL_HPP
|
||||
#define OBJECT_POOL_HPP
|
||||
|
||||
#include "ConcurrentDeque.hpp"
|
||||
#include "Logger.hpp"
|
||||
|
||||
template <typename T>
|
||||
class ObjectPool
|
||||
{
|
||||
public:
|
||||
|
||||
ObjectPool()
|
||||
: m_pool()
|
||||
, m_numberOfUsedObjects(0)
|
||||
{
|
||||
TRACE;
|
||||
}
|
||||
|
||||
virtual ~ObjectPool()
|
||||
{
|
||||
TRACE;
|
||||
}
|
||||
|
||||
void add(const T object) // throws CancelledException
|
||||
{
|
||||
TRACE;
|
||||
m_pool.push(object);
|
||||
}
|
||||
|
||||
|
||||
T acquire() // throws CancelledException
|
||||
{
|
||||
TRACE;
|
||||
T tmp = m_pool.waitAndPop();
|
||||
m_numberOfUsedObjects++;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
template<class U = T>
|
||||
typename std::enable_if< std::is_pointer<U>::value >::type
|
||||
release(T object)
|
||||
{
|
||||
TRACE;
|
||||
if ( m_pool.cancelled() ) {
|
||||
m_numberOfUsedObjects--;
|
||||
delete object;
|
||||
return;
|
||||
}
|
||||
|
||||
m_pool.push(object);
|
||||
m_numberOfUsedObjects--;
|
||||
}
|
||||
|
||||
template<class U = T>
|
||||
typename std::enable_if< !(std::is_pointer<U>::value) >::type
|
||||
release(T object)
|
||||
{
|
||||
TRACE;
|
||||
if ( m_pool.cancelled() ) {
|
||||
m_numberOfUsedObjects--;
|
||||
return;
|
||||
}
|
||||
|
||||
m_pool.push(object);
|
||||
m_numberOfUsedObjects--;
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
TRACE;
|
||||
m_pool.cancel();
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
|
||||
ConcurrentDeque<T> m_pool;
|
||||
int m_numberOfUsedObjects;
|
||||
};
|
||||
|
||||
#endif // OBJECT_POOL_HPP
|
@ -0,0 +1,31 @@
|
||||
#include "MysqlConnectionPool.hpp"
|
||||
|
||||
#include "Logger.hpp"
|
||||
|
||||
|
||||
MysqlConnectionPool::MysqlConnectionPool( const char *host,
|
||||
const char *user,
|
||||
const char *passwd,
|
||||
const char *db )
|
||||
: m_host(host)
|
||||
, m_user(user)
|
||||
, m_passwd(passwd)
|
||||
, m_db(db)
|
||||
{
|
||||
TRACE;
|
||||
}
|
||||
|
||||
MysqlConnectionPool::~MysqlConnectionPool()
|
||||
{
|
||||
TRACE;
|
||||
}
|
||||
|
||||
|
||||
void MysqlConnectionPool::create()
|
||||
{
|
||||
TRACE;
|
||||
|
||||
MysqlClient *client = new MysqlClient ( m_host, m_user, m_passwd, m_db );
|
||||
client->connect();
|
||||
add(client);
|
||||
}
|
@ -0,0 +1,134 @@
|
||||
#include <cxxtest/TestSuite.h>
|
||||
|
||||
#include "Common.hpp"
|
||||
#include "Fixture.hpp"
|
||||
|
||||
#include "ObjectPool.hpp"
|
||||
#include "Thread.hpp"
|
||||
|
||||
class TestObjectPool : public CxxTest::TestSuite
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
void testBasic( void )
|
||||
{
|
||||
TEST_HEADER;
|
||||
|
||||
ObjectPool<int> op;
|
||||
|
||||
int a(1);
|
||||
op.add(a);
|
||||
|
||||
TS_ASSERT_EQUALS( op.acquire(), a );
|
||||
}
|
||||
|
||||
void testPointers( void )
|
||||
{
|
||||
TEST_HEADER;
|
||||
|
||||
ObjectPool<int*> op;
|
||||
|
||||
int *a = new int(1);
|
||||
int *b = new int(2);
|
||||
op.add(a);
|
||||
op.add(b);
|
||||
|
||||
int *tmp_a = op.acquire();
|
||||
int *tmp_b = op.acquire();
|
||||
|
||||
TS_ASSERT_EQUALS( *tmp_a, *a );
|
||||
TS_ASSERT_EQUALS( *tmp_b, *b );
|
||||
|
||||
// release will delete them
|
||||
op.release(tmp_a);
|
||||
op.release(tmp_b);
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
|
||||
class ObjecPoolUserThread : public Thread
|
||||
{
|
||||
public:
|
||||
ObjecPoolUserThread( ObjectPool<int*> &objectPool
|
||||
)
|
||||
: m_objectPool(objectPool)
|
||||
{
|
||||
TRACE;
|
||||
}
|
||||
|
||||
private:
|
||||
void* run()
|
||||
{
|
||||
TRACE;
|
||||
int *a;
|
||||
try {
|
||||
a = m_objectPool.acquire();
|
||||
LOG( Logger::DEBUG, std::string("Acquired int: ").
|
||||
append(TToStr(*a)).c_str() );
|
||||
} catch ( CancelledException ex ) {
|
||||
LOG( Logger::DEBUG, "Cancelled while acquiring" );
|
||||
}
|
||||
|
||||
sleep(1);
|
||||
|
||||
try {
|
||||
m_objectPool.release(a);
|
||||
} catch ( CancelledException ex ) {
|
||||
LOG( Logger::DEBUG, "Cancelled while releasing" );
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
ObjectPool<int*> &m_objectPool;
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
void testCompetingThreads( void )
|
||||
{
|
||||
TEST_HEADER;
|
||||
|
||||
ObjectPool<int*> op;
|
||||
|
||||
ObjecPoolUserThread t1(op);
|
||||
ObjecPoolUserThread t2(op);
|
||||
|
||||
int *a = new int(27);
|
||||
op.add(a);
|
||||
|
||||
t1.start();
|
||||
t2.start();
|
||||
|
||||
t1.join();
|
||||
t2.join();
|
||||
|
||||
// no need to delete "a", dtor of the ConqurrentDeque takes care of it
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
|
||||
void testCleanUp( void )
|
||||
{
|
||||
TEST_HEADER;
|
||||
|
||||
ObjectPool<int*> cop;
|
||||
int *a = new int(12);
|
||||
int *b = new int(13);
|
||||
int *c = new int(14);
|
||||
cop.add(a);
|
||||
cop.add(b);
|
||||
cop.add(c);
|
||||
|
||||
// ObjecPoolUserThread t1(cop);
|
||||
// ObjecPoolUserThread t2(cop);
|
||||
|
||||
// t1.start();
|
||||
// t2.start();
|
||||
|
||||
cop.clear();
|
||||
}
|
||||
|
||||
};
|
@ -1,35 +0,0 @@
|
||||
#include <cxxtest/TestSuite.h>
|
||||
|
||||
#define private public // need to reach private variables
|
||||
|
||||
#include "Common.hpp"
|
||||
#include "Fixture.hpp"
|
||||
#include "Mutex.hpp"
|
||||
|
||||
class TestPThreadWrappers : public CxxTest::TestSuite
|
||||
{
|
||||
|
||||
|
||||
public:
|
||||
|
||||
void testMutexBasic( void )
|
||||
{
|
||||
TEST_HEADER;
|
||||
Mutex m;
|
||||
m.lock();
|
||||
TS_ASSERT_EQUALS ( m.tryLock(0), 0 );
|
||||
m.unlock();
|
||||
}
|
||||
|
||||
void testMutexCreate( void )
|
||||
{
|
||||
TEST_HEADER;
|
||||
Mutex m(PTHREAD_MUTEX_ERRORCHECK);
|
||||
m.lock();
|
||||
TS_ASSERT_EQUALS ( m.lock(), 1 );
|
||||
|
||||
m.unlock();
|
||||
}
|
||||
|
||||
|
||||
};
|
@ -1,35 +0,0 @@
|
||||
#include <cxxtest/TestSuite.h>
|
||||
|
||||
#define private public // need to reach Singleton's private m_instance
|
||||
|
||||
#include "Common.hpp"
|
||||
#include "Fixture.hpp"
|
||||
#include "Singleton_DCLP.hpp"
|
||||
|
||||
|
||||
class TestSingletonDCLPSuite : public CxxTest::TestSuite
|
||||
{
|
||||
|
||||
private:
|
||||
|
||||
class BasicSingleton : public Singleton_DCLP<BasicSingleton>
|
||||
{
|
||||
public:
|
||||
int getSeven()
|
||||
{
|
||||
TRACE;
|
||||
return 7;
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
void testBasic( void )
|
||||
{
|
||||
TEST_HEADER;
|
||||
|
||||
TS_ASSERT_EQUALS( BasicSingleton::getInstance()->getSeven(), 7 );
|
||||
}
|
||||
|
||||
|
||||
};
|
Loading…
Reference in new issue