/
BirdLeon
/
ROBLOX2016
Обзор
Документация
Войти
/
BirdLeon
/
ROBLOX2016
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
Library/boost/libs/interprocess/test/intermodule_singleton_test.cpp
327 строк
9 KB
PatoFlamejanteTV
full source code
19 дек 2024, 19:11
19 дек 2024, 19:11
05db15d
Код
Авторство
О чём код?
////////////////////////////////////////////////////////////////////////////// // // (C) Copyright Ion Gaztanaga 2004-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // // See http://www.boost.org/libs/interprocess for documentation. // ////////////////////////////////////////////////////////////////////////////// #include <boost/interprocess/detail/intermodule_singleton.hpp> #include <boost/interprocess/detail/portable_intermodule_singleton.hpp> #include <iostream> #include <cstdlib> //for std::abort using namespace boost::interprocess; class MyClass { public: MyClass() { std::cout << "MyClass()\n" << std::endl; } void shout() const { std::cout << "Shout\n" << std::endl; } ~MyClass() { std::cout << "~MyClass()\n" << std::endl; } }; class MyDerivedClass : public MyClass {}; class MyThrowingClass { public: MyThrowingClass() { throw int(0); } }; template < template<class T, bool LazyInit, bool Phoenix> class IntermoduleType > int intermodule_singleton_test() { bool exception_thrown = false; bool exception_2_thrown = false; try{ IntermoduleType<MyThrowingClass, true, false>::get(); } catch(int &){ exception_thrown = true; //Second try try{ IntermoduleType<MyThrowingClass, true, false>::get(); } catch(interprocess_exception &){ exception_2_thrown = true; } } if(!exception_thrown || !exception_2_thrown){ return 1; } MyClass & mc = IntermoduleType<MyClass, true, false>::get(); mc.shout(); IntermoduleType<MyClass, true, false>::get().shout(); IntermoduleType<MyDerivedClass, true, false>::get().shout(); //Second try exception_2_thrown = false; try{ IntermoduleType<MyThrowingClass, true, false>::get(); } catch(interprocess_exception &){ exception_2_thrown = true; } if(!exception_2_thrown){ return 1; } return 0; } //A class simulating a logger //We'll register constructor/destructor counts //to test the singleton was correctly resurrected //by LogUser singleton. template<class Tag> class Logger { public: Logger() { ++constructed_times; std::cout << "Logger(),tag:" << typeid(Tag).name() << "(construct #" << constructed_times << ")\n" << std::endl; } void log_it() {} ~Logger() { ++destroyed_times; std::cout << "~Logger(),tag:" << typeid(Tag).name() << "(destroy #" << destroyed_times << ")\n" << std::endl; } static unsigned int constructed_times; static unsigned int destroyed_times; }; template<class Tag> unsigned int Logger<Tag>::constructed_times; template<class Tag> unsigned int Logger<Tag>::destroyed_times; //A class simulating a logger user. //The destructor uses the logger so that //the logger is resurrected if it was //already destroyed template<class LogSingleton> class LogUser { public: LogUser() { std::cout << "LogUser(),tag:" << typeid(LogSingleton).name() << "\n" << std::endl; } void function_using_log() { LogSingleton::get().log_it(); } ~LogUser() { std::cout << "~LogUser(),tag:" << typeid(LogSingleton).name() << "\n" << std::endl; LogSingleton::get().log_it(); } }; //A class that tests the correct //phoenix singleton behaviour. //Logger should be resurrected by LogUser template<class Tag> class LogPhoenixTester { public: LogPhoenixTester() { std::cout << "LogPhoenixTester(), tag: " << typeid(Tag).name() << "\n" << std::endl; } void dummy() {} ~LogPhoenixTester() { //Test Phoenix singleton was correctly executed: //created and destroyed two times //This test will be executed after main ends std::cout << "~LogPhoenixTester(), tag: " << typeid(Tag).name() << "\n" << std::endl; if(Logger<Tag>::constructed_times != Logger<Tag>::destroyed_times || Logger<Tag>::constructed_times != 2) { std::stringstream sstr; sstr << "LogPhoenixTester failed for tag "; sstr << typeid(Tag).name(); sstr << "\n"; if(Logger<Tag>::constructed_times != 2){ sstr << "Logger<Tag>::constructed_times != 2\n"; sstr << "("; sstr << Logger<Tag>::constructed_times << ")\n"; } else{ sstr << "Logger<Tag>::constructed_times != Logger<Tag>::destroyed_times\n"; sstr << "(" << Logger<Tag>::constructed_times << " vs. " << Logger<Tag>::destroyed_times << ")\n"; } std::cout << "~LogPhoenixTester(), error: " << sstr.str() << std::endl; std::abort(); } } }; //A class simulating a logger user. //The destructor uses the logger so that //the logger is resurrected if it was //already destroyed template<class LogSingleton> class LogDeadReferenceUser { public: LogDeadReferenceUser() { std::cout << "LogDeadReferenceUser(), LogSingleton: " << typeid(LogSingleton).name() << "\n" << std::endl; } void function_using_log() { LogSingleton::get().log_it(); } ~LogDeadReferenceUser() { std::cout << "~LogDeadReferenceUser(), LogSingleton: " << typeid(LogSingleton).name() << "\n" << std::endl; //Make sure the exception is thrown as we are //trying to use a dead non-phoenix singleton try{ LogSingleton::get().log_it(); std::string s("LogDeadReferenceUser failed for LogSingleton "); s += typeid(LogSingleton).name(); std::cout << "~LogDeadReferenceUser(), error: " << s << std::endl; std::abort(); } catch(interprocess_exception &){ //Correct behaviour } } }; template < template<class T, bool LazyInit, bool Phoenix> class IntermoduleType > int phoenix_singleton_test() { typedef int DummyType; typedef IntermoduleType<DummyType, true, true> Tag; typedef Logger<Tag> LoggerType; typedef IntermoduleType<LoggerType, true, true> LoggerSingleton; typedef LogUser<LoggerSingleton> LogUserType; typedef IntermoduleType<LogUserType, true, true> LogUserSingleton; typedef IntermoduleType<LogPhoenixTester<Tag>, true, true> LogPhoenixTesterSingleton; //Instantiate Phoenix tester singleton so that it will be destroyed the last LogPhoenixTesterSingleton::get().dummy(); //Now instantitate a log user singleton LogUserType &log_user = LogUserSingleton::get(); //Then force LoggerSingleton instantiation //calling a function that will use it. //After main ends, LoggerSingleton will be destroyed //before LogUserSingleton due to LIFO //singleton semantics log_user.function_using_log(); //Next, LogUserSingleton destructor will resurrect //LoggerSingleton. //After that LoggerSingleton will be destroyed and //lastly LogPhoenixTester will be destroyed checking //LoggerSingleton was correctly destroyed. return 0; } template < template<class T, bool LazyInit, bool Phoenix> class IntermoduleType > int dead_reference_singleton_test() { typedef int DummyType; typedef IntermoduleType<DummyType, true, false> Tag; typedef Logger<Tag> LoggerType; typedef IntermoduleType<LoggerType, true, false> LoggerSingleton; typedef LogDeadReferenceUser<LoggerSingleton> LogDeadReferenceUserType; typedef IntermoduleType<LogDeadReferenceUserType, true, false> LogDeadReferenceUserSingleton; //Now instantitate a log user singleton LogDeadReferenceUserType &log_user = LogDeadReferenceUserSingleton::get(); //Then force LoggerSingleton instantiation //calling a function that will use it. //After main ends, LoggerSingleton will be destroyed //before LogDeadReferenceUserType due to LIFO //singleton semantics log_user.function_using_log(); //Next, LogDeadReferenceUserType destructor will try to use //LoggerSingleton and an exception will be raised an catched. return 0; } //reduce name length template<typename C, bool LazyInit, bool Phoenix> class port_singleton : public ipcdetail::portable_intermodule_singleton<C, LazyInit, Phoenix> {}; #ifdef BOOST_INTERPROCESS_WINDOWS template<typename C, bool LazyInit, bool Phoenix> class win_singleton : public ipcdetail::windows_intermodule_singleton< C, LazyInit, Phoenix> {}; #endif int main () { if(0 != intermodule_singleton_test<port_singleton>()){ return 1; } #ifdef BOOST_INTERPROCESS_WINDOWS if(0 != intermodule_singleton_test<win_singleton>()){ return 1; } #endif //Only few platforms support this #ifdef BOOST_INTERPROCESS_ATEXIT_CALLABLE_FROM_ATEXIT //Phoenix singletons are tested after main ends, //LogPhoenixTester does the work phoenix_singleton_test<port_singleton>(); #ifdef BOOST_INTERPROCESS_WINDOWS phoenix_singleton_test<win_singleton>(); #endif #endif //Dead reference singletons are tested after main ends, //LogDeadReferenceUser does the work dead_reference_singleton_test<port_singleton>(); #ifdef BOOST_INTERPROCESS_WINDOWS dead_reference_singleton_test<win_singleton>(); #endif return 0; }