diff --git a/include/Multiton.hpp b/include/Multiton.hpp new file mode 100644 index 0000000..5c680d1 --- /dev/null +++ b/include/Multiton.hpp @@ -0,0 +1,69 @@ +#ifndef MULTITON_H +#define MULTITON_H + +#include + +// http://stackoverflow.com/questions/2346091/c-templated-class-implementation-of-the-multiton-pattern + +/// @note Not thread-safe! Use some concurrent map! + +template class Multiton +{ +public: + + static T& getRef( const Key& key ) + { + return *getPtr(key); + } + + static T* getPtr( const Key& key ) + { + typename std::map::const_iterator it = m_instances.find(key); + + if ( it != m_instances.end() ) { + return (T*)(it->second); + } + + T* instance = new T; + m_instances[key] = instance; + return instance; + } + + static bool remove( const Key& key ) + { + typename std::map::const_iterator it = m_instances.find(key); + + if ( it == m_instances.end() ) { + return false; + } + + delete (*it).second; + m_instances.remove(it); + return true; + } + + static void destroy() + { + typename std::map::const_iterator it; + for ( it = m_instances.begin(); it != m_instances.end(); ++it ) { + delete (*it).second; + } + m_instances.clear(); + } + +protected: + + Multiton() {} + + virtual ~Multiton() {} + +private: + Multiton(const Multiton&) {} + Multiton& operator= (const Multiton&) { return *this; } + + static std::map m_instances; +}; + +template std::map Multiton::m_instances; + +#endif // MULTITON_H diff --git a/include/Singleton.hpp b/include/Singleton.hpp index 5d5b9b3..8b376af 100644 --- a/include/Singleton.hpp +++ b/include/Singleton.hpp @@ -1,9 +1,6 @@ #ifndef SINGLETON_HPP #define SINGLETON_HPP -#include "Common.hpp" -#include "Logger.hpp" - template class Singleton diff --git a/include/Singleton_DCLP.hpp b/include/Singleton_DCLP.hpp new file mode 100644 index 0000000..07ead7f --- /dev/null +++ b/include/Singleton_DCLP.hpp @@ -0,0 +1,53 @@ +#ifndef SINGLETON_DCLP_HPP +#define SINGLETON_DCLP_HPP + +#include + + +template +class Singleton_DCLP +{ +protected: + + Singleton_DCLP() {}; + virtual ~Singleton_DCLP() {}; + +private: + + Singleton_DCLP( const Singleton_DCLP& ); + Singleton_DCLP& operator=( const Singleton_DCLP& ); + +public: + + static T* getInstance() + { + if ( not m_instance ) + { + std::lock_guard guard(m_lock); + + // this is now the critical section + + if ( not m_instance ) // re-check pinstance + { + // Douglas Schmidt proposed volatile + // to prevent "agressive optimalizations" + volatile T *temp = new T(); + m_instance = (T*)temp; + } + } + + return m_instance; + } + + +private: + + static std::mutex m_lock; + static T* m_instance; +}; + +template std::mutex Singleton_DCLP::m_lock; +template T* Singleton_DCLP::m_instance = 0; + + +#endif // SINGLETON_DCLP_HPP diff --git a/include/Singleton_call_once.hpp b/include/Singleton_call_once.hpp new file mode 100644 index 0000000..117a913 --- /dev/null +++ b/include/Singleton_call_once.hpp @@ -0,0 +1,41 @@ +#ifndef SINGLETON_CALL_ONCE_HPP +#define SINGLETON_CALL_ONCE_HPP + +#include + +template +class Singleton_call_once +{ +protected: + + Singleton_call_once() {}; + virtual ~Singleton_call_once() {}; + +private: + + Singleton_call_once( const Singleton_call_once& ); + Singleton_call_once& operator=( const Singleton_call_once& ); + +public: + + static T* getInstance() + { + std::call_once(m_flag, &Singleton_call_once::do_init); + return m_instance; + } + +private: + + static void do_init() + { + m_instance = new T(); + } + + static T* m_instance; + static std::once_flag m_flag; +}; + +template T* Singleton_call_once::m_instance = 0; +template std::once_flag Singleton_call_once::m_flag; + +#endif // SINGLETON_CALL_ONCE_HPP diff --git a/include/Singleton_meyers.hpp b/include/Singleton_meyers.hpp new file mode 100644 index 0000000..f065dbe --- /dev/null +++ b/include/Singleton_meyers.hpp @@ -0,0 +1,28 @@ +#ifndef SINGLETON_MEYERS_HPP +#define SINGLETON_MEYERS_HPP + +template +class Singleton_meyers +{ +protected: + + Singleton_meyers() {}; + virtual ~Singleton_meyers() {}; + +private: + + Singleton_meyers( const Singleton_meyers& ); + Singleton_meyers& operator=( const Singleton_meyers& ); + +public: + + inline static T* getInstance() + { + /// @note static local initialization is thread safe in c++011 + static T instance; + return &instance; + } +}; + + +#endif // SINGLETON_MEYERS_HPP diff --git a/src/Logger.cpp b/src/Logger.cpp index 437e768..23b805f 100644 --- a/src/Logger.cpp +++ b/src/Logger.cpp @@ -3,6 +3,8 @@ #include //time #include "Colors.hpp" +#include "Common.hpp" + void Logger::init(std::ostream& log_stream ) { diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 8aaa7d8..541227c 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,5 +1,5 @@ set (CXX_FLAGS "-Wall -Wextra -pedantic -Weffc++ -Wshadow " - "-ggdb -fprofile-arcs -ftest-coverage " ) + "-ggdb -fprofile-arcs -ftest-coverage --std=c++0x " ) add_definitions( ${CXX_FLAGS} ) # add_definitions( -DNO_TRACE ) @@ -16,15 +16,18 @@ if(CXXTEST_FOUND) generated_main.cpp Fixture.hpp - test_Singelton.hpp - test_Mutex.hpp - test_ScopedLock.hpp - test_ConditionalVariable.hpp - test_Thread.hpp - test_ThreadPool.hpp - test_Semaphore.hpp - test_Timer.hpp - test_Common.hpp + test_Singelton_call_once.hpp +# test_Singleton.hpp +# test_Singleton_meyers.hpp +# test_Singleton_DCLP.hpp +# test_Mutex.hpp +# test_ScopedLock.hpp +# test_ConditionalVariable.hpp +# test_Thread.hpp +# test_ThreadPool.hpp +# test_Semaphore.hpp +# test_Timer.hpp +# test_Common.hpp # test_TimerThreadMultimap.hpp ) target_link_libraries(test CppUtils gcov) diff --git a/test/run_test.sh b/test/run_test.sh index 06e1499..d225319 100755 --- a/test/run_test.sh +++ b/test/run_test.sh @@ -46,6 +46,9 @@ rm -f ./leak.log.core.* # cxxtest output rm -f $test.out +#rm $(find .. -name *.gcda) +find .. -name *.gcda -exec rm -rf {} \; + echo -e "${pre}Run tests${post}" diff --git a/test/test_Multiton.hpp b/test/test_Multiton.hpp new file mode 100644 index 0000000..decd5a8 --- /dev/null +++ b/test/test_Multiton.hpp @@ -0,0 +1,38 @@ +#include + +#include "Common.hpp" +#include "Fixture.hpp" +#include "Multiton.hpp" + + +class TestMultitonSuite : public CxxTest::TestSuite +{ + +private: + + class Dummy + { + public: + void sayHi() { LOG( Logger::FINEST, "Hi there!"); } + + }; + + class DummyMultiton : public Multiton + { + + }; + +public: + + void testBasic( void ) + { + TEST_HEADER; + + DummyMultiton::getRef("foobar").sayHi(); + DummyMultiton::getPtr("foobar")->sayHi(); + + DummyMultiton::destroy(); + } + + +}; diff --git a/test/test_Singelton_DCLP.hpp b/test/test_Singelton_DCLP.hpp new file mode 100644 index 0000000..d5089b3 --- /dev/null +++ b/test/test_Singelton_DCLP.hpp @@ -0,0 +1,35 @@ +#include + +#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 + { + public: + int getSeven() + { + TRACE; + return 7; + } + }; + +public: + + void testBasic( void ) + { + TEST_HEADER; + + TS_ASSERT_EQUALS( BasicSingleton::getInstance()->getSeven(), 7 ); + } + + +}; diff --git a/test/test_Singelton_call_once.hpp b/test/test_Singelton_call_once.hpp new file mode 100644 index 0000000..873530a --- /dev/null +++ b/test/test_Singelton_call_once.hpp @@ -0,0 +1,35 @@ +#include + +#define private public // need to reach Singleton's private m_instance + +#include "Common.hpp" +#include "Fixture.hpp" +#include "Singleton_call_once.hpp" + + +class TestSingletonCallOnceSuite : public CxxTest::TestSuite +{ + +private: + + class BasicSingleton : public Singleton_call_once + { + public: + int getSeven() + { + TRACE; + return 7; + } + }; + +public: + + void testBasic( void ) + { + TEST_HEADER; + + TS_ASSERT_EQUALS( BasicSingleton::getInstance()->getSeven(), 7 ); + } + + +}; diff --git a/test/test_Singelton.hpp b/test/test_Singleton.hpp similarity index 100% rename from test/test_Singelton.hpp rename to test/test_Singleton.hpp diff --git a/test/test_Singleton_DCLP.hpp b/test/test_Singleton_DCLP.hpp new file mode 100644 index 0000000..d5089b3 --- /dev/null +++ b/test/test_Singleton_DCLP.hpp @@ -0,0 +1,35 @@ +#include + +#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 + { + public: + int getSeven() + { + TRACE; + return 7; + } + }; + +public: + + void testBasic( void ) + { + TEST_HEADER; + + TS_ASSERT_EQUALS( BasicSingleton::getInstance()->getSeven(), 7 ); + } + + +}; diff --git a/test/test_Singleton_meyers.hpp b/test/test_Singleton_meyers.hpp new file mode 100644 index 0000000..4047678 --- /dev/null +++ b/test/test_Singleton_meyers.hpp @@ -0,0 +1,35 @@ +#include + +#define private public // need to reach Singleton's private m_instance + +#include "Common.hpp" +#include "Fixture.hpp" +#include "Singleton_meyers.hpp" + + +class TestSingletonMeyersSuite : public CxxTest::TestSuite +{ + +private: + + class BasicSingleton : public Singleton_meyers + { + public: + int getSeven() + { + TRACE; + return 7; + } + }; + +public: + + void testBasic( void ) + { + TEST_HEADER; + + TS_ASSERT_EQUALS( BasicSingleton::getInstance()->getSeven(), 7 ); + } + + +};