* Updated documentation to show rvalue-references funcions instead of emulation functions.

*  More non-copyable classes are now movable.
*  Move-constructor and assignments now leave moved object in default-constructed state
   instead of just swapping contents.
*  Several bugfixes (#2391, #2431, #1390, #2570, #2528).

[SVN r50258]
This commit is contained in:
Ion Gaztañaga
2008-12-13 13:47:00 +00:00
parent c1a6867856
commit 8f145becf5
15 changed files with 133 additions and 17 deletions

View File

@@ -1,5 +1,5 @@
[/
/ Copyright (c) 2007 Ion Gaztanaga
/ Copyright (c) 2007-2008 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)
@@ -8,7 +8,7 @@
[library Boost.Interprocess
[quickbook 1.3]
[authors [Gaztañaga, Ion]]
[copyright 2005- 2007 Ion Gaztañaga]
[copyright 2005- 2008 Ion Gaztañaga]
[id interprocess]
[dirname interprocess]
[purpose Interprocess communication utilities]
@@ -1516,11 +1516,11 @@ In the previous example, a mutex is used to ['lock] but we can't use it to
can do two things:
* [*wait]: The thread is blocked until some other thread notifies that it can
continue because the condition that lead to waiting has disapeared.
continue because the condition that lead to waiting has disappeared.
* [*notify]: The thread sends a signal to one blocked thread or to all blocked
threads to tell them that they the condition that provoked their wait has
disapeared.
disappeared.
Waiting in a condition variable is always associated with a mutex.
The mutex must be locked prior to waiting on the condition. When waiting
@@ -2178,7 +2178,7 @@ These operations can be managed more effectively using [*lock transfer operation
A lock transfer operations explicitly indicates that a mutex owned by a lock is
transferred to another lock executing atomic unlocking plus locking operations.
[section:lock_trnasfer_simple_transfer Simple Lock Transfer]
[section:lock_transfer_simple_transfer Simple Lock Transfer]
Imagine that a thread modifies some data in the beginning but after that, it has to
just read it in a long time. The code can acquire the exclusive lock, modify the data
@@ -3668,10 +3668,10 @@ corrupted.
As mentioned, the managed segment stores the information about named and unique
objects in two indexes. Depending on the type of those indexes, the index must
reallocate some auxiliary structures when new named or unique allocations are made.
For some indexes, if the user knows how many maned or unique objects is going to
create it's possible to preallocate some structures to obtain much better
performance (if the index is an ordered vector it can preallocate memory to avoid
reallocations, if the index is a hash structure it can preallocate the bucket array...).
For some indexes, if the user knows how many named or unique objects are going to
be created it's possible to preallocate some structures to obtain much better
performance. (If the index is an ordered vector it can preallocate memory to avoid
reallocations. If the index is a hash structure it can preallocate the bucket array).
The following functions reserve memory to make the subsequent allocation of
named or unique objects more efficient. These functions are only useful for
@@ -5671,7 +5671,7 @@ including creating containers of such objects:
[section:basic_guidelines Basic guidelines]
When building [*Boost.Interprocess] architecture, I took some basic guidelines that can be
resumed in these points:
summarized by these points:
* [*Boost.Interprocess] should be portable at least in UNIX and Windows systems. That
means unifying not only interfaces but also behaviour. This is why
@@ -6541,6 +6541,16 @@ warranty.
[section:release_notes Release Notes]
[section:release_notes_boost_1_38_00 Boost 1.38 Release]
* Updated documentation to show rvalue-references funcions instead of emulation functions.
* More non-copyable classes are now movable.
* Move-constructor and assignments now leave moved object in default-constructed state
instead of just swapping contents.
* Several bugfixes (#2391, #2431, #1390, #2570, #2528).
[endsect]
[section:release_notes_boost_1_37_00 Boost 1.37 Release]
* Containers can be used now in recursive types.

View File

@@ -22,7 +22,6 @@ rule test_all
for local fileb in [ glob *.cpp ]
{
all_rules += [ link $(fileb) /boost/thread//boost_thread
# all_rules += [ compile $(fileb)
: # additional args
: # test-files
: # requirements

View File

@@ -52,3 +52,19 @@
->find a way to pass security attributes to shared memory
->Explain in docs that shared memory can't be used between different users in windows
-> Implement vector with memcpy/memmove for trivially copyable types.
-> Update all swap() calls to work with rvalues in all classes
-> correct swap overloads for the documentation so that just appears a single rvalue swap
-> correct splice()/merg overloads for the documentation so that just appears a single rvalue splice
-> flat_xxx constructors are not documented
-> operator >> eta antzekoek moved_value behar dute
-> make file_lock movable
-> Add cmath workaround for Boost < 1.37

View File

@@ -312,7 +312,7 @@
</Filter>
</Filter>
<Filter
Name="Managed Memory Classes"
Name="Public interface"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
<File

View File

@@ -123,6 +123,17 @@ bool do_test()
{
deque<recursive_deque> recursive_deque_deque;
}
{
//Now test move semantics
deque<recursive_deque> original;
deque<recursive_deque> move_ctor(detail::move_impl(original));
deque<recursive_deque> move_assign;
move_assign = detail::move_impl(move_ctor);
move_assign.swap(detail::move_impl(original));
move_assign.swap(original);
}
//Customize managed_shared_memory class
typedef basic_managed_shared_memory
<char,

View File

@@ -49,7 +49,16 @@ int main ()
{
scoped_lock<file_lock> sl(flock, test::delay(1));
}
}
}/*
{
//Now test move semantics
file_lock mapping(test::get_process_id_name());
file_lock move_ctor(detail::move_impl(mapping));
file_lock move_assign;
move_assign = detail::move_impl(move_ctor);
mapping.swap(detail::move_impl(move_assign));
mapping.swap(move_assign);
}*/
//test::test_all_lock<file_lock_lock_test_wrapper>();
//test::test_all_mutex<false, file_lock_lock_test_wrapper>();

View File

@@ -128,6 +128,8 @@ int main ()
file_mapping move_ctor(detail::move_impl(mapping));
file_mapping move_assign;
move_assign = detail::move_impl(move_ctor);
mapping.swap(detail::move_impl(move_assign));
mapping.swap(move_assign);
}
}
catch(std::exception &exc){

View File

@@ -51,6 +51,15 @@ void recursive_list_test()//Test for recursive types
int main ()
{
recursive_list_test();
{
//Now test move semantics
list<recursive_list> original;
list<recursive_list> move_ctor(detail::move_impl(original));
list<recursive_list> move_assign;
move_assign = detail::move_impl(move_ctor);
move_assign.swap(detail::move_impl(original));
move_assign.swap(original);
}
if(test::list_test<managed_shared_memory, MyList, true>())
return 1;

View File

@@ -206,6 +206,8 @@ int main ()
managed_mapped_file move_ctor(detail::move_impl(original));
managed_mapped_file move_assign;
move_assign = detail::move_impl(move_ctor);
move_assign.swap(detail::move_impl(original));
move_assign.swap(original);
}
}

View File

@@ -202,6 +202,8 @@ int main ()
managed_shared_memory move_ctor(detail::move_impl(original));
managed_shared_memory move_assign;
move_assign = detail::move_impl(move_ctor);
move_assign.swap(detail::move_impl(original));
move_assign.swap(original);
}
}

View File

@@ -35,7 +35,7 @@ class movable_int
{}
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
movable_int(const detail::moved_object<movable_int> &mmi)
movable_int(detail::moved_object<movable_int> mmi)
: m_int(mmi.get().m_int)
{ mmi.get().m_int = 0; }
#else
@@ -45,7 +45,7 @@ class movable_int
#endif
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
movable_int & operator= (const detail::moved_object<movable_int> &mmi)
movable_int & operator= (detail::moved_object<movable_int> mmi)
{ this->m_int = mmi.get().m_int; mmi.get().m_int = 0; return *this; }
#else
movable_int & operator= (movable_int &&mmi)
@@ -109,7 +109,7 @@ class movable_and_copyable_int
{ this->m_int = mi.m_int; return *this; }
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
movable_and_copyable_int(const detail::moved_object<movable_and_copyable_int> &mmi)
movable_and_copyable_int(detail::moved_object<movable_and_copyable_int> mmi)
: m_int(mmi.get().m_int)
{ mmi.get().m_int = 0; }
#else
@@ -119,7 +119,7 @@ class movable_and_copyable_int
#endif
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
movable_and_copyable_int & operator= (const detail::moved_object<movable_and_copyable_int> &mmi)
movable_and_copyable_int & operator= (detail::moved_object<movable_and_copyable_int> mmi)
{ this->m_int = mmi.get().m_int; mmi.get().m_int = 0; return *this; }
#else
movable_and_copyable_int & operator= (movable_and_copyable_int &&mmi)

View File

@@ -51,6 +51,15 @@ void recursive_slist_test()//Test for recursive types
int main ()
{
recursive_slist_test();
{
//Now test move semantics
slist<recursive_slist> original;
slist<recursive_slist> move_ctor(detail::move_impl(original));
slist<recursive_slist> move_assign;
move_assign = detail::move_impl(move_ctor);
move_assign.swap(detail::move_impl(original));
move_assign.swap(original);
}
if(test::list_test<managed_shared_memory, MyList, false>())
return 1;

View File

@@ -158,6 +158,18 @@ public:
{ return a.id_ < b.id_; }
};
template<class C>
void test_move_semantics()
{
//Now test move semantics
C original;
C move_ctor(detail::move_impl(original));
C move_assign;
move_assign = detail::move_impl(move_ctor);
move_assign.swap(detail::move_impl(original));
move_assign.swap(original);
}
int main ()
{
//Recursive container instantiation
@@ -167,6 +179,13 @@ int main ()
map<recursive_map, recursive_map> map_;
multimap<recursive_multimap, recursive_multimap> multimap_;
}
//Now test move semantics
{
test_move_semantics<set<recursive_set> >();
test_move_semantics<multiset<recursive_multiset> >();
test_move_semantics<map<recursive_map, recursive_map> >();
test_move_semantics<multimap<recursive_multimap, recursive_multimap> >();
}
using namespace boost::interprocess::detail;

View File

@@ -56,6 +56,25 @@ int main ()
const int memsize = 65536/size_aligner*size_aligner;
static detail::max_align static_buffer[memsize/size_aligner];
{
//Now test move semantics
managed_heap_memory original(memsize);
managed_heap_memory move_ctor(detail::move_impl(original));
managed_heap_memory move_assign;
move_assign = detail::move_impl(move_ctor);
original.swap(detail::move_impl(move_assign));
original.swap(move_assign);
}
{
//Now test move semantics
managed_external_buffer original(create_only, static_buffer, memsize);
managed_external_buffer move_ctor(detail::move_impl(original));
managed_external_buffer move_assign;
move_assign = detail::move_impl(move_ctor);
original.swap(detail::move_impl(move_assign));
original.swap(move_assign);
}
//Named new capable user mem allocator
wmanaged_external_buffer user_buffer(create_only, static_buffer, memsize);

View File

@@ -91,6 +91,15 @@ void recursive_vector_test()//Test for recursive types
int main()
{
recursive_vector_test();
{
//Now test move semantics
vector<recursive_vector> original;
vector<recursive_vector> move_ctor(detail::move_impl(original));
vector<recursive_vector> move_assign;
move_assign = detail::move_impl(move_ctor);
move_assign.swap(detail::move_impl(original));
move_assign.swap(original);
}
typedef allocator<int, managed_shared_memory::segment_manager> ShmemAllocator;
typedef vector<int, ShmemAllocator> MyVector;