mirror of
https://github.com/boostorg/interprocess.git
synced 2026-01-19 04:12:13 +00:00
Intermodule singleton optimization for windows
[SVN r79515]
This commit is contained in:
@@ -6615,6 +6615,14 @@ thank them:
|
||||
|
||||
[section:release_notes Release Notes]
|
||||
|
||||
[section:release_notes_boost_1_51_00 Boost 1.51 Release]
|
||||
|
||||
* Synchronous and asynchronous flushing for `mapped_region::flush`.
|
||||
* Source & ABI breaking: Removed `get_offset` method from `mapped_region` as
|
||||
it has no practical utility and `m_offset` member was not for anything else.
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:release_notes_boost_1_50_00 Boost 1.50 Release]
|
||||
|
||||
* Fixed bugs
|
||||
|
||||
@@ -34,8 +34,9 @@
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalOptions="/fixed:no"
|
||||
AdditionalDependencies="winmm.lib"
|
||||
OutputFile="$(OutDir)/fully_mapped_file_test_d.exe"
|
||||
OutputFile="$(OutDir)/mapped_file_test_d.exe"
|
||||
LinkIncremental="1"
|
||||
AdditionalLibraryDirectories="../../../../stage/lib"
|
||||
GenerateDebugInformation="TRUE"
|
||||
|
||||
@@ -47,8 +47,8 @@ inline boost::xtime delay(int secs, int msecs=0, int nsecs=0)
|
||||
const int NANOSECONDS_PER_MILLISECOND = 1000000;
|
||||
|
||||
boost::xtime xt;
|
||||
int ret = boost::xtime_get(&xt, boost::TIME_UTC_);
|
||||
BOOST_INTERPROCES_CHECK(ret == static_cast<int>(boost::TIME_UTC_));(void)ret;
|
||||
int ret = boost::xtime_get(&xt, boost::TIME_UTC);
|
||||
BOOST_INTERPROCES_CHECK(ret == static_cast<int>(boost::TIME_UTC));(void)ret;
|
||||
nsecs += xt.nsec;
|
||||
msecs += nsecs / NANOSECONDS_PER_MILLISECOND;
|
||||
secs += msecs / MILLISECONDS_PER_SECOND;
|
||||
|
||||
@@ -27,6 +27,13 @@ inline void get_process_id_name(std::string &str)
|
||||
str = sstr.str().c_str();
|
||||
}
|
||||
|
||||
inline void get_process_id_ptr_name(std::string &str, const void *ptr)
|
||||
{
|
||||
std::stringstream sstr;
|
||||
sstr << "process_" << boost::interprocess::ipcdetail::get_current_process_id() << "_" << ptr << std::ends;
|
||||
str = sstr.str().c_str();
|
||||
}
|
||||
|
||||
inline const char *get_process_id_name()
|
||||
{
|
||||
static std::string str;
|
||||
@@ -34,6 +41,13 @@ inline const char *get_process_id_name()
|
||||
return str.c_str();
|
||||
}
|
||||
|
||||
inline const char *get_process_id_ptr_name(void *ptr)
|
||||
{
|
||||
static std::string str;
|
||||
get_process_id_ptr_name(str, ptr);
|
||||
return str.c_str();
|
||||
}
|
||||
|
||||
inline const char *add_to_process_id_name(const char *name)
|
||||
{
|
||||
static std::string str;
|
||||
@@ -42,6 +56,14 @@ inline const char *add_to_process_id_name(const char *name)
|
||||
return str.c_str();
|
||||
}
|
||||
|
||||
inline const char *add_to_process_id_ptr_name(const char *name, void *ptr)
|
||||
{
|
||||
static std::string str;
|
||||
get_process_id_ptr_name(str, ptr);
|
||||
str += name;
|
||||
return str.c_str();
|
||||
}
|
||||
|
||||
} //namespace test{
|
||||
} //namespace interprocess{
|
||||
} //namespace boost{
|
||||
|
||||
@@ -18,17 +18,17 @@ class MyClass
|
||||
public:
|
||||
MyClass()
|
||||
{
|
||||
std::cout << "Constructor\n";
|
||||
std::cout << "MyClass()\n" << std::endl;
|
||||
}
|
||||
|
||||
void shout() const
|
||||
{
|
||||
std::cout << "Shout\n";
|
||||
std::cout << "Shout\n" << std::endl;
|
||||
}
|
||||
|
||||
~MyClass()
|
||||
{
|
||||
std::cout << "Destructor\n";
|
||||
std::cout << "~MyClass()\n" << std::endl;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -101,6 +101,7 @@ class Logger
|
||||
Logger()
|
||||
{
|
||||
++constructed_times;
|
||||
std::cout << "Logger(),tag:" << typeid(Tag).name() << "(construct #" << constructed_times << ")\n" << std::endl;
|
||||
}
|
||||
|
||||
void log_it()
|
||||
@@ -109,6 +110,7 @@ class Logger
|
||||
~Logger()
|
||||
{
|
||||
++destroyed_times;
|
||||
std::cout << "~Logger(),tag:" << typeid(Tag).name() << "(destroy #" << destroyed_times << ")\n" << std::endl;
|
||||
}
|
||||
|
||||
static unsigned int constructed_times;
|
||||
@@ -130,13 +132,18 @@ class LogUser
|
||||
{
|
||||
public:
|
||||
LogUser()
|
||||
{}
|
||||
{
|
||||
std::cout << "LogUser(),tag:" << typeid(LogSingleton).name() << "\n" << std::endl;
|
||||
}
|
||||
|
||||
void function_using_log()
|
||||
{ LogSingleton::get().log_it(); }
|
||||
|
||||
~LogUser()
|
||||
{ LogSingleton::get().log_it(); }
|
||||
{
|
||||
std::cout << "~LogUser(),tag:" << typeid(LogSingleton).name() << "\n" << std::endl;
|
||||
LogSingleton::get().log_it();
|
||||
}
|
||||
};
|
||||
|
||||
//A class that tests the correct
|
||||
@@ -147,7 +154,9 @@ class LogPhoenixTester
|
||||
{
|
||||
public:
|
||||
LogPhoenixTester()
|
||||
{}
|
||||
{
|
||||
std::cout << "LogPhoenixTester(), tag: " << typeid(Tag).name() << "\n" << std::endl;
|
||||
}
|
||||
|
||||
void dummy()
|
||||
{}
|
||||
@@ -157,12 +166,24 @@ class 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::string s("LogPhoenixTester failed for tag ");
|
||||
s += typeid(Tag).name();
|
||||
throw std::runtime_error(s.c_str());
|
||||
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";
|
||||
}
|
||||
throw std::runtime_error(sstr.str().c_str());
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -176,15 +197,18 @@ 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
|
||||
//try to use a dead non-phoenix singleton
|
||||
//trying to use a dead non-phoenix singleton
|
||||
try{
|
||||
LogSingleton::get().log_it();
|
||||
std::string s("LogDeadReferenceUser failed for LogSingleton ");
|
||||
@@ -254,30 +278,43 @@ int dead_reference_singleton_test()
|
||||
return 0;
|
||||
}
|
||||
|
||||
//reduce name length
|
||||
template<typename C, bool LazyInit = true, bool Phoenix = true>
|
||||
class port_singleton
|
||||
: public ipcdetail::portable_intermodule_singleton<C, LazyInit, Phoenix>
|
||||
{};
|
||||
|
||||
#ifdef BOOST_INTERPROCESS_WINDOWS
|
||||
template<typename C, bool LazyInit = true, bool Phoenix = true>
|
||||
class win_singleton
|
||||
: public ipcdetail::windows_intermodule_singleton< C, LazyInit, Phoenix>
|
||||
{};
|
||||
#endif
|
||||
|
||||
int main ()
|
||||
{
|
||||
if(0 != intermodule_singleton_test<ipcdetail::portable_intermodule_singleton>()){
|
||||
if(0 != intermodule_singleton_test<port_singleton>()){
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifdef BOOST_INTERPROCESS_WINDOWS
|
||||
if(0 != intermodule_singleton_test<ipcdetail::windows_intermodule_singleton>()){
|
||||
if(0 != intermodule_singleton_test<win_singleton>()){
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
//Phoenix singletons are tested after main ends,
|
||||
//LogPhoenixTester does the work
|
||||
phoenix_singleton_test<ipcdetail::portable_intermodule_singleton>();
|
||||
phoenix_singleton_test<port_singleton>();
|
||||
#ifdef BOOST_INTERPROCESS_WINDOWS
|
||||
phoenix_singleton_test<ipcdetail::windows_intermodule_singleton>();
|
||||
phoenix_singleton_test<win_singleton>();
|
||||
#endif
|
||||
|
||||
//Dead reference singletons are tested after main ends,
|
||||
//LogDeadReferenceUser does the work
|
||||
dead_reference_singleton_test<ipcdetail::portable_intermodule_singleton>();
|
||||
dead_reference_singleton_test<port_singleton>();
|
||||
#ifdef BOOST_INTERPROCESS_WINDOWS
|
||||
dead_reference_singleton_test<ipcdetail::windows_intermodule_singleton>();
|
||||
dead_reference_singleton_test<win_singleton>();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -24,13 +24,13 @@ int main ()
|
||||
|
||||
#if defined(BOOST_INTERPROCESS_WINDOWS)
|
||||
test::test_all_lock<ipcdetail::windows_mutex>();
|
||||
test::test_all_mutex<true, ipcdetail::windows_mutex>();
|
||||
test::test_all_mutex<ipcdetail::windows_mutex>();
|
||||
test::test_all_lock<ipcdetail::spin_mutex>();
|
||||
test::test_all_mutex<true, ipcdetail::spin_mutex>();
|
||||
test::test_all_mutex<ipcdetail::spin_mutex>();
|
||||
#endif
|
||||
|
||||
test::test_all_lock<interprocess_mutex>();
|
||||
test::test_all_mutex<true, interprocess_mutex>();
|
||||
test::test_all_mutex<interprocess_mutex>();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -228,33 +228,24 @@ void timed_lock_and_sleep(void *arg, M &sm)
|
||||
}
|
||||
}
|
||||
|
||||
template<bool SameObject, typename M>
|
||||
template<typename M>
|
||||
void test_mutex_lock()
|
||||
{
|
||||
shared_val = 0;
|
||||
|
||||
M m1, m2;
|
||||
M *pm1, *pm2;
|
||||
|
||||
if(SameObject){
|
||||
pm1 = pm2 = &m1;
|
||||
}
|
||||
else{
|
||||
pm1 = &m1;
|
||||
pm2 = &m2;
|
||||
}
|
||||
M mtx;
|
||||
|
||||
data<M> d1(1);
|
||||
data<M> d2(2);
|
||||
|
||||
// Locker one launches, holds the lock for 2*BaseSeconds seconds.
|
||||
boost::thread tm1(thread_adapter<M>(&lock_and_sleep, &d1, *pm1));
|
||||
boost::thread tm1(thread_adapter<M>(&lock_and_sleep, &d1, mtx));
|
||||
|
||||
//Wait 1*BaseSeconds
|
||||
boost::thread::sleep(xsecs(1*BaseSeconds));
|
||||
|
||||
// Locker two launches, but it won't hold the lock for 2*BaseSeconds seconds.
|
||||
boost::thread tm2(thread_adapter<M>(&lock_and_sleep, &d2, *pm2));
|
||||
boost::thread tm2(thread_adapter<M>(&lock_and_sleep, &d2, mtx));
|
||||
|
||||
//Wait completion
|
||||
tm1.join();
|
||||
@@ -265,21 +256,12 @@ void test_mutex_lock()
|
||||
BOOST_INTERPROCES_CHECK(d2.m_value == 2);
|
||||
}
|
||||
|
||||
template<bool SameObject, typename M>
|
||||
template<typename M>
|
||||
void test_mutex_lock_timeout()
|
||||
{
|
||||
shared_val = 0;
|
||||
|
||||
M m1, m2;
|
||||
M *pm1, *pm2;
|
||||
|
||||
if(SameObject){
|
||||
pm1 = pm2 = &m1;
|
||||
}
|
||||
else{
|
||||
pm1 = &m1;
|
||||
pm2 = &m2;
|
||||
}
|
||||
M mtx;
|
||||
|
||||
int wait_time_s = BOOST_INTERPROCESS_TIMEOUT_WHEN_LOCKING_DURATION_MS / 1000;
|
||||
if (wait_time_s == 0 )
|
||||
@@ -289,13 +271,13 @@ void test_mutex_lock_timeout()
|
||||
data<M> d2(2, wait_time_s * 2);
|
||||
|
||||
// Locker one launches, and holds the lock for wait_time_s * 2 seconds.
|
||||
boost::thread tm1(thread_adapter<M>(&lock_and_sleep, &d1, *pm1));
|
||||
boost::thread tm1(thread_adapter<M>(&lock_and_sleep, &d1, mtx));
|
||||
|
||||
//Wait 1*BaseSeconds
|
||||
boost::thread::sleep(xsecs(wait_time_s));
|
||||
|
||||
// Locker two launches, and attempts to hold the lock for wait_time_s * 2 seconds.
|
||||
boost::thread tm2(thread_adapter<M>(&lock_and_catch_errors, &d2, *pm2));
|
||||
boost::thread tm2(thread_adapter<M>(&lock_and_catch_errors, &d2, mtx));
|
||||
|
||||
//Wait completion
|
||||
tm1.join();
|
||||
@@ -308,33 +290,24 @@ void test_mutex_lock_timeout()
|
||||
BOOST_INTERPROCES_CHECK(d2.m_error == boost::interprocess::timeout_when_locking_error);
|
||||
}
|
||||
|
||||
template<bool SameObject, typename M>
|
||||
template<typename M>
|
||||
void test_mutex_try_lock()
|
||||
{
|
||||
shared_val = 0;
|
||||
|
||||
M m1, m2;
|
||||
M *pm1, *pm2;
|
||||
|
||||
if(SameObject){
|
||||
pm1 = pm2 = &m1;
|
||||
}
|
||||
else{
|
||||
pm1 = &m1;
|
||||
pm2 = &m2;
|
||||
}
|
||||
M mtx;
|
||||
|
||||
data<M> d1(1);
|
||||
data<M> d2(2);
|
||||
|
||||
// Locker one launches, holds the lock for 2*BaseSeconds seconds.
|
||||
boost::thread tm1(thread_adapter<M>(&try_lock_and_sleep, &d1, *pm1));
|
||||
boost::thread tm1(thread_adapter<M>(&try_lock_and_sleep, &d1, mtx));
|
||||
|
||||
//Wait 1*BaseSeconds
|
||||
boost::thread::sleep(xsecs(1*BaseSeconds));
|
||||
|
||||
// Locker two launches, but it should fail acquiring the lock
|
||||
boost::thread tm2(thread_adapter<M>(&try_lock_and_sleep, &d2, *pm2));
|
||||
boost::thread tm2(thread_adapter<M>(&try_lock_and_sleep, &d2, mtx));
|
||||
|
||||
//Wait completion
|
||||
tm1.join();
|
||||
@@ -344,34 +317,25 @@ void test_mutex_try_lock()
|
||||
BOOST_INTERPROCES_CHECK(d2.m_value == -1);
|
||||
}
|
||||
|
||||
template<bool SameObject, typename M>
|
||||
template<typename M>
|
||||
void test_mutex_timed_lock()
|
||||
|
||||
{
|
||||
shared_val = 0;
|
||||
|
||||
M m1, m2;
|
||||
M *pm1, *pm2;
|
||||
|
||||
if(SameObject){
|
||||
pm1 = pm2 = &m1;
|
||||
}
|
||||
else{
|
||||
pm1 = &m1;
|
||||
pm2 = &m2;
|
||||
}
|
||||
M mtx, m2;
|
||||
|
||||
data<M> d1(1, 2*BaseSeconds);
|
||||
data<M> d2(2, 2*BaseSeconds);
|
||||
|
||||
// Locker one launches, holds the lock for 2*BaseSeconds seconds.
|
||||
boost::thread tm1(thread_adapter<M>(&timed_lock_and_sleep, &d1, *pm1));
|
||||
boost::thread tm1(thread_adapter<M>(&timed_lock_and_sleep, &d1, mtx));
|
||||
|
||||
//Wait 1*BaseSeconds
|
||||
boost::thread::sleep(xsecs(1*BaseSeconds));
|
||||
|
||||
// Locker two launches, holds the lock for 2*BaseSeconds seconds.
|
||||
boost::thread tm2(thread_adapter<M>(&timed_lock_and_sleep, &d2, *pm2));
|
||||
boost::thread tm2(thread_adapter<M>(&timed_lock_and_sleep, &d2, mtx));
|
||||
|
||||
//Wait completion
|
||||
tm1.join();
|
||||
@@ -402,15 +366,15 @@ inline void test_all_recursive_lock()
|
||||
test_recursive_lock<M>()();
|
||||
}
|
||||
|
||||
template<bool SameObject, typename M>
|
||||
template<typename M>
|
||||
void test_all_mutex()
|
||||
{
|
||||
std::cout << "test_mutex_lock<" << typeid(M).name() << ">" << std::endl;
|
||||
test_mutex_lock<SameObject, M>();
|
||||
test_mutex_lock<M>();
|
||||
std::cout << "test_mutex_try_lock<" << typeid(M).name() << ">" << std::endl;
|
||||
test_mutex_try_lock<SameObject, M>();
|
||||
test_mutex_try_lock<M>();
|
||||
std::cout << "test_mutex_timed_lock<" << typeid(M).name() << ">" << std::endl;
|
||||
test_mutex_timed_lock<SameObject, M>();
|
||||
test_mutex_timed_lock<M>();
|
||||
}
|
||||
|
||||
}}} //namespace boost { namespace interprocess { namespace test {
|
||||
|
||||
@@ -21,8 +21,8 @@
|
||||
int main ()
|
||||
{
|
||||
using namespace boost::interprocess;
|
||||
test::test_mutex_lock_timeout<true, interprocess_mutex>();
|
||||
test::test_mutex_lock_timeout<true, interprocess_recursive_mutex>();
|
||||
test::test_mutex_lock_timeout<interprocess_mutex>();
|
||||
test::test_mutex_lock_timeout<interprocess_recursive_mutex>();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/exceptions.hpp>
|
||||
#include "boost_interprocess_check.hpp"
|
||||
#include "get_process_id_name.hpp"
|
||||
#include <iostream>
|
||||
#include <typeinfo>
|
||||
#include <boost/interprocess/creation_tags.hpp>
|
||||
@@ -77,6 +78,53 @@ inline void test_named_creation()
|
||||
dont_create_and_open<NamedResource>();
|
||||
}
|
||||
|
||||
template<class NamedSync>
|
||||
class named_sync_wrapper
|
||||
: public NamedSync
|
||||
{
|
||||
public:
|
||||
named_sync_wrapper()
|
||||
: NamedSync(open_or_create, test::get_process_id_ptr_name(this))
|
||||
{}
|
||||
|
||||
~named_sync_wrapper()
|
||||
{
|
||||
NamedSync::remove(test::get_process_id_ptr_name(this));
|
||||
}
|
||||
};
|
||||
|
||||
template<class NamedSync>
|
||||
struct named_sync_deleter
|
||||
{
|
||||
~named_sync_deleter()
|
||||
{ NamedSync::remove(test::get_process_id_name()); }
|
||||
};
|
||||
|
||||
|
||||
//This wrapper is necessary to have a common constructor
|
||||
//in generic named_creation_template functions
|
||||
template<class NamedSync>
|
||||
class named_sync_creation_test_wrapper
|
||||
: public test::named_sync_deleter<NamedSync>, public NamedSync
|
||||
{
|
||||
public:
|
||||
named_sync_creation_test_wrapper(create_only_t)
|
||||
: NamedSync(create_only, test::get_process_id_name())
|
||||
{}
|
||||
|
||||
named_sync_creation_test_wrapper(open_only_t)
|
||||
: NamedSync(open_only, test::get_process_id_name())
|
||||
{}
|
||||
|
||||
named_sync_creation_test_wrapper(open_or_create_t)
|
||||
: NamedSync(open_or_create, test::get_process_id_name())
|
||||
{}
|
||||
|
||||
~named_sync_creation_test_wrapper()
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
}}} //namespace boost { namespace interprocess { namespace test {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
@@ -14,78 +14,17 @@
|
||||
#include "mutex_test_template.hpp"
|
||||
#include "named_creation_template.hpp"
|
||||
#include <string>
|
||||
#include "get_process_id_name.hpp"
|
||||
#include <boost/interprocess/detail/interprocess_tester.hpp>
|
||||
|
||||
using namespace boost::interprocess;
|
||||
|
||||
struct mutex_deleter
|
||||
{
|
||||
~mutex_deleter()
|
||||
{ named_mutex::remove(test::get_process_id_name()); }
|
||||
};
|
||||
|
||||
//This wrapper is necessary to have a default constructor
|
||||
//in generic mutex_test_template functions
|
||||
class named_mutex_lock_test_wrapper
|
||||
: public named_mutex
|
||||
{
|
||||
public:
|
||||
named_mutex_lock_test_wrapper()
|
||||
: named_mutex(open_or_create, test::get_process_id_name())
|
||||
{ ++count_; }
|
||||
|
||||
~named_mutex_lock_test_wrapper()
|
||||
{
|
||||
if(--count_){
|
||||
ipcdetail::interprocess_tester::
|
||||
dont_close_on_destruction(static_cast<named_mutex&>(*this));
|
||||
}
|
||||
}
|
||||
|
||||
static int count_;
|
||||
};
|
||||
|
||||
int named_mutex_lock_test_wrapper::count_ = 0;
|
||||
|
||||
//This wrapper is necessary to have a common constructor
|
||||
//in generic named_creation_template functions
|
||||
class named_mutex_creation_test_wrapper
|
||||
: public mutex_deleter, public named_mutex
|
||||
{
|
||||
public:
|
||||
named_mutex_creation_test_wrapper(create_only_t)
|
||||
: named_mutex(create_only, test::get_process_id_name())
|
||||
{ ++count_; }
|
||||
|
||||
named_mutex_creation_test_wrapper(open_only_t)
|
||||
: named_mutex(open_only, test::get_process_id_name())
|
||||
{ ++count_; }
|
||||
|
||||
named_mutex_creation_test_wrapper(open_or_create_t)
|
||||
: named_mutex(open_or_create, test::get_process_id_name())
|
||||
{ ++count_; }
|
||||
|
||||
~named_mutex_creation_test_wrapper()
|
||||
{
|
||||
if(--count_){
|
||||
ipcdetail::interprocess_tester::
|
||||
dont_close_on_destruction(static_cast<named_mutex&>(*this));
|
||||
}
|
||||
}
|
||||
|
||||
static int count_;
|
||||
};
|
||||
|
||||
int named_mutex_creation_test_wrapper::count_ = 0;
|
||||
|
||||
int main ()
|
||||
{
|
||||
try{
|
||||
named_mutex::remove(test::get_process_id_name());
|
||||
test::test_named_creation<named_mutex_creation_test_wrapper>();
|
||||
test::test_all_lock<named_mutex_lock_test_wrapper>();
|
||||
test::test_all_mutex<false, named_mutex_lock_test_wrapper>();
|
||||
test::test_named_creation< test::named_sync_creation_test_wrapper<named_mutex> >();
|
||||
test::test_all_lock< test::named_sync_wrapper<named_mutex> >();
|
||||
test::test_all_mutex<test::named_sync_wrapper<named_mutex> >();
|
||||
}
|
||||
catch(std::exception &ex){
|
||||
named_mutex::remove(test::get_process_id_name());
|
||||
|
||||
@@ -19,74 +19,14 @@
|
||||
|
||||
using namespace boost::interprocess;
|
||||
|
||||
struct mutex_deleter
|
||||
{
|
||||
~mutex_deleter()
|
||||
{ named_recursive_mutex::remove(test::get_process_id_name()); }
|
||||
};
|
||||
|
||||
//This wrapper is necessary to have a default constructor
|
||||
//in generic mutex_test_template functions
|
||||
class named_recursive_mutex_lock_test_wrapper
|
||||
: public named_recursive_mutex
|
||||
{
|
||||
public:
|
||||
named_recursive_mutex_lock_test_wrapper()
|
||||
: named_recursive_mutex(open_or_create, test::get_process_id_name())
|
||||
{ ++count_; }
|
||||
|
||||
~named_recursive_mutex_lock_test_wrapper()
|
||||
{
|
||||
if(--count_){
|
||||
ipcdetail::interprocess_tester::
|
||||
dont_close_on_destruction(static_cast<named_recursive_mutex&>(*this));
|
||||
}
|
||||
}
|
||||
|
||||
static int count_;
|
||||
};
|
||||
|
||||
int named_recursive_mutex_lock_test_wrapper::count_ = 0;
|
||||
|
||||
//This wrapper is necessary to have a common constructor
|
||||
//in generic named_creation_template functions
|
||||
class named_mutex_creation_test_wrapper
|
||||
: public mutex_deleter, public named_recursive_mutex
|
||||
{
|
||||
public:
|
||||
named_mutex_creation_test_wrapper(create_only_t)
|
||||
: named_recursive_mutex(create_only, test::get_process_id_name())
|
||||
{ ++count_; }
|
||||
|
||||
named_mutex_creation_test_wrapper(open_only_t)
|
||||
: named_recursive_mutex(open_only, test::get_process_id_name())
|
||||
{ ++count_; }
|
||||
|
||||
named_mutex_creation_test_wrapper(open_or_create_t)
|
||||
: named_recursive_mutex(open_or_create, test::get_process_id_name())
|
||||
{ ++count_; }
|
||||
|
||||
~named_mutex_creation_test_wrapper()
|
||||
{
|
||||
if(--count_){
|
||||
ipcdetail::interprocess_tester::
|
||||
dont_close_on_destruction(static_cast<named_recursive_mutex&>(*this));
|
||||
}
|
||||
}
|
||||
|
||||
static int count_;
|
||||
};
|
||||
|
||||
int named_mutex_creation_test_wrapper::count_ = 0;
|
||||
|
||||
int main ()
|
||||
{
|
||||
try{
|
||||
named_recursive_mutex::remove(test::get_process_id_name());
|
||||
test::test_named_creation<named_mutex_creation_test_wrapper>();
|
||||
test::test_all_lock<named_recursive_mutex_lock_test_wrapper>();
|
||||
test::test_all_mutex<false, named_recursive_mutex_lock_test_wrapper>();
|
||||
test::test_all_recursive_lock<named_recursive_mutex_lock_test_wrapper>();
|
||||
test::test_named_creation< test::named_sync_creation_test_wrapper<named_recursive_mutex> >();
|
||||
test::test_all_lock< test::named_sync_wrapper<named_recursive_mutex> >();
|
||||
test::test_all_mutex<test::named_sync_wrapper<named_recursive_mutex> >();
|
||||
test::test_all_recursive_lock<test::named_sync_wrapper<named_recursive_mutex> >();
|
||||
}
|
||||
catch(std::exception &ex){
|
||||
named_recursive_mutex::remove(test::get_process_id_name());
|
||||
|
||||
@@ -24,41 +24,27 @@ static const std::size_t SemCount = 1;
|
||||
static const std::size_t RecSemCount = 100;
|
||||
static const char * SemName = test::get_process_id_name();
|
||||
|
||||
struct semaphore_deleter
|
||||
{
|
||||
~semaphore_deleter()
|
||||
{ named_semaphore::remove(SemName); }
|
||||
};
|
||||
|
||||
//This wrapper is necessary to plug this class
|
||||
//in named creation tests and interprocess_mutex tests
|
||||
class named_semaphore_test_wrapper
|
||||
: public semaphore_deleter, public named_semaphore
|
||||
//in lock tests
|
||||
class lock_test_wrapper
|
||||
: public named_semaphore
|
||||
{
|
||||
public:
|
||||
named_semaphore_test_wrapper()
|
||||
: named_semaphore(open_or_create, SemName, SemCount)
|
||||
{ ++count_; }
|
||||
|
||||
named_semaphore_test_wrapper(create_only_t)
|
||||
: named_semaphore(create_only, SemName, SemCount)
|
||||
{ ++count_; }
|
||||
lock_test_wrapper(create_only_t, const char *name, unsigned int count = 1)
|
||||
: named_semaphore(create_only, name, count)
|
||||
{}
|
||||
|
||||
named_semaphore_test_wrapper(open_only_t)
|
||||
: named_semaphore(open_only, SemName)
|
||||
{ ++count_; }
|
||||
lock_test_wrapper(open_only_t, const char *name)
|
||||
: named_semaphore(open_only, name)
|
||||
{}
|
||||
|
||||
named_semaphore_test_wrapper(open_or_create_t)
|
||||
: named_semaphore(open_or_create, SemName, SemCount)
|
||||
{ ++count_; }
|
||||
lock_test_wrapper(open_or_create_t, const char *name, unsigned int count = 1)
|
||||
: named_semaphore(open_or_create, name, count)
|
||||
{}
|
||||
|
||||
~named_semaphore_test_wrapper()
|
||||
{
|
||||
if(--count_){
|
||||
ipcdetail::interprocess_tester::
|
||||
dont_close_on_destruction(static_cast<named_semaphore&>(*this));
|
||||
}
|
||||
}
|
||||
~lock_test_wrapper()
|
||||
{}
|
||||
|
||||
void lock()
|
||||
{ this->wait(); }
|
||||
@@ -71,31 +57,26 @@ class named_semaphore_test_wrapper
|
||||
|
||||
void unlock()
|
||||
{ this->post(); }
|
||||
|
||||
protected:
|
||||
named_semaphore_test_wrapper(int initial_count)
|
||||
: named_semaphore(create_only, SemName, initial_count)
|
||||
{}
|
||||
|
||||
static int count_;
|
||||
};
|
||||
|
||||
int named_semaphore_test_wrapper::count_ = 0;
|
||||
|
||||
//This wrapper is necessary to plug this class
|
||||
//in recursive tests
|
||||
class recursive_named_semaphore_test_wrapper
|
||||
: public named_semaphore_test_wrapper
|
||||
class recursive_test_wrapper
|
||||
: public lock_test_wrapper
|
||||
{
|
||||
public:
|
||||
recursive_named_semaphore_test_wrapper()
|
||||
: named_semaphore_test_wrapper(RecSemCount)
|
||||
recursive_test_wrapper(create_only_t, const char *name)
|
||||
: lock_test_wrapper(create_only, name, RecSemCount)
|
||||
{}
|
||||
|
||||
static int count_;
|
||||
};
|
||||
recursive_test_wrapper(open_only_t, const char *name)
|
||||
: lock_test_wrapper(open_only, name)
|
||||
{}
|
||||
|
||||
int recursive_named_semaphore_test_wrapper::count_ = 0;
|
||||
recursive_test_wrapper(open_or_create_t, const char *name)
|
||||
: lock_test_wrapper(open_or_create, name, RecSemCount)
|
||||
{}
|
||||
};
|
||||
|
||||
bool test_named_semaphore_specific()
|
||||
{
|
||||
@@ -125,10 +106,10 @@ int main ()
|
||||
{
|
||||
try{
|
||||
named_semaphore::remove(SemName);
|
||||
test::test_named_creation<named_semaphore_test_wrapper>();
|
||||
test::test_all_lock<named_semaphore_test_wrapper>();
|
||||
test::test_all_recursive_lock<recursive_named_semaphore_test_wrapper>();
|
||||
test::test_all_mutex<false, named_semaphore_test_wrapper>();
|
||||
test::test_named_creation< test::named_sync_creation_test_wrapper<lock_test_wrapper> >();
|
||||
test::test_all_lock< test::named_sync_wrapper<lock_test_wrapper> >();
|
||||
test::test_all_mutex<test::named_sync_wrapper<lock_test_wrapper> >();
|
||||
test::test_all_recursive_lock<test::named_sync_wrapper<recursive_test_wrapper> >();
|
||||
test_named_semaphore_specific();
|
||||
}
|
||||
catch(std::exception &ex){
|
||||
|
||||
@@ -86,10 +86,10 @@ int main ()
|
||||
{
|
||||
try{
|
||||
named_upgradable_mutex::remove(test::get_process_id_name());
|
||||
test::test_named_creation<named_upgradable_mutex_creation_test_wrapper>();
|
||||
test::test_all_lock<named_upgradable_mutex_lock_test_wrapper>();
|
||||
test::test_all_mutex<true, named_upgradable_mutex_lock_test_wrapper>();
|
||||
test::test_all_sharable_mutex<true, named_upgradable_mutex_lock_test_wrapper>();
|
||||
test::test_named_creation< test::named_sync_creation_test_wrapper<named_upgradable_mutex> >();
|
||||
test::test_all_lock< test::named_sync_wrapper<named_upgradable_mutex> >();
|
||||
test::test_all_mutex<test::named_sync_wrapper<named_upgradable_mutex> >();
|
||||
test::test_all_sharable_mutex<test::named_sync_wrapper<named_upgradable_mutex> >();
|
||||
}
|
||||
catch(std::exception &ex){
|
||||
named_upgradable_mutex::remove(test::get_process_id_name());
|
||||
|
||||
@@ -24,16 +24,16 @@ int main ()
|
||||
#if defined(BOOST_INTERPROCESS_WINDOWS)
|
||||
//
|
||||
test::test_all_lock<ipcdetail::windows_recursive_mutex>();
|
||||
test::test_all_mutex<true, ipcdetail::windows_recursive_mutex>();
|
||||
test::test_all_mutex<ipcdetail::windows_recursive_mutex>();
|
||||
test::test_all_recursive_lock<ipcdetail::windows_recursive_mutex>();
|
||||
//
|
||||
test::test_all_lock<ipcdetail::spin_recursive_mutex>();
|
||||
test::test_all_mutex<true, ipcdetail::spin_recursive_mutex>();
|
||||
test::test_all_mutex<ipcdetail::spin_recursive_mutex>();
|
||||
test::test_all_recursive_lock<ipcdetail::spin_recursive_mutex>();
|
||||
#endif
|
||||
//
|
||||
test::test_all_lock<interprocess_recursive_mutex>();
|
||||
test::test_all_mutex<true, interprocess_recursive_mutex>();
|
||||
test::test_all_mutex<interprocess_recursive_mutex>();
|
||||
test::test_all_recursive_lock<interprocess_recursive_mutex>();
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -63,7 +63,7 @@ int main ()
|
||||
|
||||
test::test_all_lock<semaphore_test_wrapper>();
|
||||
test::test_all_recursive_lock<recursive_semaphore_test_wrapper>();
|
||||
test::test_all_mutex<true, semaphore_test_wrapper>();
|
||||
test::test_all_mutex<semaphore_test_wrapper>();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -111,41 +111,30 @@ void timed_shared(void *arg, SM &sm)
|
||||
}
|
||||
}
|
||||
|
||||
template<bool SameObject, typename SM>
|
||||
template<typename SM>
|
||||
void test_plain_sharable_mutex()
|
||||
{
|
||||
{
|
||||
shared_val = 0;
|
||||
SM m1, m2, m3, m4;
|
||||
SM *pm1, *pm2, *pm3, *pm4;
|
||||
|
||||
if(SameObject){
|
||||
pm1 = pm2 = pm3 = pm4 = &m1;
|
||||
}
|
||||
else{
|
||||
pm1 = &m1;
|
||||
pm2 = &m2;
|
||||
pm3 = &m3;
|
||||
pm4 = &m4;
|
||||
}
|
||||
SM mtx;
|
||||
data<SM> s1(1);
|
||||
data<SM> s2(2);
|
||||
data<SM> e1(1);
|
||||
data<SM> e2(2);
|
||||
|
||||
// Writer one launches, holds the lock for 3*BaseSeconds seconds.
|
||||
boost::thread tw1(thread_adapter<SM>(plain_exclusive, &e1, *pm1));
|
||||
boost::thread tw1(thread_adapter<SM>(plain_exclusive, &e1, mtx));
|
||||
|
||||
// Writer two launches, tries to grab the lock, "clearly"
|
||||
// after Writer one will already be holding it.
|
||||
boost::thread::sleep(xsecs(1*BaseSeconds));
|
||||
boost::thread tw2(thread_adapter<SM>(plain_exclusive, &e2, *pm2));
|
||||
boost::thread tw2(thread_adapter<SM>(plain_exclusive, &e2, mtx));
|
||||
|
||||
// Reader one launches, "clearly" after writer two, and "clearly"
|
||||
// while writer 1 still holds the lock
|
||||
boost::thread::sleep(xsecs(1*BaseSeconds));
|
||||
boost::thread thr1(thread_adapter<SM>(plain_shared,&s1, *pm3));
|
||||
boost::thread thr2(thread_adapter<SM>(plain_shared,&s2, *pm4));
|
||||
boost::thread thr1(thread_adapter<SM>(plain_shared,&s1, mtx));
|
||||
boost::thread thr2(thread_adapter<SM>(plain_shared,&s2, mtx));
|
||||
|
||||
thr2.join();
|
||||
thr1.join();
|
||||
@@ -160,33 +149,23 @@ void test_plain_sharable_mutex()
|
||||
|
||||
{
|
||||
shared_val = 0;
|
||||
SM m1, m2, m3, m4;
|
||||
SM *pm1, *pm2, *pm3, *pm4;
|
||||
SM mtx;
|
||||
|
||||
if(SameObject){
|
||||
pm1 = pm2 = pm3 = pm4 = &m1;
|
||||
}
|
||||
else{
|
||||
pm1 = &m1;
|
||||
pm2 = &m2;
|
||||
pm3 = &m3;
|
||||
pm4 = &m4;
|
||||
}
|
||||
data<SM> s1(1, 3);
|
||||
data<SM> s2(2, 3);
|
||||
data<SM> e1(1);
|
||||
data<SM> e2(2);
|
||||
|
||||
//We launch 2 readers, that will block for 3*BaseTime seconds
|
||||
boost::thread thr1(thread_adapter<SM>(plain_shared,&s1,*pm1));
|
||||
boost::thread thr2(thread_adapter<SM>(plain_shared,&s2,*pm2));
|
||||
boost::thread thr1(thread_adapter<SM>(plain_shared,&s1, mtx));
|
||||
boost::thread thr2(thread_adapter<SM>(plain_shared,&s2, mtx));
|
||||
|
||||
//Make sure they try to hold the sharable lock
|
||||
boost::thread::sleep(xsecs(1*BaseSeconds));
|
||||
|
||||
// We launch two writers, that should block until the readers end
|
||||
boost::thread tw1(thread_adapter<SM>(plain_exclusive,&e1,*pm3));
|
||||
boost::thread tw2(thread_adapter<SM>(plain_exclusive,&e2,*pm4));
|
||||
boost::thread tw1(thread_adapter<SM>(plain_exclusive,&e1, mtx));
|
||||
boost::thread tw2(thread_adapter<SM>(plain_exclusive,&e2, mtx));
|
||||
|
||||
thr2.join();
|
||||
thr1.join();
|
||||
@@ -201,20 +180,11 @@ void test_plain_sharable_mutex()
|
||||
}
|
||||
}
|
||||
|
||||
template<bool SameObject, typename SM>
|
||||
template<typename SM>
|
||||
void test_try_sharable_mutex()
|
||||
{
|
||||
SM m1, m2, m3;
|
||||
SM *pm1, *pm2, *pm3;
|
||||
SM mtx;
|
||||
|
||||
if(SameObject){
|
||||
pm1 = pm2 = pm3 = &m1;
|
||||
}
|
||||
else{
|
||||
pm1 = &m1;
|
||||
pm2 = &m2;
|
||||
pm3 = &m3;
|
||||
}
|
||||
data<SM> s1(1);
|
||||
data<SM> e1(2);
|
||||
data<SM> e2(3);
|
||||
@@ -225,15 +195,15 @@ void test_try_sharable_mutex()
|
||||
|
||||
// Writer one launches, holds the lock for 3*BaseSeconds seconds.
|
||||
|
||||
boost::thread tw1(thread_adapter<SM>(try_exclusive,&e1,*pm1));
|
||||
boost::thread tw1(thread_adapter<SM>(try_exclusive,&e1,mtx));
|
||||
|
||||
// Reader one launches, "clearly" after writer #1 holds the lock
|
||||
// and before it releases the lock.
|
||||
boost::thread::sleep(xsecs(1*BaseSeconds));
|
||||
boost::thread thr1(thread_adapter<SM>(try_shared,&s1,*pm2));
|
||||
boost::thread thr1(thread_adapter<SM>(try_shared,&s1,mtx));
|
||||
|
||||
// Writer two launches in the same timeframe.
|
||||
boost::thread tw2(thread_adapter<SM>(try_exclusive,&e2,*pm3));
|
||||
boost::thread tw2(thread_adapter<SM>(try_exclusive,&e2,mtx));
|
||||
|
||||
tw2.join();
|
||||
thr1.join();
|
||||
@@ -244,21 +214,10 @@ void test_try_sharable_mutex()
|
||||
BOOST_INTERPROCES_CHECK(e2.m_value == -1); // Try would return w/o waiting
|
||||
}
|
||||
|
||||
template<bool SameObject, typename SM>
|
||||
template<typename SM>
|
||||
void test_timed_sharable_mutex()
|
||||
{
|
||||
SM m1, m2, m3, m4;
|
||||
SM *pm1, *pm2, *pm3, *pm4;
|
||||
|
||||
if(SameObject){
|
||||
pm1 = pm2 = pm3 = pm4 = &m1;
|
||||
}
|
||||
else{
|
||||
pm1 = &m1;
|
||||
pm2 = &m2;
|
||||
pm3 = &m3;
|
||||
pm4 = &m4;
|
||||
}
|
||||
SM mtx;
|
||||
data<SM> s1(1,1*BaseSeconds);
|
||||
data<SM> s2(2,3*BaseSeconds);
|
||||
data<SM> e1(3,3*BaseSeconds);
|
||||
@@ -269,21 +228,21 @@ void test_timed_sharable_mutex()
|
||||
shared_val = 0;
|
||||
|
||||
// Writer one will hold the lock for 3*BaseSeconds seconds.
|
||||
boost::thread tw1(thread_adapter<SM>(timed_exclusive,&e1,*pm1));
|
||||
boost::thread tw1(thread_adapter<SM>(timed_exclusive,&e1,mtx));
|
||||
|
||||
boost::thread::sleep(xsecs(1*BaseSeconds));
|
||||
// Writer two will "clearly" try for the lock after the readers
|
||||
// have tried for it. Writer will wait up 1*BaseSeconds seconds for the lock.
|
||||
// This write will fail.
|
||||
boost::thread tw2(thread_adapter<SM>(timed_exclusive,&e2,*pm2));
|
||||
boost::thread tw2(thread_adapter<SM>(timed_exclusive,&e2,mtx));
|
||||
|
||||
// Readers one and two will "clearly" try for the lock after writer
|
||||
// one already holds it. 1st reader will wait 1*BaseSeconds seconds, and will fail
|
||||
// to get the lock. 2nd reader will wait 3*BaseSeconds seconds, and will get
|
||||
// the lock.
|
||||
|
||||
boost::thread thr1(thread_adapter<SM>(timed_shared,&s1,*pm3));
|
||||
boost::thread thr2(thread_adapter<SM>(timed_shared,&s2,*pm4));
|
||||
boost::thread thr1(thread_adapter<SM>(timed_shared,&s1,mtx));
|
||||
boost::thread thr2(thread_adapter<SM>(timed_shared,&s2,mtx));
|
||||
|
||||
tw1.join();
|
||||
thr1.join();
|
||||
@@ -296,17 +255,17 @@ void test_timed_sharable_mutex()
|
||||
BOOST_INTERPROCES_CHECK(e2.m_value == -1);
|
||||
}
|
||||
|
||||
template<bool SameObject, typename SM>
|
||||
template<typename SM>
|
||||
void test_all_sharable_mutex()
|
||||
{
|
||||
std::cout << "test_plain_sharable_mutex<" << SameObject << ", " << typeid(SM).name() << ">" << std::endl;
|
||||
test_plain_sharable_mutex<SameObject, SM>();
|
||||
std::cout << "test_plain_sharable_mutex<" << typeid(SM).name() << ">" << std::endl;
|
||||
test_plain_sharable_mutex<SM>();
|
||||
|
||||
std::cout << "test_try_sharable_mutex<" << SameObject << ", " << typeid(SM).name() << ">" << std::endl;
|
||||
test_try_sharable_mutex<SameObject, SM>();
|
||||
std::cout << "test_try_sharable_mutex<" << typeid(SM).name() << ">" << std::endl;
|
||||
test_try_sharable_mutex<SM>();
|
||||
|
||||
std::cout << "test_timed_sharable_mutex<" << SameObject << ", " << typeid(SM).name() << ">" << std::endl;
|
||||
test_timed_sharable_mutex<SameObject, SM>();
|
||||
std::cout << "test_timed_sharable_mutex<" << typeid(SM).name() << ">" << std::endl;
|
||||
test_timed_sharable_mutex<SM>();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -23,8 +23,8 @@ int main ()
|
||||
using namespace boost::interprocess;
|
||||
|
||||
test::test_all_lock<interprocess_upgradable_mutex>();
|
||||
test::test_all_mutex<true, interprocess_upgradable_mutex>();
|
||||
test::test_all_sharable_mutex<true, interprocess_upgradable_mutex>();
|
||||
test::test_all_mutex<interprocess_upgradable_mutex>();
|
||||
test::test_all_sharable_mutex<interprocess_upgradable_mutex>();
|
||||
|
||||
//Test lock transition
|
||||
{
|
||||
|
||||
@@ -63,7 +63,7 @@ inline bool in_range(const boost::posix_time::ptime& xt, int secs=1)
|
||||
boost::xtime xsecs(int secs)
|
||||
{
|
||||
boost::xtime ret;
|
||||
boost::xtime_get(&ret, boost::TIME_UTC_);
|
||||
boost::xtime_get(&ret, boost::TIME_UTC);
|
||||
ret.sec += secs;
|
||||
return ret;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user