////////////////////////////////////////////////////////////////////////////// // // (C) Copyright Peter Dimov 2002-2005, 2007. // (C) Copyright Ion Gaztanaga 2006-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 #include #include #include #include #include #include #include #include #include #include #include #include #include "get_process_id_name.hpp" #include #include using namespace boost::interprocess; class base_class { public: virtual ~base_class() {} }; class derived_class : public base_class { public: virtual ~derived_class() {} }; int simple_test() { typedef managed_shared_memory::segment_manager segment_mngr_t; typedef allocator base_class_allocator; typedef deleter base_deleter_t; typedef shared_ptr base_shared_ptr; std::string process_name; test::get_process_id_name(process_name); shared_memory_object::remove(process_name.c_str()); { managed_shared_memory shmem(create_only, process_name.c_str(), 10000); { base_shared_ptr s_ptr(base_shared_ptr::pointer(0), base_class_allocator(shmem.get_segment_manager()), base_deleter_t(shmem.get_segment_manager())); base_shared_ptr s_ptr2(shmem.construct("base_class")(), base_class_allocator(shmem.get_segment_manager()), base_deleter_t(shmem.get_segment_manager())); base_shared_ptr s_ptr3(offset_ptr(shmem.construct("derived_class")()), base_class_allocator(shmem.get_segment_manager()), base_deleter_t(shmem.get_segment_manager())); if(s_ptr3.get_deleter() == 0){ return 1; } //if(s_ptr3.get_allocator() == 0){ //return 1; //} base_shared_ptr s_ptr_empty; if(s_ptr_empty.get_deleter() != 0){ return 1; } //if(s_ptr_empty.get_allocator() != 0){ //return 1; //} } } shared_memory_object::remove(process_name.c_str()); return 0; } int string_shared_ptr_vector_insertion_test() { typedef managed_shared_memory::segment_manager segment_mngr_t; //Allocator of chars typedef allocator char_allocator_t; //A shared memory string class typedef basic_string, char_allocator_t> string_t; //A shared memory string allocator typedef allocator string_allocator_t; //A deleter for shared_ptr<> that erases a shared memory string typedef deleter string_deleter_t; //A shared pointer that points to a shared memory string and its instantiation typedef shared_ptr string_shared_ptr_t; //An allocator for shared pointers to a string in shared memory typedef allocator string_shared_ptr_allocator_t; //A weak pointer that points to a shared memory string and its instantiation typedef weak_ptr string_weak_ptr_t; //An allocator for weak pointers to a string in shared memory typedef allocator string_weak_ptr_allocator_t; //A vector of shared pointers to strings (all in shared memory) and its instantiation typedef vector string_shared_ptr_vector_t; //A vector of weak pointers to strings (all in shared memory) and its instantiation typedef vector string_weak_ptr_vector_t; std::string process_name; test::get_process_id_name(process_name); //A shared memory managed memory classes shared_memory_object::remove(process_name.c_str()); { managed_shared_memory shmem(create_only, process_name.c_str(), 20000); { const int NumElements = 100; //Construct the allocator of strings string_allocator_t string_allocator(shmem.get_segment_manager()); //Construct the allocator of a shared_ptr to string string_shared_ptr_allocator_t string_shared_ptr_allocator(shmem.get_segment_manager()); //Construct the allocator of a shared_ptr to string string_weak_ptr_allocator_t string_weak_ptr_allocator(shmem.get_segment_manager()); //This is a string deleter using destroy_ptr() function of the managed_shared_memory string_deleter_t deleter(shmem.get_segment_manager()); //Create a string in shared memory, to avoid leaks with exceptions use //scoped ptr until we store this pointer in the shared ptr scoped_ptr scoped_string (shmem.construct(anonymous_instance)(string_allocator), deleter); //Now construct a shared pointer to a string string_shared_ptr_t string_shared_ptr (scoped_string.get(), string_shared_ptr_allocator, deleter); //Check use count is just one if(!string_shared_ptr.unique()){ return 1; } //We don't need the scoped_ptr anonymous since the raw pointer is in the shared ptr scoped_string.release(); //Now fill a shared memory vector of shared_ptrs to a string string_shared_ptr_vector_t my_sharedptr_vector(string_shared_ptr_allocator); my_sharedptr_vector.insert(my_sharedptr_vector.begin(), NumElements, string_shared_ptr); //Insert in the middle to test movability my_sharedptr_vector.insert(my_sharedptr_vector.begin() + my_sharedptr_vector.size()/2, NumElements, string_shared_ptr); //Now check the shared count is the objects contained in the //vector plus string_shared_ptr if(string_shared_ptr.use_count() != static_cast(my_sharedptr_vector.size()+1)){ return 1; } //Now create a weak ptr from the shared_ptr string_weak_ptr_t string_weak_ptr (string_shared_ptr); //Use count should remain the same if(string_weak_ptr.use_count() != static_cast(my_sharedptr_vector.size()+1)){ return 1; } //Now reset the local shared_ptr and check use count string_shared_ptr.reset(); if(string_weak_ptr.use_count() != static_cast(my_sharedptr_vector.size())){ return 1; } //Now reset the local shared_ptr's use count should be zero if(string_shared_ptr.use_count() != 0){ return 1; } //Now recreate the shared ptr from the weak ptr //and recheck use count string_shared_ptr = string_shared_ptr_t(string_weak_ptr); if(string_shared_ptr.use_count() != static_cast(my_sharedptr_vector.size()+1)){ return 1; } //Now fill a vector of weak_ptr-s string_weak_ptr_vector_t my_weakptr_vector(string_weak_ptr_allocator); my_weakptr_vector.insert(my_weakptr_vector.begin(), NumElements, string_weak_ptr); //The shared count should remain the same if(string_shared_ptr.use_count() != static_cast(my_sharedptr_vector.size()+1)){ return 1; } //So weak pointers should be fine string_weak_ptr_vector_t::iterator beg = my_weakptr_vector.begin(), end = my_weakptr_vector.end(); for(;beg != end; ++beg){ if(beg->expired()){ return 1; } //The shared pointer constructed from weak ptr should //be the same as the original, since all weak pointer //point the the same object if(string_shared_ptr_t(*beg) != string_shared_ptr){ return 1; } } //Now destroy all the shared ptr-s of the shared ptr vector my_sharedptr_vector.clear(); //The only alive shared ptr should be the local one if(string_shared_ptr.use_count() != 1){ return 1; } //Now we invalidate the last alive shared_ptr string_shared_ptr.reset(); //Now all weak pointers should have expired beg = my_weakptr_vector.begin(); end = my_weakptr_vector.end(); for(;beg != end; ++beg){ if(!beg->expired()){ return 1; } bool success = false; //Now this should throw try{ string_shared_ptr_t dummy(*beg); //We should never reach here return 1; } catch(const boost::interprocess::bad_weak_ptr &){ success = true; } if(!success){ return 1; } } //Clear weak ptr vector my_weakptr_vector.clear(); //Now lock returned shared ptr should return null if(string_weak_ptr.lock().get()){ return 1; } //Reset weak_ptr string_weak_ptr.reset(); } } shared_memory_object::remove(process_name.c_str()); return 0; } // // This part is taken from shared_ptr_basic_test.cpp // // Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd. // Copyright (c) 2006 Ion Gaztanaga // // 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) // static int cnt = 0; struct X { X(){ ++cnt; } // virtual destructor deliberately omitted virtual ~X(){ --cnt; } virtual int id() const { return 1; } private: X(X const &); X & operator= (X const &); }; struct Y: public X { Y(){ ++cnt; } virtual ~Y(){ --cnt; } virtual int id() const { return 2; } private: Y(Y const &); Y & operator= (Y const &); }; int * get_object() { ++cnt; return &cnt; } void release_object(int * p) { BOOST_TEST(p == &cnt); --cnt; } template void test_is_X(shared_ptr const & p) { BOOST_TEST(p->id() == 1); BOOST_TEST((*p).id() == 1); } template void test_is_X(weak_ptr const & p) { BOOST_TEST(p.get() != 0); BOOST_TEST(p.get()->id() == 1); } template void test_is_Y(shared_ptr const & p) { BOOST_TEST(p->id() == 2); BOOST_TEST((*p).id() == 2); } template void test_is_Y(weak_ptr const & p) { shared_ptr q = p.lock(); BOOST_TEST(q.get() != 0); BOOST_TEST(q->id() == 2); } template void test_eq(T const & a, T2 const & b) { BOOST_TEST(a == b); BOOST_TEST(!(a != b)); BOOST_TEST(!(a < b)); BOOST_TEST(!(b < a)); } template void test_ne(T const & a, T2 const & b) { BOOST_TEST(!(a == b)); BOOST_TEST(a != b); BOOST_TEST(a < b || b < a); BOOST_TEST(!(a < b && b < a)); } template void test_shared(weak_ptr const & a, weak_ptr const & b) { BOOST_TEST(!(a < b)); BOOST_TEST(!(b < a)); } template void test_nonshared(weak_ptr const & a, weak_ptr const & b) { BOOST_TEST(a < b || b < a); BOOST_TEST(!(a < b && b < a)); } template void test_eq2(T const & a, U const & b) { BOOST_TEST(a == b); BOOST_TEST(!(a != b)); } template void test_ne2(T const & a, U const & b) { BOOST_TEST(!(a == b)); BOOST_TEST(a != b); } template void test_is_zero(shared_ptr const & p) { BOOST_TEST(!p); BOOST_TEST(p.get() == 0); } template void test_is_nonzero(shared_ptr const & p) { // p? true: false is used to test p in a boolean context. // BOOST_TEST(p) is not guaranteed to test the conversion, // as the macro might test !!p instead. BOOST_TEST(p? true: false); BOOST_TEST(p.get() != 0); } int basic_shared_ptr_test() { typedef managed_shared_memory::segment_manager segment_mngr_t; typedef allocator v_allocator_t; typedef deleter x_deleter_t; typedef deleter y_deleter_t; typedef shared_ptr x_shared_ptr; typedef shared_ptr y_shared_ptr; typedef weak_ptr x_weak_ptr; typedef weak_ptr y_weak_ptr; std::string process_name; test::get_process_id_name(process_name); shared_memory_object::remove(process_name.c_str()); { managed_shared_memory shmem(create_only, process_name.c_str(), 10000); { v_allocator_t v_allocator (shmem.get_segment_manager()); x_deleter_t x_deleter (shmem.get_segment_manager()); y_deleter_t y_deleter (shmem.get_segment_manager()); y_shared_ptr p (shmem.construct(anonymous_instance)(), v_allocator, y_deleter); x_shared_ptr p2(shmem.construct(anonymous_instance)(), v_allocator, x_deleter); test_is_nonzero(p); test_is_nonzero(p2); test_is_Y(p); test_is_X(p2); test_ne(p, p2); { shared_ptr q(p); test_eq(p, q); } y_shared_ptr p3 (dynamic_pointer_cast(p)); shared_ptr p4 (dynamic_pointer_cast(p2)); test_is_nonzero(p3); test_is_zero(p4); BOOST_TEST(p.use_count() == 2); BOOST_TEST(p2.use_count() == 1); BOOST_TEST(p3.use_count() == 2); test_is_Y(p3); test_eq2(p, p3); test_ne2(p2, p4); shared_ptr p5(p); test_is_nonzero(p5); test_eq2(p, p5); BOOST_TEST(p5.use_count() == 3); x_weak_ptr wp1(p2); BOOST_TEST(!wp1.expired()); BOOST_TEST(wp1.use_count() != 0); p.reset(); p2.reset(); p3.reset(); p4.reset(); test_is_zero(p); test_is_zero(p2); test_is_zero(p3); test_is_zero(p4); BOOST_TEST(p5.use_count() == 1); BOOST_TEST(wp1.expired()); BOOST_TEST(wp1.use_count() == 0); try{ x_shared_ptr sp1(wp1); BOOST_ERROR("shared_ptr sp1(wp1) failed to throw"); } catch(boost::interprocess::bad_weak_ptr const &) {} test_is_zero(wp1.lock()); weak_ptr wp2 = static_pointer_cast(p5); BOOST_TEST(wp2.use_count() == 1); test_is_Y(wp2); test_nonshared(wp1, wp2); // Scoped to not affect the subsequent use_count() tests. { shared_ptr sp2(wp2); test_is_nonzero(wp2.lock()); } y_weak_ptr wp3 = dynamic_pointer_cast(wp2.lock()); BOOST_TEST(wp3.use_count() == 1); test_shared(wp2, wp3); weak_ptr wp4(wp3); BOOST_TEST(wp4.use_count() == 1); test_shared(wp2, wp4); wp1 = p2; test_is_zero(wp1.lock()); wp1 = p4; x_weak_ptr wp5; bool b1 = wp1 < wp5; bool b2 = wp5 < wp1; y_shared_ptr p6 = static_pointer_cast(p5); p5.reset(); p6.reset(); BOOST_TEST(wp1.use_count() == 0); BOOST_TEST(wp2.use_count() == 0); BOOST_TEST(wp3.use_count() == 0); // Test operator< stability for std::set< weak_ptr<> > // Thanks to Joe Gottman for pointing this out BOOST_TEST(b1 == (wp1 < wp5)); BOOST_TEST(b2 == (wp5 < wp1)); } BOOST_TEST(cnt == 0); } shared_memory_object::remove(process_name.c_str()); return boost::report_errors(); } struct alias_tester { int v_; explicit alias_tester( int v ): v_( v ) { } ~alias_tester() { v_ = 0; } }; void test_alias() { typedef managed_shared_memory::segment_manager segment_mngr_t; typedef allocator v_allocator_t; typedef deleter int_deleter_t; typedef shared_ptr int_shared_ptr; typedef shared_ptr const_int_shared_ptr; std::string process_name; test::get_process_id_name(process_name); shared_memory_object::remove(process_name.c_str()); { managed_shared_memory shmem(create_only, process_name.c_str(), 10000); { int m = 0; int_shared_ptr p; int_shared_ptr p2( p, &m ); BOOST_TEST( ipcdetail::to_raw_pointer(p2.get()) == &m ); BOOST_TEST( p2? true: false ); BOOST_TEST( !!p2 ); BOOST_TEST( p2.use_count() == p.use_count() ); BOOST_TEST( !( p < p2 ) && !( p2 < p ) ); p2.reset( p, static_cast(0) ); BOOST_TEST( p2.get() == 0 ); BOOST_TEST( p2? false: true ); BOOST_TEST( !p2 ); BOOST_TEST( p2.use_count() == p.use_count() ); BOOST_TEST( !( p < p2 ) && !( p2 < p ) ); } { int m = 0; int_shared_ptr p(make_managed_shared_ptr (shmem.construct(anonymous_instance)(), shmem)); const_int_shared_ptr p2( p, &m ); BOOST_TEST( ipcdetail::to_raw_pointer(p2.get()) == &m ); BOOST_TEST( p2? true: false ); BOOST_TEST( !!p2 ); BOOST_TEST( p2.use_count() == p.use_count() ); BOOST_TEST( !( p < p2 ) && !( p2 < p ) ); int_shared_ptr p_nothrow(make_managed_shared_ptr (shmem.construct(anonymous_instance)(), shmem, std::nothrow)); } } shared_memory_object::remove(process_name.c_str()); } int main() { if(0 != simple_test()) return 1; if(0 != string_shared_ptr_vector_insertion_test()) return 1; if(0 != basic_shared_ptr_test()) return 1; test_alias(); } #include