Changes for Boost.1.39

[SVN r51964]
This commit is contained in:
Ion Gaztañaga
2009-03-24 21:52:06 +00:00
parent 814c51a803
commit 3d0fcd68e3
274 changed files with 23335 additions and 20691 deletions

View File

@@ -25,8 +25,15 @@ doxygen autodoc
<doxygen:param>EXTRACT_ALL=NO
<doxygen:param>HIDE_UNDOC_MEMBERS=YES
<doxygen:param>EXTRACT_PRIVATE=NO
<doxygen:param>ENABLE_PREPROCESSING=YES
<doxygen:param>EXPAND_ONLY_PREDEF=YES
<doxygen:param>PREDEFINED=BOOST_INTERPROCESS_DOXYGEN_INVOKED
<doxygen:param>MACRO_EXPANSION=YES
<doxygen:param>"PREDEFINED=\"BOOST_INTERPROCESS_DOXYGEN_INVOKED\" \\
\"BOOST_INTERPROCESS_ENABLE_MOVE_EMULATION(a)= \" \\
\"BOOST_INTERPROCESS_RV_REF(a)=a &&\" \\
\"BOOST_INTERPROCESS_RV_REF_2_TEMPL_ARGS(a)=a &&\" \\
\"BOOST_INTERPROCESS_RV_REF_3_TEMPL_ARGS(a)=a &&\" \\
\"BOOST_INTERPROCESS_FWD_REF(a)=a &&\""
<xsl:param>"boost.doxygen.reftitle=Boost.Interprocess Reference"
;

View File

@@ -94,13 +94,8 @@ You can just allocate a portion of a shared memory segment, copy the
message to that buffer, send the offset of that portion of shared
memory to another process, and you are done. Let's see the example:
[import ../example/doc_ipc_messageA.cpp]
[doc_ipc_messageA]
In receiver process one just could write the following lines:
[import ../example/doc_ipc_messageB.cpp]
[doc_ipc_messageB]
[import ../example/doc_ipc_message.cpp]
[doc_ipc_message]
[endsect]
@@ -108,15 +103,10 @@ In receiver process one just could write the following lines:
You want to create objects in a shared memory segment, giving a string name to them so that
any other process can find, use and delete them from the segment when the objects are not
needed anymore. Just write in one process:
needed anymore. Example:
[import ../example/doc_named_allocA.cpp]
[doc_named_allocA]
In other process execute the following:
[import ../example/doc_named_allocB.cpp]
[doc_named_allocB]
[import ../example/doc_named_alloc.cpp]
[doc_named_alloc]
[endsect]
@@ -148,16 +138,19 @@ list, map, so you can avoid these manual data structures just like with standard
mapped files. For example, we can construct STL-like containers in shared memory.
To do this, we just need to create a special (managed) shared memory segment,
declare a [*Boost.Interprocess] allocator and construct the vector in shared memory
just if it was any other object. Just execute this first process:
just if it was any other object.
[import ../example/doc_contA.cpp]
[doc_contA]
The class that allows this complex structures in shared memory is called
[classref boost::interprocess::managed_shared_memory] and it's easy to use.
Just execute this example without arguments:
After this process is executed we can search the constructed vector and use it with
STL algorithms:
[import ../example/doc_spawn_vector.cpp]
[doc_spawn_vector]
[import ../example/doc_contB.cpp]
[doc_contB]
The parent process will create an special shared memory class that allows easy construction
of many complex data structures associated with a name. The parent process executes the same
program with an additional argument so the child process opens the shared memory and uses
the vector and erases it.
[endsect]
@@ -498,16 +491,11 @@ For more details regarding `mapped_region` see the
Let's see a simple example of shared memory use. A server process creates a
shared memory object, maps it and initializes all the bytes to a value. After that,
a client process opens the shared memory, maps it, and checks
that the data is correctly initialized. This is the server process:
that the data is correctly initialized:
[import ../example/doc_shared_memory.cpp]
[doc_shared_memory]
Now the client process:
[import ../example/doc_shared_memory2.cpp]
[doc_shared_memory2]
[endsect]
[section:emulation Emulation for systems without shared memory objects]
@@ -521,12 +509,11 @@ POSIX:
defined by POSIX (see [link interprocess.sharedmemorybetweenprocesses.sharedmemory.windows_shared_memory
Native windows shared memory] section for more information).
* Some UNIX systems don't support shared memory objects at all. MacOS is
one of these operating systems.
* Some UNIX systems don't fully support POSIX shared memory objects at all.
In those platforms, shared memory is emulated with mapped files created
in the temporary files directory. Because of this emulation, shared memory
has filesystem lifetime in those systems.
has filesystem lifetime in some of those systems.
[endsect]
@@ -554,12 +541,9 @@ the name will subsequently cause the creation of a
shared memory object of this name exists (that is, trying to open an object
with that name will fail and an object of the same name can be created again).
In Windows operating systems, the function fails if the object is being used,
so a programmer can't consider the UNIX behavior as the portable behavior:
`shared_memory_object::remove` [*can] fail if the shared memory is still in use,
but this does not mean that it [*will] fail if it's in use. Just the same
behavior as the standard C (stdio.h) `int remove(const char *path)` function.
In Windows operating systems, current version supports an usually acceptable emulation
of the UNIX unlink behaviour: the file is randomly renamed and marked as to be deleted when
the last open handle is closed.
[endsect]
@@ -586,7 +570,6 @@ be used so that `region` is used to communicate two related processes.
[endsect]
[section:windows_shared_memory Native windows shared memory]
Windows operating system also offers shared memory, but the lifetime of this
@@ -624,20 +607,13 @@ shared memory object, maps it and initializes all the bytes to a value. After th
a client process opens the shared memory, maps it, and checks
that the data is correctly initialized. Take in care that [*if the server exits before
the client connects to the shared memory the client connection will fail], because
the shared memory segment is destroyed when no processes are attached to the memory.
the shared memory segment is destroyed when no proces is attached to the memory.
This is the server process:
[import ../example/doc_windows_shared_memory.cpp]
[doc_windows_shared_memory]
Now, before destroying the
[classref boost::interprocess::windows_shared_memory windows_shared memory]
object, launch the client process:
[import ../example/doc_windows_shared_memory2.cpp]
[doc_windows_shared_memory2]
As we can see, native windows shared memory needs synchronization to make sure
that the shared memory won't be destroyed before the client is launched.
@@ -801,16 +777,11 @@ Let's reproduce the same example described in the shared memory section, using
memory mapped files. A server process creates a shared
memory segment, maps it and initializes all the bytes to a value. After that,
a client process opens the shared memory, maps it, and checks
that the data is correctly initialized. This is the server process:
that the data is correctly initialized::
[import ../example/doc_file_mapping.cpp]
[doc_file_mapping]
Now the client process:
[import ../example/doc_file_mapping2.cpp]
[doc_file_mapping2]
[endsect]
[endsect]
@@ -1478,17 +1449,17 @@ will write a flag when ends writing the traces
This is the process main process. Creates the shared memory, constructs
the cyclic buffer and start writing traces:
[import ../example/doc_anonymous_mutexA.cpp]
[import ../example/comp_doc_anonymous_mutexA.cpp]
[doc_anonymous_mutexA]
The second process opens the shared memory, obtains access to the cyclic buffer
and starts writing traces:
[import ../example/doc_anonymous_mutexB.cpp]
[import ../example/comp_doc_anonymous_mutexB.cpp]
[doc_anonymous_mutexB]
As we can see, a mutex is useful to protect data but not to notify to another process
an event. For this, we need a condition variable, as we will see in the next section.
As we can see, a mutex is useful to protect data but not to notify an event to another
process. For this, we need a condition variable, as we will see in the next section.
[endsect]
@@ -1583,13 +1554,13 @@ This is the process main process. Creates the shared memory, places there
the buffer and starts writing messages one by one until it writes "last message"
to indicate that there are no more messages to print:
[import ../example/doc_anonymous_conditionA.cpp]
[import ../example/comp_doc_anonymous_conditionA.cpp]
[doc_anonymous_conditionA]
The second process opens the shared memory and prints each message
until the "last message" message is received:
[import ../example/doc_anonymous_conditionB.cpp]
[import ../example/comp_doc_anonymous_conditionB.cpp]
[doc_anonymous_conditionB]
With condition variables, a process can block if it can't continue the work,
@@ -1665,13 +1636,13 @@ This is the process main process. Creates the shared memory, places there
the integer array and starts integers one by one, blocking if the array
is full:
[import ../example/doc_anonymous_semaphoreA.cpp]
[import ../example/comp_doc_anonymous_semaphoreA.cpp]
[doc_anonymous_semaphoreA]
The second process opens the shared memory and copies the received integers
to it's own buffer:
[import ../example/doc_anonymous_semaphoreB.cpp]
[import ../example/comp_doc_anonymous_semaphoreB.cpp]
[doc_anonymous_semaphoreB]
The same interprocess communication can be achieved with a condition variables
@@ -2152,11 +2123,11 @@ more features and operations, see their reference for more informations
[/section:upgradable_mutexes_example Anonymous Upgradable Mutex Example]
[/import ../example/doc_anonymous_upgradable_mutexA.cpp]
[/import ../example/comp_doc_anonymous_upgradable_mutexA.cpp]
[/doc_anonymous_upgradable_mutexA]
[/import ../example/doc_anonymous_upgradable_mutexB.cpp]
[/import ../example/comp_doc_anonymous_upgradable_mutexB.cpp]
[/doc_anonymous_upgradable_mutexB]
[/endsect]
@@ -2722,7 +2693,7 @@ objects are created pointing to the same file, no synchronization is guaranteed.
POSIX, when two file descriptors are used to lock a file if a descriptor is closed,
all file locks set by the calling process are cleared.
To sum up, if you plan to use file locking in your processes, use the following
To sum up, if you plan to use portable file locking in your processes, use the following
restrictions:
* [*For each file, use a single `file_lock` object per process.]
@@ -2867,12 +2838,12 @@ In the following example, the first process creates the message queue, and write
an array of integers on it. The other process just reads the array and checks that
the sequence number is correct. This is the first process:
[import ../example/doc_message_queueA.cpp]
[import ../example/comp_doc_message_queueA.cpp]
[doc_message_queueA]
This is the second process:
[import ../example/doc_message_queueB.cpp]
[import ../example/comp_doc_message_queueB.cpp]
[doc_message_queueB]
To know more about this class and all its operations, please see the
@@ -3246,11 +3217,16 @@ To use a managed mapped file, you must include the following header:
managed_mapped_file mfile (open_or_create, "MyMappedFile", //Mapped file name 65536); //Mapped file size
When the `managed_mapped_file` object is destroyed, the file is
automatically unmapped, and all the resources are freed. To remove
the file from the filesystem you can use standard C `std::remove`
or [*Boost.Filesystem]'s `remove()` functions. File removing might fail
the file from the filesystem you could use standard C `std::remove`
or [*Boost.Filesystem]'s `remove()` functions, but file removing might fail
if any process still has the file mapped in memory or the file is open
by any process.
To obtain a more portable behaviour, use `file_mapping::remove(const char *)` operation, which
will remove the file even if it's being mapped. However, removal will fail in some OS systems if
the file (eg. by C++ file streams) and no delete share permission was granted to the file. But in
most common cases `file_mapping::remove` is portable enough.
[endsect]
For more information about managed mapped file capabilities, see
@@ -3871,20 +3847,20 @@ Here is the declaration of the function:
[c++]
enum allocation_type
enum boost::interprocess::allocation_type
{
//Bitwise OR (|) combinable values
allocate_new = ...,
expand_fwd = ...,
expand_bwd = ...,
shrink_in_place = ...,
nothrow_allocation = ...
boost::interprocess::allocate_new = ...,
boost::interprocess::expand_fwd = ...,
boost::interprocess::expand_bwd = ...,
boost::interprocess::shrink_in_place = ...,
boost::interprocess::nothrow_allocation = ...
};
template<class T>
std::pair<T *, bool>
allocation_command( allocation_type command
allocation_command( boost::interprocess::allocation_type command
, std::size_t limit_size
, std::size_t preferred_size
, std::size_t &received_size
@@ -3893,66 +3869,66 @@ Here is the declaration of the function:
[*Preconditions for the function]:
* If the parameter command contains the value `shrink_in_place` it can't
contain any of these values: `expand_fwd`, `expand_bwd`.
* If the parameter command contains the value `boost::interprocess::shrink_in_place` it can't
contain any of these values: `boost::interprocess::expand_fwd`, `boost::interprocess::expand_bwd`.
* If the parameter command contains `expand_fwd` or `expand_bwd`, the parameter
* If the parameter command contains `boost::interprocess::expand_fwd` or `boost::interprocess::expand_bwd`, the parameter
`reuse_ptr` must be non-null and returned by a previous allocation function.
* If the parameter command contains the value `shrink_in_place`, the parameter
* If the parameter command contains the value `boost::interprocess::shrink_in_place`, the parameter
`limit_size` must be equal or greater than the parameter `preferred_size`.
* If the parameter `command` contains any of these values: `expand_fwd` or `expand_bwd`,
* If the parameter `command` contains any of these values: `boost::interprocess::expand_fwd` or `boost::interprocess::expand_bwd`,
the parameter `limit_size` must be equal or less than the parameter `preferred_size`.
[*Which are the effects of this function:]
* If the parameter command contains the value `shrink_in_place`, the function
* If the parameter command contains the value `boost::interprocess::shrink_in_place`, the function
will try to reduce the size of the memory block referenced by pointer `reuse_ptr`
to the value `preferred_size` moving only the end of the block.
If it's not possible, it will try to reduce the size of the memory block as
much as possible as long as this results in `size(p) <= limit_size`. Success
is reported only if this results in `preferred_size <= size(p)` and `size(p) <= limit_size`.
* If the parameter `command` only contains the value `expand_fwd` (with optional
additional `nothrow_allocation`), the allocator will try to increase the size of the
* If the parameter `command` only contains the value `boost::interprocess::expand_fwd` (with optional
additional `boost::interprocess::nothrow_allocation`), the allocator will try to increase the size of the
memory block referenced by pointer reuse moving only the end of the block to the
value `preferred_size`. If it's not possible, it will try to increase the size
of the memory block as much as possible as long as this results in
`size(p) >= limit_size`. Success is reported only if this results in `limit_size <= size(p)`.
* If the parameter `command` only contains the value `expand_bwd` (with optional
additional `nothrow_allocation`), the allocator will try to increase the size of
* If the parameter `command` only contains the value `boost::interprocess::expand_bwd` (with optional
additional `boost::interprocess::nothrow_allocation`), the allocator will try to increase the size of
the memory block referenced by pointer `reuse_ptr` only moving the start of the
block to a returned new position `new_ptr`. If it's not possible, it will try to
move the start of the block as much as possible as long as this results in
`size(new_ptr) >= limit_size`. Success is reported only if this results in
`limit_size <= size(new_ptr)`.
* If the parameter `command` only contains the value `allocate_new` (with optional
additional `nothrow_allocation`), the allocator will try to allocate memory for
* If the parameter `command` only contains the value `boost::interprocess::allocate_new` (with optional
additional `boost::interprocess::nothrow_allocation`), the allocator will try to allocate memory for
`preferred_size` objects. If it's not possible it will try to allocate memory for
at least `limit_size` objects.
* If the parameter `command` only contains a combination of `expand_fwd` and
`allocate_new`, (with optional additional `nothrow_allocation`) the allocator will
* If the parameter `command` only contains a combination of `boost::interprocess::expand_fwd` and
`boost::interprocess::allocate_new`, (with optional additional `boost::interprocess::nothrow_allocation`) the allocator will
try first the forward expansion. If this fails, it would try a new allocation.
* If the parameter `command` only contains a combination of `expand_bwd` and
`allocate_new` (with optional additional `nothrow_allocation`), the allocator will
* If the parameter `command` only contains a combination of `boost::interprocess::expand_bwd` and
`boost::interprocess::allocate_new` (with optional additional `boost::interprocess::nothrow_allocation`), the allocator will
try first to obtain `preferred_size` objects using both methods if necessary.
If this fails, it will try to obtain `limit_size` objects using both methods if
necessary.
* If the parameter `command` only contains a combination of `expand_fwd` and
`expand_bwd` (with optional additional `nothrow_allocation`), the allocator will
* If the parameter `command` only contains a combination of `boost::interprocess::expand_fwd` and
`boost::interprocess::expand_bwd` (with optional additional `boost::interprocess::nothrow_allocation`), the allocator will
try first forward expansion. If this fails it will try to obtain preferred_size
objects using backwards expansion or a combination of forward and backwards expansion.
If this fails, it will try to obtain `limit_size` objects using both methods if
necessary.
* If the parameter `command` only contains a combination of allocation_new,
`expand_fwd` and `expand_bwd`, (with optional additional `nothrow_allocation`)
`boost::interprocess::expand_fwd` and `boost::interprocess::expand_bwd`, (with optional additional `boost::interprocess::nothrow_allocation`)
the allocator will try first forward expansion. If this fails it will try to obtain
preferred_size objects using new allocation, backwards expansion or a combination of
forward and backwards expansion. If this fails, it will try to obtain `limit_size`
@@ -3967,13 +3943,13 @@ contain any of these values: `expand_fwd`, `expand_bwd`.
* The allocator is unable to allocate/expand/shrink the memory or there is an
error in preconditions
* The parameter command does not contain `nothrow_allocation`.
* The parameter command does not contain `boost::interprocess::nothrow_allocation`.
[*This function returns:]
* The address of the allocated memory or the new address of the expanded memory
as the first member of the pair. If the parameter command contains
`nothrow_allocation` the first member will be 0
`boost::interprocess::nothrow_allocation` the first member will be 0
if the allocation/expansion fails or there is an error in preconditions.
* The second member of the pair will be false if the memory has been allocated,
@@ -5018,7 +4994,7 @@ Let's see an example:
[endsect]
[section:containers_and_move_semantics Move semantics in Interprocess containers]
[section:containers_and_move Move semantics in Interprocess containers]
[*Boost.Interprocess] containers support move semantics, which means that the contents
of a container can be moved from a container two another one, without any copying. The
@@ -5030,7 +5006,7 @@ objects in the container, avoiding unnecessary copies.
To transfer the contents of a container to another one, use
`boost::interprocess::move()` function, as shown in the example. For more details
`boost::move()` function, as shown in the example. For more details
about functions supporting move-semantics, see the reference section of
Boost.Interprocess containers:
@@ -6541,6 +6517,17 @@ warranty.
[section:release_notes Release Notes]
[section:release_notes_boost_1_39_00 Boost 1.39 Release]
* Added experimental `stable_vector` container.
* `shared_memory_object::remove` has now POSIX `unlink` semantics and
`file_mapping::remove` was added to obtain POSIX `unlink` semantics with mapped files.
* Shared memory in windows has now kernel lifetime instead of filesystem lifetime: shared
memory will disappear when the system reboots.
* Updated move semantics.
[endsect]
[section:release_notes_boost_1_38_00 Boost 1.38 Release]
* Updated documentation to show rvalue-references funcions instead of emulation functions.

View File

@@ -19,7 +19,7 @@ rule test_all
{
local all_rules = ;
for local fileb in [ glob *.cpp ]
for local fileb in [ glob comp*.cpp ]
{
all_rules += [ link $(fileb) /boost/thread//boost_thread
: # additional args
@@ -28,6 +28,17 @@ rule test_all
] ;
}
for local fileb in [ glob doc_*.cpp ]
{
all_rules += [ run $(fileb) /boost/thread//boost_thread
: # additional args
: # test-files
: # requirements
<toolset>acc:<linkflags>-lrt
<toolset>acc-pa_risc:<linkflags>-lrt
] ;
}
return $(all_rules) ;
}

View File

@@ -21,13 +21,17 @@ using namespace boost::interprocess;
int main ()
{
//Erase previous shared memory
shared_memory_object::remove("shared_memory");
//Erase previous shared memory and schedule erasure on exit
struct shm_destroy
{
shm_destroy() { shared_memory_object::remove("MySharedMemory"); }
~shm_destroy(){ shared_memory_object::remove("MySharedMemory"); }
} remover;
//Create a shared memory object.
shared_memory_object shm
(create_only //only create
,"shared_memory" //name
,"MySharedMemory" //name
,read_write //read-write mode
);
try{
@@ -66,13 +70,10 @@ int main ()
}
}
catch(interprocess_exception &ex){
shared_memory_object::remove("shared_memory");
std::cout << ex.what() << std::endl;
return 1;
}
//Erase shared memory
shared_memory_object::remove("shared_memory");
return 0;
}
//]

View File

@@ -23,7 +23,7 @@ int main ()
//Create a shared memory object.
shared_memory_object shm
(open_only //only create
,"shared_memory" //name
,"MySharedMemory" //name
,read_write //read-write mode
);
@@ -61,13 +61,10 @@ int main ()
while(!end_loop);
}
catch(interprocess_exception &ex){
shared_memory_object::remove("shared_memory");
std::cout << ex.what() << std::endl;
return 1;
}
//Erase shared memory
shared_memory_object::remove("shared_memory");
return 0;
}
//]

View File

@@ -21,13 +21,17 @@ using namespace boost::interprocess;
int main ()
{
try{
//Erase previous shared memory
shared_memory_object::remove("shared_memory");
//Remove shared memory on construction and destruction
struct shm_destroy
{
shm_destroy() { shared_memory_object::remove("MySharedMemory"); }
~shm_destroy(){ shared_memory_object::remove("MySharedMemory"); }
} remover;
//Create a shared memory object.
shared_memory_object shm
(create_only //only create
,"shared_memory" //name
,"MySharedMemory" //name
,read_write //read-write mode
);
@@ -65,12 +69,9 @@ int main ()
}
}
catch(interprocess_exception &ex){
shared_memory_object::remove("shared_memory");
std::cout << ex.what() << std::endl;
return 1;
}
//Erase shared memory
shared_memory_object::remove("shared_memory");
return 0;
}
//]

View File

@@ -0,0 +1,68 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2006-2007. 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/config_begin.hpp>
//[doc_anonymous_mutexB
#include <boost/interprocess/shared_memory_object.hpp>
#include <boost/interprocess/mapped_region.hpp>
#include <boost/interprocess/sync/scoped_lock.hpp>
#include "doc_anonymous_mutex_shared_data.hpp"
#include <iostream>
#include <cstdio>
using namespace boost::interprocess;
int main ()
{
//Remove shared memory on destruction
struct shm_destroy
{
~shm_destroy(){ shared_memory_object::remove("MySharedMemory"); }
} remover;
//Open the shared memory object.
shared_memory_object shm
(open_only //only create
,"MySharedMemory" //name
,read_write //read-write mode
);
//Map the whole shared memory in this process
mapped_region region
(shm //What to map
,read_write //Map it as read-write
);
//Get the address of the mapped region
void * addr = region.get_address();
//Construct the shared structure in memory
shared_memory_log * data = static_cast<shared_memory_log*>(addr);
//Write some logs
for(int i = 0; i < 100; ++i){
//Lock the mutex
scoped_lock<interprocess_mutex> lock(data->mutex);
std::sprintf(data->items[(data->current_line++) % shared_memory_log::NumItems]
,"%s_%d", "process_a", i);
if(i == (shared_memory_log::NumItems-1))
data->end_b = true;
//Mutex is released here
}
//Wait until the other process ends
while(1){
scoped_lock<interprocess_mutex> lock(data->mutex);
if(data->end_a)
break;
}
return 0;
}
//]
#include <boost/interprocess/detail/config_end.hpp>

View File

@@ -0,0 +1,64 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2006-2007. 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/config_begin.hpp>
//[doc_anonymous_semaphoreA
#include <boost/interprocess/shared_memory_object.hpp>
#include <boost/interprocess/mapped_region.hpp>
#include <iostream>
#include "doc_anonymous_semaphore_shared_data.hpp"
using namespace boost::interprocess;
int main ()
{
//Remove shared memory on construction and destruction
struct shm_destroy
{
shm_destroy() { shared_memory_object::remove("MySharedMemory"); }
~shm_destroy(){ shared_memory_object::remove("MySharedMemory"); }
} remover;
//Create a shared memory object.
shared_memory_object shm
(create_only //only create
,"MySharedMemory" //name
,read_write //read-write mode
);
//Set size
shm.truncate(sizeof(shared_memory_buffer));
//Map the whole shared memory in this process
mapped_region region
(shm //What to map
,read_write //Map it as read-write
);
//Get the address of the mapped region
void * addr = region.get_address();
//Construct the shared structure in memory
shared_memory_buffer * data = new (addr) shared_memory_buffer;
const int NumMsg = 100;
//Insert data in the array
for(int i = 0; i < NumMsg; ++i){
data->nempty.wait();
data->mutex.wait();
data->items[i % shared_memory_buffer::NumItems] = i;
data->mutex.post();
data->nstored.post();
}
return 0;
}
//]
#include <boost/interprocess/detail/config_end.hpp>

View File

@@ -0,0 +1,61 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2006-2007. 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/config_begin.hpp>
//[doc_anonymous_semaphoreB
#include <boost/interprocess/shared_memory_object.hpp>
#include <boost/interprocess/mapped_region.hpp>
#include <iostream>
#include "doc_anonymous_semaphore_shared_data.hpp"
using namespace boost::interprocess;
int main ()
{
//Remove shared memory on destruction
struct shm_destroy
{
~shm_destroy(){ shared_memory_object::remove("MySharedMemory"); }
} remover;
//Create a shared memory object.
shared_memory_object shm
(open_only //only create
,"MySharedMemory" //name
,read_write //read-write mode
);
//Map the whole shared memory in this process
mapped_region region
(shm //What to map
,read_write //Map it as read-write
);
//Get the address of the mapped region
void * addr = region.get_address();
//Obtain the shared structure
shared_memory_buffer * data = static_cast<shared_memory_buffer*>(addr);
const int NumMsg = 100;
int extracted_data [NumMsg];
//Extract the data
for(int i = 0; i < NumMsg; ++i){
data->nstored.wait();
data->mutex.wait();
extracted_data[i] = data->items[i % shared_memory_buffer::NumItems];
data->mutex.post();
data->nempty.post();
}
return 0;
}
//]
#include <boost/interprocess/detail/config_end.hpp>

View File

@@ -0,0 +1,72 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2006-2007. 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/config_begin.hpp>
//[doc_anonymous_upgradable_mutexA
#include <boost/interprocess/shared_memory_object.hpp>
#include <boost/interprocess/mapped_region.hpp>
#include <boost/interprocess/sync/scoped_lock.hpp>
#include "doc_upgradable_mutex_shared_data.hpp"
#include <iostream>
#include <cstdio>
using namespace boost::interprocess;
int main ()
{
//Remove shared memory on destruction
struct shm_destroy
{
~shm_destroy(){ shared_memory_object::remove("MySharedMemory"); }
} remover;
//Create a shared memory object.
shared_memory_object shm
(create_only //only create
,"MySharedMemory" //name
,read_write //read-write mode
);
//Set size
shm.truncate(sizeof(shared_data));
//Map the whole shared memory in this process
mapped_region region
(shm //What to map
,read_write //Map it as read-write
);
//Get the address of the mapped region
void * addr = region.get_address();
//Construct the shared structure in memory
shared_data * data = new (addr) shared_data;
//Write some logs
for(int i = 0; i < shared_data::NumItems; ++i){
//Lock the upgradable_mutex
scoped_lock<interprocess_upgradable_mutex> lock(data->upgradable_mutex);
std::sprintf(data->items[(data->current_line++) % shared_data::NumItems]
,"%s_%d", "process_a", i);
if(i == (shared_data::NumItems-1))
data->end_a = true;
//Mutex is released here
}
//Wait until the other process ends
while(1){
scoped_lock<interprocess_upgradable_mutex> lock(data->upgradable_mutex);
if(data->end_b)
break;
}
return 0;
}
//]
#include <boost/interprocess/detail/config_end.hpp>

View File

@@ -0,0 +1,70 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2006-2007. 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/config_begin.hpp>
//[doc_anonymous_upgradable_mutexB
#include <boost/interprocess/shared_memory_object.hpp>
#include <boost/interprocess/mapped_region.hpp>
#include <boost/interprocess/sync/scoped_lock.hpp>
#include "doc_upgradable_mutex_shared_data.hpp"
#include <iostream>
#include <cstdio>
using namespace boost::interprocess;
int main ()
{
//Remove shared memory on destruction
struct shm_destroy
{
~shm_destroy(){ shared_memory_object::remove("MySharedMemory"); }
} remover;
//Open the shared memory object.
shared_memory_object shm
(open_only //only create
,"MySharedMemory" //name
,read_write //read-write mode
);
//Map the whole shared memory in this process
mapped_region region
(shm //What to map
,read_write //Map it as read-write
);
//Get the address of the mapped region
void * addr = region.get_address();
//Construct the shared structure in memory
shared_data * data = static_cast<shared_data*>(addr);
//Write some logs
for(int i = 0; i < 100; ++i){
//Lock the upgradable_mutex
scoped_lock<interprocess_upgradable_mutex> lock(data->upgradable_mutex);
std::sprintf(data->items[(data->current_line++) % shared_data::NumItems]
,"%s_%d", "process_a", i);
if(i == (shared_data::NumItems-1))
data->end_b = true;
//Mutex is released here
}
//Wait until the other process ends
while(1){
scoped_lock<interprocess_upgradable_mutex> lock(data->upgradable_mutex);
if(data->end_a)
break;
}
return 0;
}
//]
#include <boost/interprocess/detail/config_end.hpp>

View File

@@ -18,46 +18,44 @@ using namespace boost::interprocess;
int main ()
{
shared_memory_object::remove("MySharedMemory");
//Remove shared memory on construction and destruction
struct shm_destroy
{
shm_destroy() { shared_memory_object::remove("MySharedMemory"); }
~shm_destroy(){ shared_memory_object::remove("MySharedMemory"); }
} remover;
try{
//Create shared memory
managed_shared_memory segment(create_only,
"MySharedMemory", //segment name
65536);
//Create shared memory
managed_shared_memory segment(create_only,
"MySharedMemory", //segment name
65536);
//Create a adaptive_pool that allocates ints from the managed segment
//The number of chunks per segment is the default value
typedef adaptive_pool<int, managed_shared_memory::segment_manager>
adaptive_pool_t;
adaptive_pool_t allocator_instance(segment.get_segment_manager());
//Create a adaptive_pool that allocates ints from the managed segment
//The number of chunks per segment is the default value
typedef adaptive_pool<int, managed_shared_memory::segment_manager>
adaptive_pool_t;
adaptive_pool_t allocator_instance(segment.get_segment_manager());
//Create another adaptive_pool. Since the segment manager address
//is the same, this adaptive_pool will be
//attached to the same pool so "allocator_instance2" can deallocate
//nodes allocated by "allocator_instance"
adaptive_pool_t allocator_instance2(segment.get_segment_manager());
//Create another adaptive_pool. Since the segment manager address
//is the same, this adaptive_pool will be
//attached to the same pool so "allocator_instance2" can deallocate
//nodes allocated by "allocator_instance"
adaptive_pool_t allocator_instance2(segment.get_segment_manager());
//Create another adaptive_pool using copy-constructor. This
//adaptive_pool will also be attached to the same pool
adaptive_pool_t allocator_instance3(allocator_instance2);
//Create another adaptive_pool using copy-constructor. This
//adaptive_pool will also be attached to the same pool
adaptive_pool_t allocator_instance3(allocator_instance2);
//All allocators are equal
assert(allocator_instance == allocator_instance2);
assert(allocator_instance2 == allocator_instance3);
//All allocators are equal
assert(allocator_instance == allocator_instance2);
assert(allocator_instance2 == allocator_instance3);
//So memory allocated with one can be deallocated with another
allocator_instance2.deallocate(allocator_instance.allocate(1), 1);
allocator_instance3.deallocate(allocator_instance2.allocate(1), 1);
//So memory allocated with one can be deallocated with another
allocator_instance2.deallocate(allocator_instance.allocate(1), 1);
allocator_instance3.deallocate(allocator_instance2.allocate(1), 1);
//The common pool will be destroyed here, since no allocator is
//attached to the pool
}
catch(...){
shared_memory_object::remove("MySharedMemory");
throw;
}
shared_memory_object::remove("MySharedMemory");
//The common pool will be destroyed here, since no allocator is
//attached to the pool
return 0;
}
//]

View File

@@ -18,7 +18,12 @@ using namespace boost::interprocess;
int main ()
{
shared_memory_object::remove("MySharedMemory");
//Remove shared memory on construction and destruction
struct shm_destroy
{
shm_destroy() { shared_memory_object::remove("MySharedMemory"); }
~shm_destroy(){ shared_memory_object::remove("MySharedMemory"); }
} remover;
//Create shared memory
managed_shared_memory segment(create_only,

View File

@@ -1,70 +0,0 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2006-2007. 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/config_begin.hpp>
//[doc_anonymous_mutexB
#include <boost/interprocess/shared_memory_object.hpp>
#include <boost/interprocess/mapped_region.hpp>
#include <boost/interprocess/sync/scoped_lock.hpp>
#include "doc_anonymous_mutex_shared_data.hpp"
#include <iostream>
#include <cstdio>
using namespace boost::interprocess;
int main ()
{
try{
//Open the shared memory object.
shared_memory_object shm
(open_only //only create
,"shared_memory" //name
,read_write //read-write mode
);
//Map the whole shared memory in this process
mapped_region region
(shm //What to map
,read_write //Map it as read-write
);
//Get the address of the mapped region
void * addr = region.get_address();
//Construct the shared structure in memory
shared_memory_log * data = static_cast<shared_memory_log*>(addr);
//Write some logs
for(int i = 0; i < 100; ++i){
//Lock the mutex
scoped_lock<interprocess_mutex> lock(data->mutex);
std::sprintf(data->items[(data->current_line++) % shared_memory_log::NumItems]
,"%s_%d", "process_a", i);
if(i == (shared_memory_log::NumItems-1))
data->end_b = true;
//Mutex is released here
}
//Wait until the other process ends
while(1){
scoped_lock<interprocess_mutex> lock(data->mutex);
if(data->end_a)
break;
}
}
catch(interprocess_exception &ex){
shared_memory_object::remove("shared_memory");
std::cout << ex.what() << std::endl;
return 1;
}
shared_memory_object::remove("shared_memory");
return 0;
}
//]
#include <boost/interprocess/detail/config_end.hpp>

View File

@@ -1,70 +0,0 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2006-2007. 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/config_begin.hpp>
//[doc_anonymous_semaphoreA
#include <boost/interprocess/shared_memory_object.hpp>
#include <boost/interprocess/mapped_region.hpp>
#include <iostream>
#include "doc_anonymous_semaphore_shared_data.hpp"
using namespace boost::interprocess;
int main ()
{
try{
//Erase previous shared memory
shared_memory_object::remove("shared_memory");
//Create a shared memory object.
shared_memory_object shm
(create_only //only create
,"shared_memory" //name
,read_write //read-write mode
);
//Set size
shm.truncate(sizeof(shared_memory_buffer));
//Map the whole shared memory in this process
mapped_region region
(shm //What to map
,read_write //Map it as read-write
);
//Get the address of the mapped region
void * addr = region.get_address();
//Construct the shared structure in memory
shared_memory_buffer * data = new (addr) shared_memory_buffer;
const int NumMsg = 100;
//Insert data in the array
for(int i = 0; i < NumMsg; ++i){
data->nempty.wait();
data->mutex.wait();
data->items[i % shared_memory_buffer::NumItems] = i;
data->mutex.post();
data->nstored.post();
}
}
catch(interprocess_exception &ex){
shared_memory_object::remove("shared_memory");
std::cout << ex.what() << std::endl;
return 1;
}
//Erase shared memory
shared_memory_object::remove("shared_memory");
return 0;
}
//]
#include <boost/interprocess/detail/config_end.hpp>

View File

@@ -1,66 +0,0 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2006-2007. 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/config_begin.hpp>
//[doc_anonymous_semaphoreB
#include <boost/interprocess/shared_memory_object.hpp>
#include <boost/interprocess/mapped_region.hpp>
#include <iostream>
#include "doc_anonymous_semaphore_shared_data.hpp"
using namespace boost::interprocess;
int main ()
{
try{
//Create a shared memory object.
shared_memory_object shm
(open_only //only create
,"shared_memory" //name
,read_write //read-write mode
);
//Map the whole shared memory in this process
mapped_region region
(shm //What to map
,read_write //Map it as read-write
);
//Get the address of the mapped region
void * addr = region.get_address();
//Obtain the shared structure
shared_memory_buffer * data = static_cast<shared_memory_buffer*>(addr);
const int NumMsg = 100;
int extracted_data [NumMsg];
//Extract the data
for(int i = 0; i < NumMsg; ++i){
data->nstored.wait();
data->mutex.wait();
extracted_data[i] = data->items[i % shared_memory_buffer::NumItems];
data->mutex.post();
data->nempty.post();
}
}
catch(interprocess_exception &ex){
shared_memory_object::remove("shared_memory");
std::cout << ex.what() << std::endl;
return 1;
}
//Erase shared memory
shared_memory_object::remove("shared_memory");
return 0;
}
//]
#include <boost/interprocess/detail/config_end.hpp>

View File

@@ -1,79 +0,0 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2006-2007. 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/config_begin.hpp>
//[doc_anonymous_upgradable_mutexA
#include <boost/interprocess/shared_memory_object.hpp>
#include <boost/interprocess/mapped_region.hpp>
#include <boost/interprocess/sync/scoped_lock.hpp>
#include "doc_upgradable_mutex_shared_data.hpp"
#include <iostream>
#include <cstdio>
using namespace boost::interprocess;
int main ()
{
try{
//Erase previous shared memory
shared_memory_object::remove("shared_memory");
//Create a shared memory object.
shared_memory_object shm
(create_only //only create
,"shared_memory" //name
,read_write //read-write mode
);
//Set size
shm.truncate(sizeof(shared_data));
//Map the whole shared memory in this process
mapped_region region
(shm //What to map
,read_write //Map it as read-write
);
//Get the address of the mapped region
void * addr = region.get_address();
//Construct the shared structure in memory
shared_data * data = new (addr) shared_data;
//Write some logs
for(int i = 0; i < shared_data::NumItems; ++i){
//Lock the upgradable_mutex
scoped_lock<interprocess_upgradable_mutex> lock(data->upgradable_mutex);
std::sprintf(data->items[(data->current_line++) % shared_data::NumItems]
,"%s_%d", "process_a", i);
if(i == (shared_data::NumItems-1))
data->end_a = true;
//Mutex is released here
}
//Wait until the other process ends
while(1){
scoped_lock<interprocess_upgradable_mutex> lock(data->upgradable_mutex);
if(data->end_b)
break;
}
}
catch(interprocess_exception &ex){
shared_memory_object::remove("shared_memory");
std::cout << ex.what() << std::endl;
return 1;
}
//Erase shared memory
shared_memory_object::remove("shared_memory");
return 0;
}
//]
#include <boost/interprocess/detail/config_end.hpp>

View File

@@ -1,72 +0,0 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2006-2007. 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/config_begin.hpp>
//[doc_anonymous_upgradable_mutexB
#include <boost/interprocess/shared_memory_object.hpp>
#include <boost/interprocess/mapped_region.hpp>
#include <boost/interprocess/sync/scoped_lock.hpp>
#include "doc_upgradable_mutex_shared_data.hpp"
#include <iostream>
#include <cstdio>
using namespace boost::interprocess;
int main ()
{
try{
//Open the shared memory object.
shared_memory_object shm
(open_only //only create
,"shared_memory" //name
,read_write //read-write mode
);
//Map the whole shared memory in this process
mapped_region region
(shm //What to map
,read_write //Map it as read-write
);
//Get the address of the mapped region
void * addr = region.get_address();
//Construct the shared structure in memory
shared_data * data = static_cast<shared_data*>(addr);
//Write some logs
for(int i = 0; i < 100; ++i){
//Lock the upgradable_mutex
scoped_lock<interprocess_upgradable_mutex> lock(data->upgradable_mutex);
std::sprintf(data->items[(data->current_line++) % shared_data::NumItems]
,"%s_%d", "process_a", i);
if(i == (shared_data::NumItems-1))
data->end_b = true;
//Mutex is released here
}
//Wait until the other process ends
while(1){
scoped_lock<interprocess_upgradable_mutex> lock(data->upgradable_mutex);
if(data->end_a)
break;
}
}
catch(interprocess_exception &ex){
shared_memory_object::remove("shared_memory");
std::cout << ex.what() << std::endl;
return 1;
}
shared_memory_object::remove("shared_memory");
return 0;
}
//]
#include <boost/interprocess/detail/config_end.hpp>

View File

@@ -14,72 +14,73 @@
#include <boost/interprocess/streams/bufferstream.hpp>
#include <vector>
#include <iterator>
#include <cstddef>
using namespace boost::interprocess;
int main ()
{
shared_memory_object::remove("MySharedMemory");
try{
//Create shared memory
managed_shared_memory segment(create_only,
"MySharedMemory", //segment name
65536);
//Remove shared memory on construction and destruction
struct shm_destroy
{
shm_destroy() { shared_memory_object::remove("MySharedMemory"); }
~shm_destroy(){ shared_memory_object::remove("MySharedMemory"); }
} remover;
//Fill data
std::vector<int> data, data2;
data.reserve(100);
for(int i = 0; i < 100; ++i){
data.push_back(i);
}
//Create shared memory
managed_shared_memory segment(create_only,
"MySharedMemory", //segment name
65536);
//Allocate a buffer in shared memory to write data
char *my_cstring =
segment.construct<char>("MyCString")[100*5](0);
bufferstream mybufstream(my_cstring, 100*5);
//Now write data to the buffer
for(int i = 0; i < 100; ++i){
mybufstream << data[i] << std::endl;
}
//Check there was no overflow attempt
assert(mybufstream.good());
//Extract all values from the shared memory string
//directly to a vector.
data2.reserve(100);
std::istream_iterator<int> it(mybufstream), itend;
std::copy(it, itend, std::back_inserter(data2));
//This extraction should have ended will fail error since
//the numbers formatted in the buffer end before the end
//of the buffer. (Otherwise it would trigger eofbit)
assert(mybufstream.fail());
//Compare data
assert(std::equal(data.begin(), data.end(), data2.begin()));
//Clear errors and rewind
mybufstream.clear();
mybufstream.seekp(0, std::ios::beg);
//Now write again the data trying to do a buffer overflow
for(int i = 0; i < 500; ++i){
mybufstream << data[i] << std::endl;
}
//Now make sure badbit is active
//which means overflow attempt.
assert(!mybufstream.good());
assert(mybufstream.bad());
segment.destroy_ptr(my_cstring);
//Fill data
std::vector<int> data;
data.reserve(100);
for(int i = 0; i < 100; ++i){
data.push_back(i);
}
catch(...){
shared_memory_object::remove("MySharedMemory");
throw;
const std::size_t BufferSize = 100*5;
//Allocate a buffer in shared memory to write data
char *my_cstring =
segment.construct<char>("MyCString")[BufferSize](0);
bufferstream mybufstream(my_cstring, BufferSize);
//Now write data to the buffer
for(int i = 0; i < 100; ++i){
mybufstream << data[i] << std::endl;
}
shared_memory_object::remove("MySharedMemory");
//Check there was no overflow attempt
assert(mybufstream.good());
//Extract all values from the shared memory string
//directly to a vector.
std::vector<int> data2;
std::istream_iterator<int> it(mybufstream), itend;
std::copy(it, itend, std::back_inserter(data2));
//This extraction should have ended will fail error since
//the numbers formatted in the buffer end before the end
//of the buffer. (Otherwise it would trigger eofbit)
assert(mybufstream.fail());
//Compare data
assert(std::equal(data.begin(), data.end(), data2.begin()));
//Clear errors and rewind
mybufstream.clear();
mybufstream.seekp(0, std::ios::beg);
//Now write again the data trying to do a buffer overflow
for(int i = 0, m = data.size()*5; i < m; ++i){
mybufstream << data[i%5] << std::endl;
}
//Now make sure badbit is active
//which means overflow attempt.
assert(!mybufstream.good());
assert(mybufstream.bad());
segment.destroy_ptr(my_cstring);
return 0;
}
//]

View File

@@ -18,54 +18,53 @@ using namespace boost::interprocess;
int main ()
{
shared_memory_object::remove("MySharedMemory");
try{
//Create shared memory
managed_shared_memory segment(create_only,
"MySharedMemory", //segment name
65536);
//Remove shared memory on construction and destruction
struct shm_destroy
{
shm_destroy() { shared_memory_object::remove("MySharedMemory"); }
~shm_destroy(){ shared_memory_object::remove("MySharedMemory"); }
} remover;
//Create a cached_adaptive_pool that allocates ints from the managed segment
//The number of chunks per segment is the default value
typedef cached_adaptive_pool<int, managed_shared_memory::segment_manager>
cached_adaptive_pool_t;
cached_adaptive_pool_t allocator_instance(segment.get_segment_manager());
//Create shared memory
managed_shared_memory segment(create_only,
"MySharedMemory", //segment name
65536);
//The max cached nodes are configurable per instance
allocator_instance.set_max_cached_nodes(3);
//Create a cached_adaptive_pool that allocates ints from the managed segment
//The number of chunks per segment is the default value
typedef cached_adaptive_pool<int, managed_shared_memory::segment_manager>
cached_adaptive_pool_t;
cached_adaptive_pool_t allocator_instance(segment.get_segment_manager());
//Create another cached_adaptive_pool. Since the segment manager address
//is the same, this cached_adaptive_pool will be
//attached to the same pool so "allocator_instance2" can deallocate
//nodes allocated by "allocator_instance"
cached_adaptive_pool_t allocator_instance2(segment.get_segment_manager());
//The max cached nodes are configurable per instance
allocator_instance.set_max_cached_nodes(3);
//The max cached nodes are configurable per instance
allocator_instance2.set_max_cached_nodes(5);
//Create another cached_adaptive_pool. Since the segment manager address
//is the same, this cached_adaptive_pool will be
//attached to the same pool so "allocator_instance2" can deallocate
//nodes allocated by "allocator_instance"
cached_adaptive_pool_t allocator_instance2(segment.get_segment_manager());
//Create another cached_adaptive_pool using copy-constructor. This
//cached_adaptive_pool will also be attached to the same pool
cached_adaptive_pool_t allocator_instance3(allocator_instance2);
//The max cached nodes are configurable per instance
allocator_instance2.set_max_cached_nodes(5);
//We can clear the cache
allocator_instance3.deallocate_cache();
//Create another cached_adaptive_pool using copy-constructor. This
//cached_adaptive_pool will also be attached to the same pool
cached_adaptive_pool_t allocator_instance3(allocator_instance2);
//All allocators are equal
assert(allocator_instance == allocator_instance2);
assert(allocator_instance2 == allocator_instance3);
//We can clear the cache
allocator_instance3.deallocate_cache();
//So memory allocated with one can be deallocated with another
allocator_instance2.deallocate(allocator_instance.allocate(1), 1);
allocator_instance3.deallocate(allocator_instance2.allocate(1), 1);
//All allocators are equal
assert(allocator_instance == allocator_instance2);
assert(allocator_instance2 == allocator_instance3);
//The common pool will be destroyed here, since no allocator is
//attached to the pool
}
catch(...){
shared_memory_object::remove("MySharedMemory");
throw;
}
shared_memory_object::remove("MySharedMemory");
//So memory allocated with one can be deallocated with another
allocator_instance2.deallocate(allocator_instance.allocate(1), 1);
allocator_instance3.deallocate(allocator_instance2.allocate(1), 1);
//The common pool will be destroyed here, since no allocator is
//attached to the pool
return 0;
}
//]

View File

@@ -18,54 +18,53 @@ using namespace boost::interprocess;
int main ()
{
shared_memory_object::remove("MySharedMemory");
try{
//Create shared memory
managed_shared_memory segment(create_only,
"MySharedMemory", //segment name
65536);
//Remove shared memory on construction and destruction
struct shm_destroy
{
shm_destroy() { shared_memory_object::remove("MySharedMemory"); }
~shm_destroy(){ shared_memory_object::remove("MySharedMemory"); }
} remover;
//Create a cached_node_allocator that allocates ints from the managed segment
//The number of chunks per segment is the default value
typedef cached_node_allocator<int, managed_shared_memory::segment_manager>
cached_node_allocator_t;
cached_node_allocator_t allocator_instance(segment.get_segment_manager());
//Create shared memory
managed_shared_memory segment(create_only,
"MySharedMemory", //segment name
65536);
//The max cached nodes are configurable per instance
allocator_instance.set_max_cached_nodes(3);
//Create a cached_node_allocator that allocates ints from the managed segment
//The number of chunks per segment is the default value
typedef cached_node_allocator<int, managed_shared_memory::segment_manager>
cached_node_allocator_t;
cached_node_allocator_t allocator_instance(segment.get_segment_manager());
//Create another cached_node_allocator. Since the segment manager address
//is the same, this cached_node_allocator will be
//attached to the same pool so "allocator_instance2" can deallocate
//nodes allocated by "allocator_instance"
cached_node_allocator_t allocator_instance2(segment.get_segment_manager());
//The max cached nodes are configurable per instance
allocator_instance.set_max_cached_nodes(3);
//The max cached nodes are configurable per instance
allocator_instance2.set_max_cached_nodes(5);
//Create another cached_node_allocator. Since the segment manager address
//is the same, this cached_node_allocator will be
//attached to the same pool so "allocator_instance2" can deallocate
//nodes allocated by "allocator_instance"
cached_node_allocator_t allocator_instance2(segment.get_segment_manager());
//Create another cached_node_allocator using copy-constructor. This
//cached_node_allocator will also be attached to the same pool
cached_node_allocator_t allocator_instance3(allocator_instance2);
//The max cached nodes are configurable per instance
allocator_instance2.set_max_cached_nodes(5);
//We can clear the cache
allocator_instance3.deallocate_cache();
//Create another cached_node_allocator using copy-constructor. This
//cached_node_allocator will also be attached to the same pool
cached_node_allocator_t allocator_instance3(allocator_instance2);
//All allocators are equal
assert(allocator_instance == allocator_instance2);
assert(allocator_instance2 == allocator_instance3);
//We can clear the cache
allocator_instance3.deallocate_cache();
//So memory allocated with one can be deallocated with another
allocator_instance2.deallocate(allocator_instance.allocate(1), 1);
allocator_instance3.deallocate(allocator_instance2.allocate(1), 1);
//All allocators are equal
assert(allocator_instance == allocator_instance2);
assert(allocator_instance2 == allocator_instance3);
//The common pool will be destroyed here, since no allocator is
//attached to the pool
}
catch(...){
shared_memory_object::remove("MySharedMemory");
throw;
}
shared_memory_object::remove("MySharedMemory");
//So memory allocated with one can be deallocated with another
allocator_instance2.deallocate(allocator_instance.allocate(1), 1);
allocator_instance3.deallocate(allocator_instance2.allocate(1), 1);
//The common pool will be destroyed here, since no allocator is
//attached to the pool
return 0;
}
//]

View File

@@ -52,28 +52,31 @@ typedef map< char_string, complex_data
int main ()
{
shared_memory_object::remove("MySharedMemory");
remove_shared_memory_on_destroy remove_on_destroy("MySharedMemory");
//Remove shared memory on construction and destruction
struct shm_destroy
{
//Create shared memory
managed_shared_memory segment(create_only,"MySharedMemory", 65536);
shm_destroy() { shared_memory_object::remove("MySharedMemory"); }
~shm_destroy(){ shared_memory_object::remove("MySharedMemory"); }
} remover;
//An allocator convertible to any allocator<T, segment_manager_t> type
void_allocator alloc_inst (segment.get_segment_manager());
//Create shared memory
managed_shared_memory segment(create_only,"MySharedMemory", 65536);
//Construct the shared memory map and fill it
complex_map_type *mymap = segment.construct<complex_map_type>
//(object name), (first ctor parameter, second ctor parameter)
("MyMap")(std::less<char_string>(), alloc_inst);
//An allocator convertible to any allocator<T, segment_manager_t> type
void_allocator alloc_inst (segment.get_segment_manager());
for(int i = 0; i < 100; ++i){
//Both key(string) and value(complex_data) need an allocator in their constructors
char_string key_object(alloc_inst);
complex_data mapped_object(i, "default_name", alloc_inst);
map_value_type value(key_object, mapped_object);
//Modify values and insert them in the map
mymap->insert(value);
}
//Construct the shared memory map and fill it
complex_map_type *mymap = segment.construct<complex_map_type>
//(object name), (first ctor parameter, second ctor parameter)
("MyMap")(std::less<char_string>(), alloc_inst);
for(int i = 0; i < 100; ++i){
//Both key(string) and value(complex_data) need an allocator in their constructors
char_string key_object(alloc_inst);
complex_data mapped_object(i, "default_name", alloc_inst);
map_value_type value(key_object, mapped_object);
//Modify values and insert them in the map
mymap->insert(value);
}
return 0;
}

View File

@@ -17,48 +17,47 @@
int main ()
{
using namespace boost::interprocess;
shared_memory_object::remove("MySharedMemory");
try{
//A managed shared memory where we can construct objects
//associated with a c-string
managed_shared_memory segment(create_only,
"MySharedMemory", //segment name
65536);
//Remove shared memory on construction and destruction
struct shm_destroy
{
shm_destroy() { shared_memory_object::remove("MySharedMemory"); }
~shm_destroy(){ shared_memory_object::remove("MySharedMemory"); }
} remover;
//Alias an STL-like allocator of ints that allocates ints from the segment
typedef allocator<int, managed_shared_memory::segment_manager>
ShmemAllocator;
//A managed shared memory where we can construct objects
//associated with a c-string
managed_shared_memory segment(create_only,
"MySharedMemory", //segment name
65536);
//Alias a vector that uses the previous STL-like allocator
typedef vector<int, ShmemAllocator> MyVector;
//Alias an STL-like allocator of ints that allocates ints from the segment
typedef allocator<int, managed_shared_memory::segment_manager>
ShmemAllocator;
int initVal[] = {0, 1, 2, 3, 4, 5, 6 };
const int *begVal = initVal;
const int *endVal = initVal + sizeof(initVal)/sizeof(initVal[0]);
//Alias a vector that uses the previous STL-like allocator
typedef vector<int, ShmemAllocator> MyVector;
//Initialize the STL-like allocator
const ShmemAllocator alloc_inst (segment.get_segment_manager());
int initVal[] = {0, 1, 2, 3, 4, 5, 6 };
const int *begVal = initVal;
const int *endVal = initVal + sizeof(initVal)/sizeof(initVal[0]);
//Construct the vector in the shared memory segment with the STL-like allocator
//from a range of iterators
MyVector *myvector =
segment.construct<MyVector>
("MyVector")/*object name*/
(begVal /*first ctor parameter*/,
endVal /*second ctor parameter*/,
alloc_inst /*third ctor parameter*/);
//Initialize the STL-like allocator
const ShmemAllocator alloc_inst (segment.get_segment_manager());
//Use vector as your want
std::sort(myvector->rbegin(), myvector->rend());
// . . .
//When done, destroy and delete vector from the segment
segment.destroy<MyVector>("MyVector");
}
catch(...){
shared_memory_object::remove("MySharedMemory");
throw;
}
shared_memory_object::remove("MySharedMemory");
//Construct the vector in the shared memory segment with the STL-like allocator
//from a range of iterators
MyVector *myvector =
segment.construct<MyVector>
("MyVector")/*object name*/
(begVal /*first ctor parameter*/,
endVal /*second ctor parameter*/,
alloc_inst /*third ctor parameter*/);
//Use vector as your want
std::sort(myvector->rbegin(), myvector->rend());
// . . .
//When done, destroy and delete vector from the segment
segment.destroy<MyVector>("MyVector");
return 0;
}
//]

View File

@@ -1,60 +0,0 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2006-2007. 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/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
//[doc_contA
#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/containers/vector.hpp>
#include <boost/interprocess/allocators/allocator.hpp>
int main ()
{
using namespace boost::interprocess;
try{
//Shared memory front-end that is able to construct objects
//associated with a c-string. Erase previous shared memory with the name
//to be used and create the memory segment at the specified address and initialize resources
shared_memory_object::remove("MySharedMemory");
managed_shared_memory segment
(create_only
,"MySharedMemory" //segment name
,65536); //segment size in bytes
//Alias an STL compatible allocator of ints that allocates ints from the managed
//shared memory segment. This allocator will allow to place containers
//in managed shared memory segments
typedef allocator<int, managed_shared_memory::segment_manager>
ShmemAllocator;
//Alias a vector that uses the previous STL-like allocator
typedef vector<int, ShmemAllocator> MyVector;
//Initialize shared memory STL-compatible allocator
const ShmemAllocator alloc_inst (segment.get_segment_manager());
//Construct a shared memory
MyVector *myvector =
segment.construct<MyVector>("MyVector") //object name
(alloc_inst);//first ctor parameter
//Insert data in the vector
for(int i = 0; i < 100; ++i){
myvector->push_back(i);
}
}
catch(...){
shared_memory_object::remove("MySharedMemory");
throw;
}
shared_memory_object::remove("MySharedMemory");
return 0;
}
//]
#include <boost/interprocess/detail/config_end.hpp>

View File

@@ -1,57 +0,0 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2006-2007. 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/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
//[doc_contB
#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/containers/vector.hpp>
#include <boost/interprocess/allocators/allocator.hpp>
#include <algorithm>
int main ()
{
using namespace boost::interprocess;
try{
//A special shared memory where we can
//construct objects associated with a name.
//Connect to the already created shared memory segment
//and initialize needed resources
managed_shared_memory segment
(open_only
,"MySharedMemory"); //segment name
//Alias an STL compatible allocator of ints that allocates ints from the managed
//shared memory segment. This allocator will allow to place containers
//in managed shared memory segments
typedef allocator<int, managed_shared_memory::segment_manager>
ShmemAllocator;
//Alias a vector that uses the previous STL-like allocator
typedef vector<int, ShmemAllocator> MyVector;
//Find the vector using the c-string name
MyVector *myvector = segment.find<MyVector>("MyVector").first;
//Use vector in reverse order
std::sort(myvector->rbegin(), myvector->rend());
// . . .
//When done, destroy the vector from the segment
segment.destroy<MyVector>("MyVector");
}
catch(...){
shared_memory_object::remove("MySharedMemory");
throw;
}
shared_memory_object::remove("MySharedMemory");
return 0;
}
//]
#include <boost/interprocess/detail/config_end.hpp>

View File

@@ -13,35 +13,36 @@
#include <boost/interprocess/mapped_region.hpp>
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <cstring>
#include <cstddef>
#include <cstdio> //std::remove
#include <cstdlib>
int main ()
int main(int argc, char *argv[])
{
using namespace boost::interprocess;
try{
//Create a file
std::filebuf fbuf;
fbuf.open("file.bin", std::ios_base::in | std::ios_base::out
| std::ios_base::trunc | std::ios_base::binary);
const std::size_t FileSize = 10000;
if(argc == 1){ //Parent process executes this
{ //Create a file
std::filebuf fbuf;
fbuf.open("file.bin", std::ios_base::in | std::ios_base::out
| std::ios_base::trunc | std::ios_base::binary);
//Set the size
fbuf.pubseekoff(FileSize-1, std::ios_base::beg);
fbuf.sputc(0);
}
//Remove file on exit
struct file_remove
{
~file_remove (){ file_mapping::remove("file.bin"); }
} destroy_on_exit;
//Set the size
fbuf.pubseekoff(9999, std::ios_base::beg);
fbuf.sputc(0);
fbuf.close();
//Create a file mapping.
//Create a file mapping
file_mapping m_file("file.bin", read_write);
//Map the whole file in this process
mapped_region region
(m_file //What to map
,read_write //Map it as read-write
);
if(region.get_size() != 10000)
return 1;
//Map the whole file with read-write permissions in this process
mapped_region region(m_file, read_write);
//Get the address of the mapped region
void * addr = region.get_address();
@@ -50,12 +51,42 @@ int main ()
//Write all the memory to 1
std::memset(addr, 1, size);
//Launch child process
std::string s(argv[0]); s += " child";
if(0 != std::system(s.c_str()))
return 1;
}
catch(interprocess_exception &ex){
std::remove("file.bin");
std::cout << ex.what() << std::endl;
return 1;
else{ //Child process executes this
{ //Open the file mapping and map it as read-only
file_mapping m_file ("file.bin", read_only);
mapped_region region(m_file, read_only);
//Get the address of the mapped region
void * addr = region.get_address();
std::size_t size = region.get_size();
//Check that memory was initialized to 1
const char *mem = static_cast<char*>(addr);
for(std::size_t i = 0; i < size; ++i)
if(*mem++ != 1)
return 1; //Error checking memory
}
{ //Now test it reading the file
std::filebuf fbuf;
fbuf.open("file.bin", std::ios_base::in | std::ios_base::binary);
//Read it to memory
std::vector<char> vect(FileSize, 0);
fbuf.sgetn(&vect[0], std::streamsize(vect.size()));
//Check that memory was initialized to 1
const char *mem = static_cast<char*>(&vect[0]);
for(std::size_t i = 0; i < FileSize; ++i)
if(*mem++ != 1)
return 1; //Error checking memory
}
}
return 0;
}
//]

View File

@@ -1,74 +0,0 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2006-2007. 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/config_begin.hpp>
//[doc_file_mapping2
#include <boost/interprocess/file_mapping.hpp>
#include <boost/interprocess/mapped_region.hpp>
#include <iostream>
#include <fstream>
#include <cstddef>
#include <cstdio> //std::remove
#include <vector>
int main ()
{
using namespace boost::interprocess;
try{
//Open the file mapping
file_mapping m_file ("file.bin", read_only);
//Map the whole file in this process
mapped_region region
(m_file //What to map
,read_only //Map it as read-only
);
//Get the address of the mapped region
void * addr = region.get_address();
std::size_t size = region.get_size();
//Check that memory was initialized to 1
const char *mem = static_cast<char*>(addr);
for(std::size_t i = 0; i < size; ++i){
if(*mem++ != 1){
std::cout << "Error checking memory!" << std::endl;
return 1;
}
}
//Now test it reading the file
std::filebuf fbuf;
fbuf.open("file.bin", std::ios_base::in | std::ios_base::binary);
//Read it to memory
std::vector<char> vect(region.get_size(), 0);
fbuf.sgetn(&vect[0], std::streamsize(vect.size()));
//Check that memory was initialized to 1
mem = static_cast<char*>(&vect[0]);
for(std::size_t i = 0; i < size; ++i){
if(*mem++ != 1){
std::cout << "Error checking memory!" << std::endl;
return 1;
}
}
std::cout << "Test successful!" << std::endl;
}
catch(interprocess_exception &ex){
std::remove("file.bin");
std::cout << "Unexpected exception: " << ex.what() << std::endl;
return 1;
}
std::remove("file.bin");
return 0;
}
//]
#include <boost/interprocess/detail/config_end.hpp>

View File

@@ -7,6 +7,7 @@
// See http://www.boost.org/libs/interprocess for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
//[doc_intrusive
@@ -68,42 +69,40 @@ class intrusive_ptr_owner
: m_intrusive_ptr(ptr){}
};
int main ()
int main()
{
shared_memory_object::remove("my_shmem");
//Remove shared memory on construction and destruction
struct shm_destroy
{
shm_destroy() { shared_memory_object::remove("MySharedMemory"); }
~shm_destroy(){ shared_memory_object::remove("MySharedMemory"); }
} remover;
try{
//Create shared memory
managed_shared_memory shmem(create_only, "my_shmem", 10000);
//Create shared memory
managed_shared_memory shmem(create_only, "MySharedMemory", 10000);
//Create the unique reference counted object in shared memory
N::reference_counted_class *ref_counted =
shmem.construct<N::reference_counted_class>
("ref_counted")(shmem.get_segment_manager());
//Create the unique reference counted object in shared memory
N::reference_counted_class *ref_counted =
shmem.construct<N::reference_counted_class>
("ref_counted")(shmem.get_segment_manager());
//Create an array of ten intrusive pointer owners in shared memory
intrusive_ptr_owner *intrusive_owner_array =
shmem.construct<intrusive_ptr_owner>
(anonymous_instance)[10](ref_counted);
//Create an array of ten intrusive pointer owners in shared memory
intrusive_ptr_owner *intrusive_owner_array =
shmem.construct<intrusive_ptr_owner>
(anonymous_instance)[10](ref_counted);
//Now test that reference count is ten
if(ref_counted->use_count() != 10)
return 1;
//Now test that reference count is ten
if(ref_counted->use_count() != 10)
return 1;
//Now destroy the array of intrusive pointer owners
//This should destroy every intrusive_ptr and because of
//that reference_counted_class will be destroyed
shmem.destroy_ptr(intrusive_owner_array);
//Now destroy the array of intrusive pointer owners
//This should destroy every intrusive_ptr and because of
//that reference_counted_class will be destroyed
shmem.destroy_ptr(intrusive_owner_array);
//Now the reference counted object should have been destroyed
if(shmem.find<intrusive_ptr_owner>("ref_counted").first)
return 1;
}
catch(...){
shared_memory_object::remove("my_shmem");
throw;
}
shared_memory_object::remove("my_shmem");
//Now the reference counted object should have been destroyed
if(shmem.find<intrusive_ptr_owner>("ref_counted").first)
return 1;
//Success!
return 0;
}

View File

@@ -0,0 +1,72 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2006-2007. 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/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
//[run_ipc_message
#include <boost/interprocess/managed_shared_memory.hpp>
#include <cstdlib> //std::system
#include <sstream>
int main (int argc, char *argv[])
{
using namespace boost::interprocess;
if(argc == 1){ //Parent process
//Remove shared memory on construction and destruction
struct shm_remove
{
shm_remove() { shared_memory_object::remove("MySharedMemory"); }
~shm_remove(){ shared_memory_object::remove("MySharedMemory"); }
} remover;
//Create a managed shared memory segment
managed_shared_memory segment(create_only, "MySharedMemory", 65536);
//Allocate a portion of the segment (raw memory)
std::size_t free_memory = segment.get_free_memory();
void * shptr = segment.allocate(1024/*bytes to allocate*/);
//Check invariant
if(free_memory <= segment.get_free_memory())
return 1;
//An handle from the base address can identify any byte of the shared
//memory segment even if it is mapped in different base addresses
managed_shared_memory::handle_t handle = segment.get_handle_from_address(shptr);
std::stringstream s;
s << argv[0] << " " << handle << std::ends;
//Launch child process
if(0 != std::system(s.str().c_str()))
return 1;
//Check memory has been freed
if(free_memory != segment.get_free_memory())
return 1;
}
else{
//Open managed segment
managed_shared_memory segment(open_only, "MySharedMemory");
//An handle from the base address can identify any byte of the shared
//memory segment even if it is mapped in different base addresses
managed_shared_memory::handle_t handle = 0;
//Obtain handle value
std::stringstream s; s << argv[1]; s >> handle;
//Get buffer local address from handle
void *msg = segment.get_address_from_handle(handle);
//Deallocate previously allocated memory
segment.deallocate(msg);
}
return 0;
}
//]
#include <boost/interprocess/detail/config_end.hpp>

View File

@@ -1,55 +0,0 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2006-2007. 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/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
//[doc_ipc_messageA
#include <boost/interprocess/managed_shared_memory.hpp>
int main ()
{
using namespace boost::interprocess;
//A special shared memory from which we are
//able to allocate raw memory buffers.
//First remove any old shared memory of the same name, create
//the shared memory segment and initialize needed resources
shared_memory_object::remove("MySharedMemory");
try{
managed_shared_memory segment
(create_only,
"MySharedMemory", //segment name
65536); //segment size in bytes
//Allocate a portion of the segment
void * shptr = segment.allocate(1024/*bytes to allocate*/);
//An handle from the base address can identify any byte of the shared
//memory segment even if it is mapped in different base addresses
managed_shared_memory::handle_t handle = segment.get_handle_from_address(shptr);
(void)handle;
// Copy message to buffer
// . . .
// Send handle to other process
// . . .
// Wait response from other process
// . . .
//Deallocate the portion previously allocated
segment.deallocate(shptr);
}
catch(...){
shared_memory_object::remove("MySharedMemory");
throw;
}
shared_memory_object::remove("MySharedMemory");
return 0;
}
//]
#include <boost/interprocess/detail/config_end.hpp>

View File

@@ -1,47 +0,0 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2006-2007. 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/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
//[doc_ipc_messageB
#include <boost/interprocess/managed_shared_memory.hpp>
int main ()
{
using namespace boost::interprocess;
try{
//A special shared memory from which we are
//able to allocate raw memory buffers.
//Connect to the already created shared memory segment
//and initialize needed resources
managed_shared_memory segment(open_only, "MySharedMemory"); //segment name
//An handle from the base address can identify any byte of the shared
//memory segment even if it is mapped in different base addresses
managed_shared_memory::handle_t handle = 0;
//Wait handle msg from the other process and put it in
//"handle" local variable
//Get buffer local address from handle
void *msg = segment.get_address_from_handle(handle);
(void)msg;
//Do anything with msg
//. . .
//Send ack to sender process
}
catch(...){
shared_memory_object::remove("MySharedMemory");
throw;
}
shared_memory_object::remove("MySharedMemory");
return 0;
}
//]
#include <boost/interprocess/detail/config_end.hpp>

View File

@@ -16,53 +16,52 @@ int main()
{
using namespace boost::interprocess;
//Remove shared memory on construction and destruction
struct shm_destroy
{
shm_destroy() { shared_memory_object::remove("MySharedMemory"); }
~shm_destroy(){ shared_memory_object::remove("MySharedMemory"); }
} remover;
//Managed memory segment that allocates portions of a shared memory
//segment with the default management algorithm
shared_memory_object::remove("MyManagedShm");
managed_shared_memory managed_shm(create_only, "MySharedMemory", 65536);
try{
managed_shared_memory managed_shm(create_only, "MyManagedShm", 65536);
const std::size_t Alignment = 128;
const std::size_t Alignment = 128;
//Allocate 100 bytes aligned to Alignment from segment, throwing version
void *ptr = managed_shm.allocate_aligned(100, Alignment);
//Allocate 100 bytes aligned to Alignment from segment, throwing version
void *ptr = managed_shm.allocate_aligned(100, Alignment);
//Check alignment
assert((static_cast<char*>(ptr)-static_cast<char*>(0)) % Alignment == 0);
//Check alignment
assert((static_cast<char*>(ptr)-static_cast<char*>(0)) % Alignment == 0);
//Deallocate it
managed_shm.deallocate(ptr);
//Deallocate it
managed_shm.deallocate(ptr);
//Non throwing version
ptr = managed_shm.allocate_aligned(100, Alignment, std::nothrow);
//Non throwing version
ptr = managed_shm.allocate_aligned(100, Alignment, std::nothrow);
//Check alignment
assert((static_cast<char*>(ptr)-static_cast<char*>(0)) % Alignment == 0);
//Check alignment
assert((static_cast<char*>(ptr)-static_cast<char*>(0)) % Alignment == 0);
//Deallocate it
managed_shm.deallocate(ptr);
//Deallocate it
managed_shm.deallocate(ptr);
//If we want to efficiently allocate aligned blocks of memory
//use managed_shared_memory::PayloadPerAllocation value
assert(Alignment > managed_shared_memory::PayloadPerAllocation);
//If we want to efficiently allocate aligned blocks of memory
//use managed_shared_memory::PayloadPerAllocation value
assert(Alignment > managed_shared_memory::PayloadPerAllocation);
//This allocation will maximize the size of the aligned memory
//and will increase the possibility of finding more aligned memory
ptr = managed_shm.allocate_aligned
(3*Alignment - managed_shared_memory::PayloadPerAllocation, Alignment);
//This allocation will maximize the size of the aligned memory
//and will increase the possibility of finding more aligned memory
ptr = managed_shm.allocate_aligned
(3*Alignment - managed_shared_memory::PayloadPerAllocation, Alignment);
//Check alignment
assert((static_cast<char*>(ptr)-static_cast<char*>(0)) % Alignment == 0);
//Check alignment
assert((static_cast<char*>(ptr)-static_cast<char*>(0)) % Alignment == 0);
//Deallocate it
managed_shm.deallocate(ptr);
//Deallocate it
managed_shm.deallocate(ptr);
}
catch(...){
shared_memory_object::remove("MyManagedShm");
throw;
}
shared_memory_object::remove("MyManagedShm");
return 0;
}
//]

View File

@@ -16,73 +16,71 @@ int main()
{
using namespace boost::interprocess;
//Remove shared memory on construction and destruction
struct shm_destroy
{
shm_destroy() { shared_memory_object::remove("MySharedMemory"); }
~shm_destroy(){ shared_memory_object::remove("MySharedMemory"); }
} remover;
//Managed memory segment that allocates portions of a shared memory
//segment with the default management algorithm
shared_memory_object::remove("MyManagedShm");
managed_shared_memory managed_shm(create_only, "MySharedMemory", 10000*sizeof(std::size_t));
try{
managed_shared_memory managed_shm(create_only, "MyManagedShm", 10000*sizeof(std::size_t));
//Allocate at least 100 bytes, 1000 bytes if possible
std::size_t received_size, min_size = 100, preferred_size = 1000;
std::size_t *ptr = managed_shm.allocation_command<std::size_t>
(boost::interprocess::allocate_new, min_size, preferred_size, received_size).first;
//Allocate at least 100 bytes, 1000 bytes if possible
std::size_t received_size, min_size = 100, preferred_size = 1000;
std::size_t *ptr = managed_shm.allocation_command<std::size_t>
(allocate_new, min_size, preferred_size, received_size).first;
//Received size must be bigger than min_size
assert(received_size >= min_size);
//Received size must be bigger than min_size
assert(received_size >= min_size);
//Get free memory
std::size_t free_memory_after_allocation = managed_shm.get_free_memory();
//Get free memory
std::size_t free_memory_after_allocation = managed_shm.get_free_memory();
//Now write the data
for(std::size_t i = 0; i < received_size; ++i) ptr[i] = i;
//Now write the data
for(std::size_t i = 0; i < received_size; ++i) ptr[i] = i;
//Now try to triplicate the buffer. We won't admit an expansion
//lower to the double of the original buffer.
//This "should" be successful since no other class is allocating
//memory from the segment
std::size_t expanded_size;
std::pair<std::size_t *, bool> ret = managed_shm.allocation_command
(boost::interprocess::expand_fwd, received_size*2, received_size*3, expanded_size, ptr);
//Now try to triplicate the buffer. We won't admit an expansion
//lower to the double of the original buffer.
//This "should" be successful since no other class is allocating
//memory from the segment
std::size_t expanded_size;
std::pair<std::size_t *, bool> ret = managed_shm.allocation_command
(expand_fwd, received_size*2, received_size*3, expanded_size, ptr);
//Check invariants
assert(ret.second == true);
assert(ret.first == ptr);
assert(expanded_size >= received_size*2);
//Check invariants
assert(ret.second == true);
assert(ret.first == ptr);
assert(expanded_size >= received_size*2);
//Get free memory and compare
std::size_t free_memory_after_expansion = managed_shm.get_free_memory();
assert(free_memory_after_expansion < free_memory_after_allocation);
//Get free memory and compare
std::size_t free_memory_after_expansion = managed_shm.get_free_memory();
assert(free_memory_after_expansion < free_memory_after_allocation);
//Write new values
for(std::size_t i = received_size; i < expanded_size; ++i) ptr[i] = i;
//Write new values
for(std::size_t i = received_size; i < expanded_size; ++i) ptr[i] = i;
//Try to shrink approximately to min_size, but the new size
//should be smaller than min_size*2.
//This "should" be successful since no other class is allocating
//memory from the segment
std::size_t shrunk_size;
ret = managed_shm.allocation_command
(boost::interprocess::shrink_in_place, min_size*2, min_size, shrunk_size, ptr);
//Try to shrink approximately to min_size, but the new size
//should be smaller than min_size*2.
//This "should" be successful since no other class is allocating
//memory from the segment
std::size_t shrunk_size;
ret = managed_shm.allocation_command
(shrink_in_place, min_size*2, min_size, shrunk_size, ptr);
//Check invariants
assert(ret.second == true);
assert(ret.first == ptr);
assert(shrunk_size <= min_size*2);
assert(shrunk_size >= min_size);
//Check invariants
assert(ret.second == true);
assert(ret.first == ptr);
assert(shrunk_size <= min_size*2);
assert(shrunk_size >= min_size);
//Get free memory and compare
std::size_t free_memory_after_shrinking = managed_shm.get_free_memory();
assert(free_memory_after_shrinking > free_memory_after_expansion);
//Get free memory and compare
std::size_t free_memory_after_shrinking = managed_shm.get_free_memory();
assert(free_memory_after_shrinking > free_memory_after_expansion);
//Deallocate the buffer
managed_shm.deallocate(ptr);
}
catch(...){
shared_memory_object::remove("MyManagedShm");
throw;
}
shared_memory_object::remove("MyManagedShm");
//Deallocate the buffer
managed_shm.deallocate(ptr);
return 0;
}
//]

View File

@@ -21,41 +21,39 @@ class my_class
int main()
{
using namespace boost::interprocess;
typedef managed_shared_memory msm;
shared_memory_object::remove("MyManagedShm");
try{
msm managed_shm(create_only, "MyManagedShm", 10000*sizeof(std::size_t));
//Remove shared memory on construction and destruction
struct shm_destroy
{
shm_destroy() { shared_memory_object::remove("MySharedMemory"); }
~shm_destroy(){ shared_memory_object::remove("MySharedMemory"); }
} remover;
//Construct objects
my_class *named_object = managed_shm.construct<my_class>("Object name")[1]();
my_class *unique_object = managed_shm.construct<my_class>(unique_instance)[2]();
my_class *anon_object = managed_shm.construct<my_class>(anonymous_instance)[3]();
managed_shared_memory managed_shm(create_only, "MySharedMemory", 10000*sizeof(std::size_t));
//Now test "get_instance_name" function.
assert(0 == std::strcmp(msm::get_instance_name(named_object), "Object name"));
assert(0 == msm::get_instance_name(unique_object));
assert(0 == msm::get_instance_name(anon_object));
//Construct objects
my_class *named_object = managed_shm.construct<my_class>("Object name")[1]();
my_class *unique_object = managed_shm.construct<my_class>(unique_instance)[2]();
my_class *anon_object = managed_shm.construct<my_class>(anonymous_instance)[3]();
//Now test "get_instance_type" function.
assert(named_type == msm::get_instance_type(named_object));
assert(unique_type == msm::get_instance_type(unique_object));
assert(anonymous_type == msm::get_instance_type(anon_object));
//Now test "get_instance_name" function.
assert(0 == std::strcmp(managed_shared_memory::get_instance_name(named_object), "Object name"));
assert(0 == managed_shared_memory::get_instance_name(unique_object));
assert(0 == managed_shared_memory::get_instance_name(anon_object));
//Now test "get_instance_length" function.
assert(1 == msm::get_instance_length(named_object));
assert(2 == msm::get_instance_length(unique_object));
assert(3 == msm::get_instance_length(anon_object));
//Now test "get_instance_type" function.
assert(named_type == managed_shared_memory::get_instance_type(named_object));
assert(unique_type == managed_shared_memory::get_instance_type(unique_object));
assert(anonymous_type == managed_shared_memory::get_instance_type(anon_object));
managed_shm.destroy_ptr(named_object);
managed_shm.destroy_ptr(unique_object);
managed_shm.destroy_ptr(anon_object);
}
catch(...){
shared_memory_object::remove("MyManagedShm");
throw;
}
shared_memory_object::remove("MyManagedShm");
//Now test "get_instance_length" function.
assert(1 == managed_shared_memory::get_instance_length(named_object));
assert(2 == managed_shared_memory::get_instance_length(unique_object));
assert(3 == managed_shared_memory::get_instance_length(anon_object));
managed_shm.destroy_ptr(named_object);
managed_shm.destroy_ptr(unique_object);
managed_shm.destroy_ptr(anon_object);
return 0;
}
//]

View File

@@ -11,7 +11,6 @@
//[doc_managed_copy_on_write
#include <boost/interprocess/managed_mapped_file.hpp>
#include <fstream> //std::fstream
#include <cstdio> //std::remove
#include <iterator>//std::distance
int main()
@@ -19,8 +18,8 @@ int main()
using namespace boost::interprocess;
//Try to erase any previous managed segment with the same name
std::remove("MyManagedFile");
std::remove("MyManagedFile2");
file_mapping::remove("MyManagedFile");
file_mapping::remove("MyManagedFile2");
remove_file_on_destroy destroyer1("MyManagedFile");
remove_file_on_destroy destroyer2("MyManagedFile2");

View File

@@ -43,7 +43,9 @@ int main()
//be stored in the static_buffer!
MyBufferList *list = objects_in_static_memory.construct<MyBufferList>(L"MyList")
(objects_in_static_memory.get_segment_manager());
//<-
(void)list;
//->
//Since the allocation algorithm from wmanaged_external_buffer uses relative
//pointers and all the pointers constructed int the static memory point
//to objects in the same segment, we can create another static buffer

View File

@@ -21,48 +21,49 @@ class MyClass
int main()
{
using namespace boost::interprocess;
try{
{ //Remove old shared memory if present
shared_memory_object::remove("MyManagedShm");
//Create a managed shared memory
managed_shared_memory shm(create_only, "MyManagedShm", 1000);
//Check size
assert(shm.get_size() == 1000);
//Construct a named object
MyClass *myclass = shm.construct<MyClass>("MyClass")();
//The managed segment is unmapped here
}
{
//Now that the segment is not mapped grow it adding extra 500 bytes
managed_shared_memory::grow("MyManagedShm", 500);
//Map it again
managed_shared_memory shm(open_only, "MyManagedShm");
//Check size
assert(shm.get_size() == 1500);
//Check "MyClass" is still there
MyClass *myclass = shm.find<MyClass>("MyClass").first;
assert(myclass != 0);
//The managed segment is unmapped here
}
{
//Now minimize the size of the segment
managed_shared_memory::shrink_to_fit("MyManagedShm");
//Map it again
managed_shared_memory shm(open_only, "MyManagedShm");
//Check size
assert(shm.get_size() < 1000);
//Check "MyClass" is still there
MyClass *myclass = shm.find<MyClass>("MyClass").first;
assert(myclass != 0);
//The managed segment is unmapped here
}
//Remove shared memory on construction and destruction
struct shm_destroy
{
shm_destroy() { shared_memory_object::remove("MySharedMemory"); }
~shm_destroy(){ shared_memory_object::remove("MySharedMemory"); }
} remover;
{
//Create a managed shared memory
managed_shared_memory shm(create_only, "MySharedMemory", 1000);
//Check size
assert(shm.get_size() == 1000);
//Construct a named object
MyClass *myclass = shm.construct<MyClass>("MyClass")();
//The managed segment is unmapped here
//<-
(void)myclass;
//->
}
catch(...){
shared_memory_object::remove("MyManagedShm");
throw;
{
//Now that the segment is not mapped grow it adding extra 500 bytes
managed_shared_memory::grow("MySharedMemory", 500);
//Map it again
managed_shared_memory shm(open_only, "MySharedMemory");
//Check size
assert(shm.get_size() == 1500);
//Check "MyClass" is still there
MyClass *myclass = shm.find<MyClass>("MyClass").first;
assert(myclass != 0);
//The managed segment is unmapped here
}
{
//Now minimize the size of the segment
managed_shared_memory::shrink_to_fit("MySharedMemory");
//Map it again
managed_shared_memory shm(open_only, "MySharedMemory");
//Check size
assert(shm.get_size() < 1000);
//Check "MyClass" is still there
MyClass *myclass = shm.find<MyClass>("MyClass").first;
assert(myclass != 0);
//The managed segment is unmapped here
}
//Remove the managed segment
shared_memory_object::remove("MyManagedShm");
return 0;
}
//]

View File

@@ -24,59 +24,67 @@ int main ()
{
const char *FileName = "file_mapping";
const std::size_t FileSize = 1000;
std::remove(FileName);
file_mapping::remove(FileName);
try{
managed_mapped_file mfile_memory(create_only, FileName, FileSize);
MyList * mylist = mfile_memory.construct<MyList>("MyList")
(mfile_memory.get_segment_manager());
std::size_t old_size = 0;
managed_mapped_file::handle_t list_handle;
{
managed_mapped_file mfile_memory(create_only, FileName, FileSize);
MyList *mylist = mfile_memory.construct<MyList>("MyList")
(mfile_memory.get_segment_manager());
//Obtain handle, that identifies the list in the buffer
managed_mapped_file::handle_t list_handle = mfile_memory.get_handle_from_address(mylist);
//Obtain handle, that identifies the list in the buffer
list_handle = mfile_memory.get_handle_from_address(mylist);
//Fill list until there is no more room in the file
try{
while(1) {
mylist->insert(mylist->begin(), 0);
//Fill list until there is no more room in the file
try{
while(1) {
mylist->insert(mylist->begin(), 0);
}
}
catch(const bad_alloc &){
//mapped file is full
}
//Let's obtain the size of the list
old_size = mylist->size();
}
catch(const bad_alloc &){
//mapped file is full
}
//Let's obtain the size of the list
std::size_t old_size = mylist->size();
//To make the list bigger, let's increase the mapped file
//in FileSize bytes more.
//mfile_memory.grow(FileSize);
managed_mapped_file::grow(FileName, FileSize*2);
//If mapping address has changed, the old pointer is invalid,
//so use previously obtained handle to find the new pointer.
mylist = static_cast<MyList *>
(mfile_memory.get_address_from_handle(list_handle));
//Fill list until there is no more room in the file
try{
while(1) {
mylist->insert(mylist->begin(), 0);
{
managed_mapped_file mfile_memory(open_only, FileName);
//If mapping address has changed, the old pointer is invalid,
//so use previously obtained handle to find the new pointer.
MyList *mylist = static_cast<MyList *>
(mfile_memory.get_address_from_handle(list_handle));
//Fill list until there is no more room in the file
try{
while(1) {
mylist->insert(mylist->begin(), 0);
}
}
catch(const bad_alloc &){
//mapped file is full
}
//Let's obtain the new size of the list
std::size_t new_size = mylist->size();
assert(new_size > old_size);
//Destroy list
mfile_memory.destroy_ptr(mylist);
}
catch(const bad_alloc &){
//mapped file is full
}
//Let's obtain the new size of the list
std::size_t new_size = mylist->size();
assert(new_size > old_size);
//Destroy list
mfile_memory.destroy_ptr(mylist);
}
catch(...){
std::remove(FileName);
file_mapping::remove(FileName);
throw;
}
std::remove(FileName);
file_mapping::remove(FileName);
return 0;
}

View File

@@ -10,69 +10,59 @@
#include <boost/interprocess/detail/config_begin.hpp>
//[doc_managed_multiple_allocation
#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/detail/move.hpp> //boost::interprocess::move
#include <cassert>//assert
#include <cstring>//std::memset
#include <new> //std::nothrow
#include <vector> //std::vector
int main()
{
using namespace boost::interprocess;
typedef managed_shared_memory::multiallocation_iterator multiallocation_iterator;
typedef managed_shared_memory::multiallocation_chain multiallocation_chain;
//Try to erase any previous managed segment with the same name
shared_memory_object::remove("MyManagedShm");
//Remove shared memory on construction and destruction
struct shm_destroy
{
shm_destroy() { shared_memory_object::remove("MySharedMemory"); }
~shm_destroy(){ shared_memory_object::remove("MySharedMemory"); }
} remover;
try{
managed_shared_memory managed_shm(create_only, "MyManagedShm", 65536);
managed_shared_memory managed_shm(create_only, "MySharedMemory", 65536);
//Allocate 16 elements of 100 bytes in a single call. Non-throwing version.
multiallocation_iterator beg_it = managed_shm.allocate_many(100, 16, std::nothrow);
//Allocate 16 elements of 100 bytes in a single call. Non-throwing version.
multiallocation_chain chain(managed_shm.allocate_many(100, 16, std::nothrow));
//To check for an error, we can use a boolean expression
//or compare it with a default constructed iterator
assert(!beg_it == (beg_it == multiallocation_iterator()));
//Check if the memory allocation was successful
if(!beg_it) return 1;
//Check if the memory allocation was successful
if(chain.empty()) return 1;
//Allocated buffers
std::vector<char*> allocated_buffers;
//Allocated buffers
std::vector<void*> allocated_buffers;
//Initialize our data
for( multiallocation_iterator it = beg_it, end_it; it != end_it; ){
allocated_buffers.push_back(&*it);
//The iterator must be incremented before overwriting memory
//because otherwise, the iterator is invalidated.
std::memset(&*it++, 0, 100);
}
//Now deallocate
while(!allocated_buffers.empty()){
managed_shm.deallocate(allocated_buffers.back());
allocated_buffers.pop_back();
}
//Allocate 10 buffers of different sizes in a single call. Throwing version
std::size_t sizes[10];
for(std::size_t i = 0; i < 10; ++i)
sizes[i] = i*3;
beg_it = managed_shm.allocate_many(sizes, 10);
//Iterate each allocated buffer and deallocate
//The "end" condition can be also checked with operator!
for(multiallocation_iterator it = beg_it; it;){
//The iterator must be incremented before overwriting memory
//because otherwise, the iterator is invalidated.
managed_shm.deallocate(&*it++);
}
//Initialize our data
while(!chain.empty()){
void *buf = chain.front();
chain.pop_front();
allocated_buffers.push_back(buf);
//The iterator must be incremented before overwriting memory
//because otherwise, the iterator is invalidated.
std::memset(buf, 0, 100);
}
catch(...){
shared_memory_object::remove("MyManagedShm");
throw;
//Now deallocate
while(!allocated_buffers.empty()){
managed_shm.deallocate(allocated_buffers.back());
allocated_buffers.pop_back();
}
shared_memory_object::remove("MyManagedShm");
//Allocate 10 buffers of different sizes in a single call. Throwing version
std::size_t sizes[10];
for(std::size_t i = 0; i < 10; ++i)
sizes[i] = i*3;
chain = managed_shm.allocate_many(sizes, 10);
managed_shm.deallocate_many(boost::interprocess::move(chain));
return 0;
}
//]

View File

@@ -15,29 +15,28 @@ int main()
{
using namespace boost::interprocess;
//Remove shared memory on construction and destruction
struct shm_destroy
{
shm_destroy() { shared_memory_object::remove("MySharedMemory"); }
~shm_destroy(){ shared_memory_object::remove("MySharedMemory"); }
} remover;
//Managed memory segment that allocates portions of a shared memory
//segment with the default management algorithm
shared_memory_object::remove("MyManagedShm");
try{
managed_shared_memory managed_shm(create_only, "MyManagedShm", 65536);
managed_shared_memory managed_shm(create_only, "MySharedMemory", 65536);
//Allocate 100 bytes of memory from segment, throwing version
void *ptr = managed_shm.allocate(100);
//Allocate 100 bytes of memory from segment, throwing version
void *ptr = managed_shm.allocate(100);
//Deallocate it
managed_shm.deallocate(ptr);
//Deallocate it
managed_shm.deallocate(ptr);
//Non throwing version
ptr = managed_shm.allocate(100, std::nothrow);
//Non throwing version
ptr = managed_shm.allocate(100, std::nothrow);
//Deallocate it
managed_shm.deallocate(ptr);
}
catch(...){
shared_memory_object::remove("MyManagedShm");
throw;
}
shared_memory_object::remove("MyManagedShm");
//Deallocate it
managed_shm.deallocate(ptr);
return 0;
}
//]

View File

@@ -19,56 +19,55 @@
int main ()
{
using namespace boost::interprocess;
//Remove shared memory on construction and destruction
struct shm_destroy
{
shm_destroy() { shared_memory_object::remove("MySharedMemory"); }
~shm_destroy(){ shared_memory_object::remove("MySharedMemory"); }
} remover;
//Shared memory front-end that is able to construct objects
//associated with a c-string. Erase previous shared memory with the name
//to be used and create the memory segment at the specified address and initialize resources
shared_memory_object::remove("MySharedMemory");
managed_shared_memory segment
(create_only
,"MySharedMemory" //segment name
,65536); //segment size in bytes
try{
managed_shared_memory segment
(create_only
,"MySharedMemory" //segment name
,65536); //segment size in bytes
//Note that map<Key, MappedType>'s value_type is std::pair<const Key, MappedType>,
//so the allocator must allocate that pair.
typedef int KeyType;
typedef float MappedType;
typedef std::pair<const int, float> ValueType;
//Note that map<Key, MappedType>'s value_type is std::pair<const Key, MappedType>,
//so the allocator must allocate that pair.
typedef int KeyType;
typedef float MappedType;
typedef std::pair<const int, float> ValueType;
//Alias an STL compatible allocator of for the map.
//This allocator will allow to place containers
//in managed shared memory segments
typedef allocator<ValueType, managed_shared_memory::segment_manager>
ShmemAllocator;
//Alias an STL compatible allocator of for the map.
//This allocator will allow to place containers
//in managed shared memory segments
typedef allocator<ValueType, managed_shared_memory::segment_manager>
ShmemAllocator;
//Alias a map of ints that uses the previous STL-like allocator.
//Note that the third parameter argument is the ordering function
//of the map, just like with std::map, used to compare the keys.
typedef map<KeyType, MappedType, std::less<KeyType>, ShmemAllocator> MyMap;
//Alias a map of ints that uses the previous STL-like allocator.
//Note that the third parameter argument is the ordering function
//of the map, just like with std::map, used to compare the keys.
typedef map<KeyType, MappedType, std::less<KeyType>, ShmemAllocator> MyMap;
//Initialize the shared memory STL-compatible allocator
ShmemAllocator alloc_inst (segment.get_segment_manager());
//Initialize the shared memory STL-compatible allocator
ShmemAllocator alloc_inst (segment.get_segment_manager());
//Construct a shared memory map.
//Note that the first parameter is the comparison function,
//and the second one the allocator.
//This the same signature as std::map's constructor taking an allocator
MyMap *mymap =
segment.construct<MyMap>("MyMap") //object name
(std::less<int>() //first ctor parameter
,alloc_inst); //second ctor parameter
//Construct a shared memory map.
//Note that the first parameter is the comparison function,
//and the second one the allocator.
//This the same signature as std::map's constructor taking an allocator
MyMap *mymap =
segment.construct<MyMap>("MyMap") //object name
(std::less<int>() //first ctor parameter
,alloc_inst); //second ctor parameter
//Insert data in the map
for(int i = 0; i < 100; ++i){
mymap->insert(std::pair<const int, float>(i, (float)i));
}
//Insert data in the map
for(int i = 0; i < 100; ++i){
mymap->insert(std::pair<const int, float>(i, (float)i));
}
catch(...){
shared_memory_object::remove("MySharedMemory");
throw;
}
shared_memory_object::remove("MySharedMemory");
return 0;
}
//]

View File

@@ -28,58 +28,57 @@ int main ()
typedef allocator<MyShmString, SegmentManager> StringAllocator;
typedef vector<MyShmString, StringAllocator> MyShmStringVector;
//Remove old shared memory and create new one
shared_memory_object::remove("myshm");
try{
managed_shared_memory shm(create_only, "myshm", 10000);
//Remove shared memory on construction and destruction
struct shm_destroy
{
shm_destroy() { shared_memory_object::remove("MySharedMemory"); }
~shm_destroy(){ shared_memory_object::remove("MySharedMemory"); }
} remover;
//Create allocators
CharAllocator charallocator (shm.get_segment_manager());
StringAllocator stringallocator(shm.get_segment_manager());
managed_shared_memory shm(create_only, "MySharedMemory", 10000);
//Create a vector of strings in shared memory.
MyShmStringVector *myshmvector =
shm.construct<MyShmStringVector>("myshmvector")(stringallocator);
//Create allocators
CharAllocator charallocator (shm.get_segment_manager());
StringAllocator stringallocator(shm.get_segment_manager());
//Insert 50 strings in shared memory. The strings will be allocated
//only once and no string copy-constructor will be called when inserting
//strings, leading to a great performance.
MyShmString string_to_compare(charallocator);
string_to_compare = "this is a long, long, long, long, long, long, string...";
myshmvector->reserve(50);
for(int i = 0; i < 50; ++i){
MyShmString move_me(string_to_compare);
//In the following line, no string copy-constructor will be called.
//"move_me"'s contents will be transferred to the string created in
//the vector
myshmvector->push_back(boost::interprocess::move(move_me));
//Create a vector of strings in shared memory.
MyShmStringVector *myshmvector =
shm.construct<MyShmStringVector>("myshmvector")(stringallocator);
//The source string is in default constructed state
assert(move_me.empty());
//Insert 50 strings in shared memory. The strings will be allocated
//only once and no string copy-constructor will be called when inserting
//strings, leading to a great performance.
MyShmString string_to_compare(charallocator);
string_to_compare = "this is a long, long, long, long, long, long, string...";
myshmvector->reserve(50);
for(int i = 0; i < 50; ++i){
MyShmString move_me(string_to_compare);
//In the following line, no string copy-constructor will be called.
//"move_me"'s contents will be transferred to the string created in
//the vector
myshmvector->push_back(boost::interprocess::move(move_me));
//The newly created string will be equal to the "move_me"'s old contents
assert(myshmvector->back() == string_to_compare);
}
//The source string is in default constructed state
assert(move_me.empty());
//Now erase a string...
myshmvector->pop_back();
//...And insert one in the first position.
//No string copy-constructor or assignments will be called, but
//move constructors and move-assignments. No memory allocation
//function will be called in this operations!!
myshmvector->insert(myshmvector->begin(), boost::interprocess::move(string_to_compare));
//Destroy vector. This will free all strings that the vector contains
shm.destroy_ptr(myshmvector);
//The newly created string will be equal to the "move_me"'s old contents
assert(myshmvector->back() == string_to_compare);
}
catch(...){
shared_memory_object::remove("myshmvector");
throw;
}
shared_memory_object::remove("myshmvector");
//Now erase a string...
myshmvector->pop_back();
//...And insert one in the first position.
//No string copy-constructor or assignments will be called, but
//move constructors and move-assignments. No memory allocation
//function will be called in this operations!!
myshmvector->insert(myshmvector->begin(), boost::interprocess::move(string_to_compare));
//Destroy vector. This will free all strings that the vector contains
shm.destroy_ptr(myshmvector);
return 0;
}
//]
#include <boost/interprocess/detail/config_end.hpp>

View File

@@ -61,30 +61,27 @@ typedef bmi::multi_index_container<
int main ()
{
//Erase previous shared memory with the name
shared_memory_object::remove("MySharedMemory");
//Remove shared memory on construction and destruction
struct shm_destroy
{
shm_destroy() { shared_memory_object::remove("MySharedMemory"); }
~shm_destroy(){ shared_memory_object::remove("MySharedMemory"); }
} remover;
try{
//Create shared memory
managed_shared_memory segment(create_only,"MySharedMemory", 65536);
//Create shared memory
managed_shared_memory segment(create_only,"MySharedMemory", 65536);
//Construct the multi_index in shared memory
employee_set *es = segment.construct<employee_set>
("My MultiIndex Container") //Container's name in shared memory
( employee_set::ctor_args_list()
, segment.get_allocator<employee>()); //Ctor parameters
//Construct the multi_index in shared memory
employee_set *es = segment.construct<employee_set>
("My MultiIndex Container") //Container's name in shared memory
( employee_set::ctor_args_list()
, segment.get_allocator<employee>()); //Ctor parameters
//Now insert elements
char_allocator ca(segment.get_allocator<char>());
es->insert(employee(0,31, "Joe", ca));
es->insert(employee(1,27, "Robert", ca));
es->insert(employee(2,40, "John", ca));
}
catch(...){
shared_memory_object::remove("MySharedMemory");
throw;
}
shared_memory_object::remove("MySharedMemory");
//Now insert elements
char_allocator ca(segment.get_allocator<char>());
es->insert(employee(0,31, "Joe", ca));
es->insert(employee(1,27, "Robert", ca));
es->insert(employee(2,40, "John", ca));
return 0;
}
//]

View File

@@ -9,24 +9,28 @@
//////////////////////////////////////////////////////////////////////////////
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
//[doc_named_allocA
//[doc_named_alloc
#include <boost/interprocess/managed_shared_memory.hpp>
#include <cstdlib> //std::system
#include <cstddef>
#include <cassert>
#include <utility>
int main ()
int main(int argc, char *argv[])
{
using namespace boost::interprocess;
typedef std::pair<double, int> MyType;
try{
//A special shared memory where we can
//construct objects associated with a name.
//First remove any old shared memory of the same name, create
//the shared memory segment and initialize needed resources
shared_memory_object::remove("MySharedMemory");
managed_shared_memory segment
//create segment name segment size
(create_only, "MySharedMemory", 65536);
if(argc == 1){ //Parent process
//Remove shared memory on construction and destruction
struct shm_remove
{
shm_remove() { shared_memory_object::remove("MySharedMemory"); }
~shm_remove(){ shared_memory_object::remove("MySharedMemory"); }
} remover;
//Construct managed shared memory
managed_shared_memory segment(create_only, "MySharedMemory", 65536);
//Create an object of MyType initialized to {0.0, 0}
MyType *instance = segment.construct<MyType>
@@ -49,12 +53,50 @@ int main ()
[3] //number of elements
( &float_initializer[0] //Iterator for the 1st ctor argument
, &int_initializer[0]); //Iterator for the 2nd ctor argument
//Launch child process
std::string s(argv[0]); s += " child";
if(0 != std::system(s.c_str()))
return 1;
//<-
(void)instance;
(void)array;
(void)array_it;
//->
//Check child has destroyed all objects
if(segment.find<MyType>("MyType array").first ||
segment.find<MyType>("MyType instance").first ||
segment.find<MyType>("MyType array from it").first)
return 1;
}
catch(...){
shared_memory_object::remove("MySharedMemory");
throw;
else{
//Open managed shared memory
managed_shared_memory segment(open_only, "MySharedMemory");
std::pair<MyType*, std::size_t> res;
//Find the array
res = segment.find<MyType> ("MyType array");
//Length should be 10
if(res.second != 10) return 1;
//Find the object
res = segment.find<MyType> ("MyType instance");
//Length should be 1
if(res.second != 1) return 1;
//Find the array constructed from iterators
res = segment.find<MyType> ("MyType array from it");
//Length should be 3
if(res.second != 3) return 1;
//We're done, delete all the objects
segment.destroy<MyType>("MyType array");
segment.destroy<MyType>("MyType instance");
segment.destroy<MyType>("MyType array from it");
}
shared_memory_object::remove("MySharedMemory");
return 0;
}
//]

View File

@@ -1,63 +0,0 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2006-2007. 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/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
//[doc_named_allocB
#include <boost/interprocess/managed_shared_memory.hpp>
#include <cstddef>
#include <utility>
#include <cassert>
int main ()
{
using namespace boost::interprocess;
typedef std::pair<double, int> MyType;
try{
//A special shared memory where we can
//construct objects associated with a name.
//Connect to the already created shared memory segment
//and initialize needed resources
managed_shared_memory segment(open_only, "MySharedMemory");
std::pair<MyType*, std::size_t> res;
//Find the array
res = segment.find<MyType> ("MyType array");
//Length should be 10
assert(res.second == 10);
//Find the object
res = segment.find<MyType> ("MyType instance");
//Length should be 1
assert(res.second == 1);
//Find the array constructed from iterators
res = segment.find<MyType> ("MyType array from it");
//Length should be 3
assert(res.second == 3);
//Use data
// . . .
//We're done, delete all the objects
segment.destroy<MyType>("MyType array");
segment.destroy<MyType>("MyType instance");
segment.destroy<MyType>("MyType array from it");
}
catch(...){
shared_memory_object::remove("MySharedMemory");
throw;
}
shared_memory_object::remove("MySharedMemory");
return 0;
}
//]
#include <boost/interprocess/detail/config_end.hpp>

View File

@@ -13,6 +13,7 @@
#include <boost/interprocess/sync/named_mutex.hpp>
#include <fstream>
#include <iostream>
#include <cstdio>
int main ()
{
@@ -37,10 +38,12 @@ int main ()
}
catch(interprocess_exception &ex){
named_mutex::remove("fstream_named_mutex");
std::remove("file_name");
std::cout << ex.what() << std::endl;
return 1;
}
named_mutex::remove("fstream_named_mutex");
std::remove("file_name");
return 0;
}
//]

View File

@@ -18,46 +18,44 @@ using namespace boost::interprocess;
int main ()
{
shared_memory_object::remove("MySharedMemory");
//Remove shared memory on construction and destruction
struct shm_destroy
{
shm_destroy() { shared_memory_object::remove("MySharedMemory"); }
~shm_destroy(){ shared_memory_object::remove("MySharedMemory"); }
} remover;
try{
//Create shared memory
managed_shared_memory segment(create_only,
"MySharedMemory", //segment name
65536);
//Create shared memory
managed_shared_memory segment(create_only,
"MySharedMemory", //segment name
65536);
//Create a node_allocator that allocates ints from the managed segment
//The number of chunks per segment is the default value
typedef node_allocator<int, managed_shared_memory::segment_manager>
node_allocator_t;
node_allocator_t allocator_instance(segment.get_segment_manager());
//Create a node_allocator that allocates ints from the managed segment
//The number of chunks per segment is the default value
typedef node_allocator<int, managed_shared_memory::segment_manager>
node_allocator_t;
node_allocator_t allocator_instance(segment.get_segment_manager());
//Create another node_allocator. Since the segment manager address
//is the same, this node_allocator will be
//attached to the same pool so "allocator_instance2" can deallocate
//nodes allocated by "allocator_instance"
node_allocator_t allocator_instance2(segment.get_segment_manager());
//Create another node_allocator. Since the segment manager address
//is the same, this node_allocator will be
//attached to the same pool so "allocator_instance2" can deallocate
//nodes allocated by "allocator_instance"
node_allocator_t allocator_instance2(segment.get_segment_manager());
//Create another node_allocator using copy-constructor. This
//node_allocator will also be attached to the same pool
node_allocator_t allocator_instance3(allocator_instance2);
//Create another node_allocator using copy-constructor. This
//node_allocator will also be attached to the same pool
node_allocator_t allocator_instance3(allocator_instance2);
//All allocators are equal
assert(allocator_instance == allocator_instance2);
assert(allocator_instance2 == allocator_instance3);
//All allocators are equal
assert(allocator_instance == allocator_instance2);
assert(allocator_instance2 == allocator_instance3);
//So memory allocated with one can be deallocated with another
allocator_instance2.deallocate(allocator_instance.allocate(1), 1);
allocator_instance3.deallocate(allocator_instance2.allocate(1), 1);
//So memory allocated with one can be deallocated with another
allocator_instance2.deallocate(allocator_instance.allocate(1), 1);
allocator_instance3.deallocate(allocator_instance2.allocate(1), 1);
//The common pool will be destroyed here, since no allocator is
//attached to the pool
}
catch(...){
shared_memory_object::remove("MySharedMemory");
throw;
}
shared_memory_object::remove("MySharedMemory");
//The common pool will be destroyed here, since no allocator is
//attached to the pool
return 0;
}
//]

View File

@@ -24,45 +24,41 @@ struct list_node
int main ()
{
//Destroy any previous shared memory with the name to be used.
//Create a special shared memory from which we can
//allocate buffers of raw memory.
shared_memory_object::remove("MySharedMemory");
try{
managed_shared_memory segment(
create_only,
"MySharedMemory", //segment name
65536); //segment size in bytes
//Remove shared memory on construction and destruction
struct shm_destroy
{
shm_destroy() { shared_memory_object::remove("MySharedMemory"); }
~shm_destroy(){ shared_memory_object::remove("MySharedMemory"); }
} remover;
//Create linked list with 10 nodes in shared memory
offset_ptr<list_node> prev = 0, current, first;
managed_shared_memory segment(
create_only,
"MySharedMemory", //segment name
65536); //segment size in bytes
int i;
for(i = 0; i < 10; ++i, prev = current){
current = static_cast<list_node*>(segment.allocate(sizeof(list_node)));
current->value = i;
current->next = 0;
//Create linked list with 10 nodes in shared memory
offset_ptr<list_node> prev = 0, current, first;
if(!prev)
first = current;
else
prev->next = current;
}
int i;
for(i = 0; i < 10; ++i, prev = current){
current = static_cast<list_node*>(segment.allocate(sizeof(list_node)));
current->value = i;
current->next = 0;
//Communicate list to other processes
//. . .
//When done, destroy list
for(current = first; current; /**/){
prev = current;
current = current->next;
segment.deallocate(prev.get());
}
if(!prev)
first = current;
else
prev->next = current;
}
catch(...){
shared_memory_object::remove("MySharedMemory");
throw;
//Communicate list to other processes
//. . .
//When done, destroy list
for(current = first; current; /**/){
prev = current;
current = current->next;
segment.deallocate(prev.get());
}
shared_memory_object::remove("MySharedMemory");
return 0;
}
//]

View File

@@ -18,42 +18,40 @@ using namespace boost::interprocess;
int main ()
{
shared_memory_object::remove("MySharedMemory");
//Remove shared memory on construction and destruction
struct shm_destroy
{
shm_destroy() { shared_memory_object::remove("MySharedMemory"); }
~shm_destroy(){ shared_memory_object::remove("MySharedMemory"); }
} remover;
try{
//Create shared memory
managed_shared_memory segment(create_only,
"MySharedMemory", //segment name
65536);
//Create shared memory
managed_shared_memory segment(create_only,
"MySharedMemory", //segment name
65536);
//Create a private_adaptive_pool that allocates ints from the managed segment
//The number of chunks per segment is the default value
typedef private_adaptive_pool<int, managed_shared_memory::segment_manager>
private_adaptive_pool_t;
private_adaptive_pool_t allocator_instance(segment.get_segment_manager());
//Create a private_adaptive_pool that allocates ints from the managed segment
//The number of chunks per segment is the default value
typedef private_adaptive_pool<int, managed_shared_memory::segment_manager>
private_adaptive_pool_t;
private_adaptive_pool_t allocator_instance(segment.get_segment_manager());
//Create another private_adaptive_pool.
private_adaptive_pool_t allocator_instance2(segment.get_segment_manager());
//Create another private_adaptive_pool.
private_adaptive_pool_t allocator_instance2(segment.get_segment_manager());
//Although the segment manager address
//is the same, this private_adaptive_pool will have its own pool so
//"allocator_instance2" CAN'T deallocate nodes allocated by "allocator_instance".
//"allocator_instance2" is NOT equal to "allocator_instance"
assert(allocator_instance != allocator_instance2);
//Although the segment manager address
//is the same, this private_adaptive_pool will have its own pool so
//"allocator_instance2" CAN'T deallocate nodes allocated by "allocator_instance".
//"allocator_instance2" is NOT equal to "allocator_instance"
assert(allocator_instance != allocator_instance2);
//Create another adaptive_pool using copy-constructor.
private_adaptive_pool_t allocator_instance3(allocator_instance2);
//Create another adaptive_pool using copy-constructor.
private_adaptive_pool_t allocator_instance3(allocator_instance2);
//This allocator is also unequal to allocator_instance2
assert(allocator_instance2 != allocator_instance3);
//This allocator is also unequal to allocator_instance2
assert(allocator_instance2 != allocator_instance3);
//Pools are destroyed with the allocators
}
catch(...){
shared_memory_object::remove("MySharedMemory");
throw;
}
shared_memory_object::remove("MySharedMemory");
//Pools are destroyed with the allocators
return 0;
}
//]

View File

@@ -18,42 +18,40 @@ using namespace boost::interprocess;
int main ()
{
shared_memory_object::remove("MySharedMemory");
//Remove shared memory on construction and destruction
struct shm_destroy
{
shm_destroy() { shared_memory_object::remove("MySharedMemory"); }
~shm_destroy(){ shared_memory_object::remove("MySharedMemory"); }
} remover;
try{
//Create shared memory
managed_shared_memory segment(create_only,
"MySharedMemory", //segment name
65536);
//Create shared memory
managed_shared_memory segment(create_only,
"MySharedMemory", //segment name
65536);
//Create a private_node_allocator that allocates ints from the managed segment
//The number of chunks per segment is the default value
typedef private_node_allocator<int, managed_shared_memory::segment_manager>
private_node_allocator_t;
private_node_allocator_t allocator_instance(segment.get_segment_manager());
//Create a private_node_allocator that allocates ints from the managed segment
//The number of chunks per segment is the default value
typedef private_node_allocator<int, managed_shared_memory::segment_manager>
private_node_allocator_t;
private_node_allocator_t allocator_instance(segment.get_segment_manager());
//Create another private_node_allocator.
private_node_allocator_t allocator_instance2(segment.get_segment_manager());
//Create another private_node_allocator.
private_node_allocator_t allocator_instance2(segment.get_segment_manager());
//Although the segment manager address
//is the same, this private_node_allocator will have its own pool so
//"allocator_instance2" CAN'T deallocate nodes allocated by "allocator_instance".
//"allocator_instance2" is NOT equal to "allocator_instance"
assert(allocator_instance != allocator_instance2);
//Although the segment manager address
//is the same, this private_node_allocator will have its own pool so
//"allocator_instance2" CAN'T deallocate nodes allocated by "allocator_instance".
//"allocator_instance2" is NOT equal to "allocator_instance"
assert(allocator_instance != allocator_instance2);
//Create another node_allocator using copy-constructor.
private_node_allocator_t allocator_instance3(allocator_instance2);
//Create another node_allocator using copy-constructor.
private_node_allocator_t allocator_instance3(allocator_instance2);
//This allocator is also unequal to allocator_instance2
assert(allocator_instance2 != allocator_instance3);
//This allocator is also unequal to allocator_instance2
assert(allocator_instance2 != allocator_instance3);
//Pools are destroyed with the allocators
}
catch(...){
shared_memory_object::remove("MySharedMemory");
throw;
}
shared_memory_object::remove("MySharedMemory");
//Pools are destroyed with the allocators
return 0;
}
//]

View File

@@ -47,60 +47,59 @@ class my_deleter
int main ()
{
//Create shared memory
shared_memory_object::remove("my_shmem");
try{
managed_shared_memory shmem(create_only, "my_shmem", 10000);
//Remove shared memory on construction and destruction
struct shm_destroy
{
shm_destroy() { shared_memory_object::remove("MySharedMemory"); }
~shm_destroy(){ shared_memory_object::remove("MySharedMemory"); }
} remover;
//In the first try, there will be no exceptions
//in the second try we will throw an exception
for(int i = 0; i < 2; ++i){
//Create an object in shared memory
my_class * my_object = shmem.construct<my_class>("my_object")();
my_class * my_object2 = shmem.construct<my_class>(anonymous_instance)();
shmem.destroy_ptr(my_object2);
//Since the next shared memory allocation can throw
//assign it to a scoped_ptr so that if an exception occurs
//we destroy the object automatically
my_deleter<my_class> d(shmem.get_segment_manager());
managed_shared_memory shmem(create_only, "MySharedMemory", 10000);
try{
scoped_ptr<my_class, my_deleter<my_class> > s_ptr(my_object, d);
//Let's emulate a exception capable operation
//In the second try, throw an exception
if(i == 1){
throw(my_exception());
}
//If we have passed the dangerous zone
//we can release the scoped pointer
//to avoid destruction
s_ptr.release();
//In the first try, there will be no exceptions
//in the second try we will throw an exception
for(int i = 0; i < 2; ++i){
//Create an object in shared memory
my_class * my_object = shmem.construct<my_class>("my_object")();
my_class * my_object2 = shmem.construct<my_class>(anonymous_instance)();
shmem.destroy_ptr(my_object2);
//Since the next shared memory allocation can throw
//assign it to a scoped_ptr so that if an exception occurs
//we destroy the object automatically
my_deleter<my_class> d(shmem.get_segment_manager());
try{
scoped_ptr<my_class, my_deleter<my_class> > s_ptr(my_object, d);
//Let's emulate a exception capable operation
//In the second try, throw an exception
if(i == 1){
throw(my_exception());
}
catch(const my_exception &){}
//Here, scoped_ptr is destroyed
//so it we haven't thrown an exception
//the object should be there, otherwise, destroyed
if(i == 0){
//Make sure the object is alive
if(!shmem.find<my_class>("my_object").first){
return 1;
}
//Now we can use it and delete it manually
shmem.destroy<my_class>("my_object");
//If we have passed the dangerous zone
//we can release the scoped pointer
//to avoid destruction
s_ptr.release();
}
catch(const my_exception &){}
//Here, scoped_ptr is destroyed
//so it we haven't thrown an exception
//the object should be there, otherwise, destroyed
if(i == 0){
//Make sure the object is alive
if(!shmem.find<my_class>("my_object").first){
return 1;
}
else{
//Make sure the object has been deleted
if(shmem.find<my_class>("my_object").first){
return 1;
}
//Now we can use it and delete it manually
shmem.destroy<my_class>("my_object");
}
else{
//Make sure the object has been deleted
if(shmem.find<my_class>("my_object").first){
return 1;
}
}
}
catch(...){
shared_memory_object::remove("my_shmem");
throw;
}
shared_memory_object::remove("my_shmem");
return 0;
}
//]

View File

@@ -11,18 +11,24 @@
//[doc_shared_memory
#include <boost/interprocess/shared_memory_object.hpp>
#include <boost/interprocess/mapped_region.hpp>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <string>
int main ()
int main(int argc, char *argv[])
{
using namespace boost::interprocess;
try{
//Erase previous shared memory
shared_memory_object::remove("shared_memory");
if(argc == 1){ //Parent process
//Remove shared memory on construction and destruction
struct shm_remove
{
shm_remove() { shared_memory_object::remove("MySharedMemory"); }
~shm_remove(){ shared_memory_object::remove("MySharedMemory"); }
} remover;
//Create a shared memory object.
shared_memory_object shm (create_only, "shared_memory", read_write);
shared_memory_object shm (create_only, "MySharedMemory", read_write);
//Set size
shm.truncate(1000);
@@ -32,11 +38,24 @@ int main ()
//Write all the memory to 1
std::memset(region.get_address(), 1, region.get_size());
//Launch child process
std::string s(argv[0]); s += " child";
if(0 != std::system(s.c_str()))
return 1;
}
catch(interprocess_exception &ex){
shared_memory_object::remove("shared_memory");
std::cout << ex.what() << std::endl;
return 1;
else{
//Open already created shared memory object.
shared_memory_object shm (open_only, "MySharedMemory", read_only);
//Map the whole shared memory in this process
mapped_region region(shm, read_only);
//Check that memory was initialized to 1
char *mem = static_cast<char*>(region.get_address());
for(std::size_t i = 0; i < region.get_size(); ++i)
if(*mem++ != 1)
return 1; //Error checking memory
}
return 0;
}

View File

@@ -1,48 +0,0 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2006-2007. 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/config_begin.hpp>
//[doc_shared_memory2
#include <boost/interprocess/shared_memory_object.hpp>
#include <boost/interprocess/mapped_region.hpp>
#include <iostream>
#include <cstring>
int main ()
{
using namespace boost::interprocess;
shared_memory_object::remove("shared_memory");
try{
//Open already created shared memory object.
shared_memory_object shm (open_only, "shared_memory", read_only);
//Map the whole shared memory in this process
mapped_region region(shm, read_only);
//Check that memory was initialized to 1
const char *mem = static_cast<char*>(region.get_address());
for(std::size_t i = 0; i < region.get_size(); ++i){
if(*mem++ != 1){
std::cout << "Error checking memory!" << std::endl;
return 1;
}
}
std::cout << "Test successful!" << std::endl;
}
catch(interprocess_exception &ex){
std::cout << "Unexpected exception: " << ex.what() << std::endl;
shared_memory_object::remove("shared_memory");
return 1;
}
shared_memory_object::remove("shared_memory");
return 0;
}
//]
#include <boost/interprocess/detail/config_end.hpp>

View File

@@ -16,7 +16,6 @@
#include <boost/interprocess/smart_ptr/shared_ptr.hpp>
#include <boost/interprocess/smart_ptr/weak_ptr.hpp>
#include <cassert>
#include <cstdio> //std::remove
using namespace boost::interprocess;
@@ -47,7 +46,7 @@ struct shared_ptr_owner
int main ()
{
//Destroy any previous file with the name to be used.
std::remove("MyMappedFile");
file_mapping::remove("MyMappedFile");
{
managed_mapped_file file(create_only, "MyMappedFile", 4096);
@@ -114,7 +113,7 @@ int main ()
//The reference count will be deallocated when all weak pointers
//disappear. After that, the file is unmapped.
}
std::remove("MyMappedFile");
file_mapping::remove("MyMappedFile");
return 0;
}
//]

View File

@@ -31,8 +31,13 @@ typedef shared_ptr<MyType, void_allocator_type, deleter_type> my_shared_ptr;
int main ()
{
//Destroy any previous segment with the name to be used.
shared_memory_object::remove("MySharedMemory");
//Remove shared memory on construction and destruction
struct shm_destroy
{
shm_destroy() { shared_memory_object::remove("MySharedMemory"); }
~shm_destroy(){ shared_memory_object::remove("MySharedMemory"); }
} remover;
managed_shared_memory segment(create_only, "MySharedMemory", 4096);
//Create a shared pointer in shared memory
@@ -49,7 +54,6 @@ int main ()
//Destroy "shared ptr". "object to share" will be automatically destroyed
segment.destroy_ptr(&shared_ptr_instance);
shared_memory_object::remove("MySharedMemory");
return 0;
}
//]

View File

@@ -0,0 +1,79 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2006-2009. 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/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
//[run_doc_spawn_vector
#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/containers/vector.hpp>
#include <boost/interprocess/allocators/allocator.hpp>
#include <string>
#include <cstdlib> //std::system
using namespace boost::interprocess;
//Define an STL compatible allocator of ints that allocates from the managed_shared_memory.
//This allocator will allow placing containers in the segment
typedef allocator<int, managed_shared_memory::segment_manager> ShmemAllocator;
//Alias a vector that uses the previous STL-like allocator so that allocates
//its values from the segment
typedef vector<int, ShmemAllocator> MyVector;
//Main function. For parent process argc == 1, for child process argc == 2
int main(int argc, char *argv[])
{
if(argc == 1){ //Parent process
//Remove shared memory on construction and destruction
struct shm_remove
{
shm_remove() { shared_memory_object::remove("MySharedMemory"); }
~shm_remove(){ shared_memory_object::remove("MySharedMemory"); }
} remover;
//Create a new segment with given name and size
managed_shared_memory segment(create_only ,"MySharedMemory", 65536);
//Initialize shared memory STL-compatible allocator
const ShmemAllocator alloc_inst (segment.get_segment_manager());
//Construct a vector named "MyVector" in shared memory with argument alloc_inst
MyVector *myvector = segment.construct<MyVector>("MyVector")(alloc_inst);
for(int i = 0; i < 100; ++i) //Insert data in the vector
myvector->push_back(i);
//Launch child process
std::string s(argv[0]); s += " child";
if(0 != std::system(s.c_str()))
return 1;
//Check child has destroyed the vector
if(segment.find<MyVector>("MyVector").first)
return 1;
}
else{ //Child process
//Open the managed segment
managed_shared_memory segment(open_only, "MySharedMemory");
//Find the vector using the c-string name
MyVector *myvector = segment.find<MyVector>("MyVector").first;
//Use vector in reverse order
std::sort(myvector->rbegin(), myvector->rend());
//When done, destroy the vector from the segment
segment.destroy<MyVector>("MyVector");
}
return 0;
};
//]
#include <boost/interprocess/detail/config_end.hpp>

View File

@@ -18,7 +18,6 @@
#include <boost/interprocess/containers/list.hpp>
#include <boost/interprocess/allocators/allocator.hpp>
#include <cassert>
#include <cstdio> //std::remove
using namespace boost::interprocess;
@@ -49,7 +48,7 @@ typedef list
int main ()
{
//Destroy any previous file with the name to be used.
std::remove("MyMappedFile");
file_mapping::remove("MyMappedFile");
{
managed_mapped_file file(create_only, "MyMappedFile", 65536);
@@ -72,9 +71,8 @@ int main ()
//Now insert all values
for(int i = 0; i < 100; ++i){
unique_vector->push_back(
make_managed_unique_ptr(file.construct<MyType>(anonymous_instance)(i), file)
);
unique_ptr_type p(make_managed_unique_ptr(file.construct<MyType>(anonymous_instance)(i), file));
unique_vector->push_back(boost::interprocess::move(p));
assert(unique_vector->back()->number_ == i);
}
@@ -84,7 +82,7 @@ int main ()
//Pass ownership of all values to the list
for(int i = 99; !unique_vector->empty(); --i){
unique_list->push_front(move(unique_vector->back()));
unique_list->push_front(boost::interprocess::move(unique_vector->back()));
//The unique ptr of the vector is now empty...
assert(unique_vector->back() == 0);
unique_vector->pop_back();
@@ -114,7 +112,7 @@ int main ()
//Now destroy the list. All elements will be automatically deallocated.
file.destroy_ptr(unique_list);
}
std::remove("MyMappedFile");
file_mapping::remove("MyMappedFile");
return 0;
}
//]

View File

@@ -20,46 +20,43 @@
int main ()
{
using namespace boost::interprocess;
//Erase previous shared memory with the name
shared_memory_object::remove("MySharedMemory");
//Remove shared memory on construction and destruction
struct shm_destroy
{
shm_destroy() { shared_memory_object::remove("MySharedMemory"); }
~shm_destroy(){ shared_memory_object::remove("MySharedMemory"); }
} remover;
try{
//Create shared memory
managed_shared_memory segment(create_only ,"MySharedMemory" ,65536);
//Create shared memory
managed_shared_memory segment(create_only ,"MySharedMemory" ,65536);
//Note that unordered_map<Key, MappedType>'s value_type is std::pair<const Key, MappedType>,
//so the allocator must allocate that pair.
typedef int KeyType;
typedef float MappedType;
typedef std::pair<const int, float> ValueType;
//Note that unordered_map<Key, MappedType>'s value_type is std::pair<const Key, MappedType>,
//so the allocator must allocate that pair.
typedef int KeyType;
typedef float MappedType;
typedef std::pair<const int, float> ValueType;
//Typedef the allocator
typedef allocator<ValueType, managed_shared_memory::segment_manager> ShmemAllocator;
//Typedef the allocator
typedef allocator<ValueType, managed_shared_memory::segment_manager> ShmemAllocator;
//Alias an unordered_map of ints that uses the previous STL-like allocator.
typedef boost::unordered_map
< KeyType , MappedType
, boost::hash<KeyType> ,std::equal_to<KeyType>
, ShmemAllocator>
MyHashMap;
//Alias an unordered_map of ints that uses the previous STL-like allocator.
typedef boost::unordered_map
< KeyType , MappedType
, boost::hash<KeyType> ,std::equal_to<KeyType>
, ShmemAllocator>
MyHashMap;
//Construct a shared memory hash map.
//Note that the first parameter is the initial bucket count and
//after that, the hash function, the equality function and the allocator
MyHashMap *myhashmap = segment.construct<MyHashMap>("MyHashMap") //object name
( 3, boost::hash<int>(), std::equal_to<int>() //
, segment.get_allocator<ValueType>()); //allocator instance
//Construct a shared memory hash map.
//Note that the first parameter is the initial bucket count and
//after that, the hash function, the equality function and the allocator
MyHashMap *myhashmap = segment.construct<MyHashMap>("MyHashMap") //object name
( 3, boost::hash<int>(), std::equal_to<int>() //
, segment.get_allocator<ValueType>()); //allocator instance
//Insert data in the hash map
for(int i = 0; i < 100; ++i){
myhashmap->insert(ValueType(i, (float)i));
}
//Insert data in the hash map
for(int i = 0; i < 100; ++i){
myhashmap->insert(ValueType(i, (float)i));
}
catch(...){
shared_memory_object::remove("MySharedMemory");
throw;
}
shared_memory_object::remove("MySharedMemory");
return 0;
}
//]

View File

@@ -30,83 +30,81 @@ typedef basic_vectorstream<MyString> MyVectorStream;
int main ()
{
//Create shared memory
shared_memory_object::remove("MySharedMemory");
try{
managed_shared_memory segment(
create_only,
"MySharedMemory", //segment name
65536); //segment size in bytes
//Remove shared memory on construction and destruction
struct shm_destroy
{
shm_destroy() { shared_memory_object::remove("MySharedMemory"); }
~shm_destroy(){ shared_memory_object::remove("MySharedMemory"); }
} remover;
//Construct shared memory vector
MyVector *myvector =
segment.construct<MyVector>("MyVector")
(IntAllocator(segment.get_segment_manager()));
managed_shared_memory segment(
create_only,
"MySharedMemory", //segment name
65536); //segment size in bytes
//Fill vector
myvector->reserve(100);
for(int i = 0; i < 100; ++i){
myvector->push_back(i);
}
//Construct shared memory vector
MyVector *myvector =
segment.construct<MyVector>("MyVector")
(IntAllocator(segment.get_segment_manager()));
//Create the vectorstream. To create the internal shared memory
//basic_string we need to pass the shared memory allocator as
//a constructor argument
MyVectorStream myvectorstream(CharAllocator(segment.get_segment_manager()));
//Reserve the internal string
myvectorstream.reserve(100*5);
//Write all vector elements as text in the internal string
//Data will be directly written in shared memory, because
//internal string's allocator is a shared memory allocator
for(std::size_t i = 0, max = myvector->size(); i < max; ++i){
myvectorstream << (*myvector)[i] << std::endl;
}
//Auxiliary vector to compare original data
MyVector *myvector2 =
segment.construct<MyVector>("MyVector2")
(IntAllocator(segment.get_segment_manager()));
//Avoid reallocations
myvector2->reserve(100);
//Extract all values from the internal
//string directly to a shared memory vector.
std::istream_iterator<int> it(myvectorstream), itend;
std::copy(it, itend, std::back_inserter(*myvector2));
//Compare vectors
assert(std::equal(myvector->begin(), myvector->end(), myvector2->begin()));
//Create a copy of the internal string
MyString stringcopy (myvectorstream.vector());
//Now we create a new empty shared memory string...
MyString *mystring =
segment.construct<MyString>("MyString")
(CharAllocator(segment.get_segment_manager()));
//...and we swap vectorstream's internal string
//with the new one: after this statement mystring
//will be the owner of the formatted data.
//No reallocations, no data copies
myvectorstream.swap_vector(*mystring);
//Let's compare both strings
assert(stringcopy == *mystring);
//Done, destroy and delete vectors and string from the segment
segment.destroy_ptr(myvector2);
segment.destroy_ptr(myvector);
segment.destroy_ptr(mystring);
//Fill vector
myvector->reserve(100);
for(int i = 0; i < 100; ++i){
myvector->push_back(i);
}
catch(...){
shared_memory_object::remove("MySharedMemory");
throw;
//Create the vectorstream. To create the internal shared memory
//basic_string we need to pass the shared memory allocator as
//a constructor argument
MyVectorStream myvectorstream(CharAllocator(segment.get_segment_manager()));
//Reserve the internal string
myvectorstream.reserve(100*5);
//Write all vector elements as text in the internal string
//Data will be directly written in shared memory, because
//internal string's allocator is a shared memory allocator
for(std::size_t i = 0, max = myvector->size(); i < max; ++i){
myvectorstream << (*myvector)[i] << std::endl;
}
shared_memory_object::remove("MySharedMemory");
//Auxiliary vector to compare original data
MyVector *myvector2 =
segment.construct<MyVector>("MyVector2")
(IntAllocator(segment.get_segment_manager()));
//Avoid reallocations
myvector2->reserve(100);
//Extract all values from the internal
//string directly to a shared memory vector.
std::istream_iterator<int> it(myvectorstream), itend;
std::copy(it, itend, std::back_inserter(*myvector2));
//Compare vectors
assert(std::equal(myvector->begin(), myvector->end(), myvector2->begin()));
//Create a copy of the internal string
MyString stringcopy (myvectorstream.vector());
//Now we create a new empty shared memory string...
MyString *mystring =
segment.construct<MyString>("MyString")
(CharAllocator(segment.get_segment_manager()));
//...and we swap vectorstream's internal string
//with the new one: after this statement mystring
//will be the owner of the formatted data.
//No reallocations, no data copies
myvectorstream.swap_vector(*mystring);
//Let's compare both strings
assert(stringcopy == *mystring);
//Done, destroy and delete vectors and string from the segment
segment.destroy_ptr(myvector2);
segment.destroy_ptr(myvector);
segment.destroy_ptr(mystring);
return 0;
}
//]

View File

@@ -29,45 +29,44 @@ int main ()
MyShmStringVector;
//Open shared memory
shared_memory_object::remove("myshm");
try{
managed_shared_memory shm(create_only, "myshm", 10000);
//Remove shared memory on construction and destruction
struct shm_destroy
{
shm_destroy() { shared_memory_object::remove("MySharedMemory"); }
~shm_destroy(){ shared_memory_object::remove("MySharedMemory"); }
} remover;
//Create allocators
CharAllocator charallocator (shm.get_segment_manager());
StringAllocator stringallocator(shm.get_segment_manager());
managed_shared_memory shm(create_only, "MySharedMemory", 10000);
//This string is in only in this process (the pointer pointing to the
//buffer that will hold the text is not in shared memory).
//But the buffer that will hold "this is my text" is allocated from
//shared memory
MyShmString mystring(charallocator);
mystring = "this is my text";
//Create allocators
CharAllocator charallocator (shm.get_segment_manager());
StringAllocator stringallocator(shm.get_segment_manager());
//This vector is only in this process (the pointer pointing to the
//buffer that will hold the MyShmString-s is not in shared memory).
//But the buffer that will hold 10 MyShmString-s is allocated from
//shared memory using StringAllocator. Since strings use a shared
//memory allocator (CharAllocator) the 10 buffers that hold
//"this is my text" text are also in shared memory.
MyShmStringVector myvector(stringallocator);
myvector.insert(myvector.begin(), 10, mystring);
//This string is in only in this process (the pointer pointing to the
//buffer that will hold the text is not in shared memory).
//But the buffer that will hold "this is my text" is allocated from
//shared memory
MyShmString mystring(charallocator);
mystring = "this is my text";
//This vector is fully constructed in shared memory. All pointers
//buffers are constructed in the same shared memory segment
//This vector can be safely accessed from other processes.
MyShmStringVector *myshmvector =
shm.construct<MyShmStringVector>("myshmvector")(stringallocator);
myshmvector->insert(myshmvector->begin(), 10, mystring);
//This vector is only in this process (the pointer pointing to the
//buffer that will hold the MyShmString-s is not in shared memory).
//But the buffer that will hold 10 MyShmString-s is allocated from
//shared memory using StringAllocator. Since strings use a shared
//memory allocator (CharAllocator) the 10 buffers that hold
//"this is my text" text are also in shared memory.
MyShmStringVector myvector(stringallocator);
myvector.insert(myvector.begin(), 10, mystring);
//Destroy vector. This will free all strings that the vector contains
shm.destroy_ptr(myshmvector);
}
catch(...){
shared_memory_object::remove("myshm");
throw;
}
shared_memory_object::remove("myshm");
//This vector is fully constructed in shared memory. All pointers
//buffers are constructed in the same shared memory segment
//This vector can be safely accessed from other processes.
MyShmStringVector *myshmvector =
shm.construct<MyShmStringVector>("myshmvector")(stringallocator);
myshmvector->insert(myshmvector->begin(), 10, mystring);
//Destroy vector. This will free all strings that the vector contains
shm.destroy_ptr(myshmvector);
return 0;
}
//]

View File

@@ -8,41 +8,61 @@
//
//////////////////////////////////////////////////////////////////////////////
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#ifdef BOOST_WINDOWS
#ifdef BOOST_INTERPROCESS_WINDOWS
//[doc_windows_shared_memory
#include <boost/interprocess/windows_shared_memory.hpp>
#include <boost/interprocess/mapped_region.hpp>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <string>
int main ()
int main(int argc, char *argv[])
{
using namespace boost::interprocess;
try{
if(argc == 1){ //Parent process
//Create a native windows shared memory object.
windows_shared_memory shm (create_only, "shared_memory", read_write, 1000);
windows_shared_memory shm (create_only, "MySharedMemory", read_write, 1000);
//Map the whole shared memory in this process
mapped_region region(shm, read_write);
//Write all the memory to 1
std::memset(region.get_address(), 1, 1000);
std::memset(region.get_address(), 1, region.get_size());
//Launch the client process and wait until finishes...
//...
//Launch child process
std::string s(argv[0]); s += " child";
if(0 != std::system(s.c_str()))
return 1;
//windows_shared_memory is destroyed when the last attached process dies...
}
catch(interprocess_exception &ex){
std::cout << ex.what() << std::endl;
return 1;
else{
//Open already created shared memory object.
windows_shared_memory shm (open_only, "MySharedMemory", read_only);
//Map the whole shared memory in this process
mapped_region region(shm, read_only);
//Check that memory was initialized to 1
char *mem = static_cast<char*>(region.get_address());
for(std::size_t i = 0; i < region.get_size(); ++i)
if(*mem++ != 1)
return 1; //Error checking memory
return 0;
}
return 0;
}
//]
#else //#ifdef BOOST_WINDOWS
#else //BOOST_INTERPROCESS_WINDOWS
int main()
{ return 0; }
#endif//#ifdef BOOST_WINDOWS
{
return 0;
}
#endif //BOOST_INTERPROCESS_WINDOWS
#include <boost/interprocess/detail/config_end.hpp>

View File

@@ -1,55 +0,0 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2006-2007. 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/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#ifdef BOOST_WINDOWS
//[doc_windows_shared_memory2
#include <boost/interprocess/windows_shared_memory.hpp>
#include <boost/interprocess/mapped_region.hpp>
#include <iostream>
#include <cstring>
int main ()
{
using namespace boost::interprocess;
try{
//Open already created shared memory object.
windows_shared_memory shm(open_only, "shared_memory", read_only);
//Map the whole shared memory in this process
mapped_region region (shm, read_only);
//Check that memory was initialized to 1
const char *mem = static_cast<char*>(region.get_address());
for(std::size_t i = 0; i < 1000; ++i){
if(*mem++ != 1){
std::cout << "Error checking memory!" << std::endl;
return 1;
}
}
std::cout << "Test successful!" << std::endl;
}
catch(interprocess_exception &ex){
std::cout << "Unexpected exception: " << ex.what() << std::endl;
return 1;
}
return 0;
}
//]
#else //#ifdef BOOST_WINDOWS
int main()
{ return 0; }
#endif//#ifdef BOOST_WINDOWS
#include <boost/interprocess/detail/config_end.hpp>

View File

@@ -18,6 +18,8 @@
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/pointer_to_other.hpp>
#include <boost/interprocess/interprocess_fwd.hpp>
#include <boost/assert.hpp>
#include <boost/utility/addressof.hpp>
@@ -80,9 +82,9 @@ class adaptive_pool_base
public:
//-------
typedef typename detail::
typedef typename boost::
pointer_to_other<void_pointer, T>::type pointer;
typedef typename detail::
typedef typename boost::
pointer_to_other<void_pointer, const T>::type const_pointer;
typedef T value_type;
typedef typename detail::add_reference
@@ -92,13 +94,9 @@ class adaptive_pool_base
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
typedef detail::version_type<adaptive_pool_base, Version> version;
typedef transform_iterator
< typename SegmentManager::
multiallocation_iterator
, detail::cast_functor <T> > multiallocation_iterator;
typedef typename SegmentManager::
multiallocation_chain multiallocation_chain;
typedef boost::interprocess::version_type<adaptive_pool_base, Version> version;
typedef detail::transform_multiallocation_chain
<typename SegmentManager::multiallocation_chain, T>multiallocation_chain;
//!Obtains adaptive_pool_base from
//!adaptive_pool_base
@@ -266,7 +264,7 @@ class adaptive_pool
typedef detail::adaptive_pool_base
< 2, T, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> base_t;
public:
typedef detail::version_type<adaptive_pool, 2> version;
typedef boost::interprocess::version_type<adaptive_pool, 2> version;
template<class T2>
struct rebind
@@ -388,7 +386,7 @@ class adaptive_pool
size_type size(const pointer &p) const;
std::pair<pointer, bool>
allocation_command(allocation_type command,
allocation_command(boost::interprocess::allocation_type command,
size_type limit_size,
size_type preferred_size,
size_type &received_size, const pointer &reuse = 0);
@@ -399,12 +397,12 @@ class adaptive_pool
//!preferred_elements. The number of actually allocated elements is
//!will be assigned to received_size. The elements must be deallocated
//!with deallocate(...)
multiallocation_iterator allocate_many(size_type elem_size, std::size_t num_elements);
multiallocation_chain allocate_many(size_type elem_size, std::size_t num_elements);
//!Allocates n_elements elements, each one of size elem_sizes[i]in a
//!contiguous block
//!of memory. The elements must be deallocated
multiallocation_iterator allocate_many(const size_type *elem_sizes, size_type n_elements);
multiallocation_chain allocate_many(const size_type *elem_sizes, size_type n_elements);
//!Allocates many elements of size elem_size in a contiguous block
//!of memory. The minimum number to be allocated is min_elements,
@@ -412,7 +410,7 @@ class adaptive_pool
//!preferred_elements. The number of actually allocated elements is
//!will be assigned to received_size. The elements must be deallocated
//!with deallocate(...)
void deallocate_many(multiallocation_iterator it);
void deallocate_many(multiallocation_chain chain);
//!Allocates just one object. Memory allocated with this function
//!must be deallocated only with deallocate_one().
@@ -425,7 +423,7 @@ class adaptive_pool
//!preferred_elements. The number of actually allocated elements is
//!will be assigned to received_size. Memory allocated with this function
//!must be deallocated only with deallocate_one().
multiallocation_iterator allocate_individual(std::size_t num_elements);
multiallocation_chain allocate_individual(std::size_t num_elements);
//!Deallocates memory previously allocated with allocate_one().
//!You should never use deallocate_one to deallocate memory allocated
@@ -438,7 +436,7 @@ class adaptive_pool
//!preferred_elements. The number of actually allocated elements is
//!will be assigned to received_size. Memory allocated with this function
//!must be deallocated only with deallocate_one().
void deallocate_individual(multiallocation_iterator it);
void deallocate_individual(multiallocation_chain it);
#endif
};

View File

@@ -18,15 +18,17 @@
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/pointer_to_other.hpp>
#include <boost/interprocess/interprocess_fwd.hpp>
#include <boost/interprocess/allocators/allocation_type.hpp>
#include <boost/interprocess/containers/allocation_type.hpp>
#include <boost/interprocess/allocators/detail/allocator_common.hpp>
#include <boost/interprocess/detail/utilities.hpp>
#include <boost/interprocess/detail/version_type.hpp>
#include <boost/interprocess/containers/version_type.hpp>
#include <boost/interprocess/exceptions.hpp>
#include <boost/assert.hpp>
#include <boost/utility/addressof.hpp>
#include <boost/interprocess/detail/type_traits.hpp>
#include <boost/interprocess/detail/iterators.hpp>
#include <memory>
#include <algorithm>
@@ -64,11 +66,11 @@ class allocator
//Typedef to const void pointer
typedef typename
detail::pointer_to_other
boost::pointer_to_other
<aux_pointer_t, const void>::type cvoid_ptr;
//Pointer to the allocator
typedef typename detail::pointer_to_other
typedef typename boost::pointer_to_other
<cvoid_ptr, segment_manager>::type alloc_ptr_t;
//Not assignable from related allocator
@@ -84,9 +86,9 @@ class allocator
public:
typedef T value_type;
typedef typename detail::pointer_to_other
typedef typename boost::pointer_to_other
<cvoid_ptr, T>::type pointer;
typedef typename detail::
typedef typename boost::
pointer_to_other<pointer, const T>::type const_pointer;
typedef typename detail::add_reference
<value_type>::type reference;
@@ -95,20 +97,13 @@ class allocator
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
typedef detail::version_type<allocator, 2> version;
typedef boost::interprocess::version_type<allocator, 2> version;
/// @cond
//Experimental. Don't use.
typedef transform_iterator
< typename SegmentManager::
multiallocation_iterator
, detail::cast_functor <T> > multiallocation_iterator;
typedef detail::multiallocation_chain_adaptor
<typename SegmentManager::
multiallocation_chain
, T> multiallocation_chain;
typedef boost::interprocess::detail::transform_multiallocation_chain
<typename SegmentManager::multiallocation_chain, T>multiallocation_chain;
/// @endcond
//!Obtains an allocator that allocates
@@ -174,7 +169,7 @@ class allocator
}
std::pair<pointer, bool>
allocation_command(allocation_type command,
allocation_command(boost::interprocess::allocation_type command,
size_type limit_size,
size_type preferred_size,
size_type &received_size, const pointer &reuse = 0)
@@ -189,19 +184,19 @@ class allocator
//!preferred_elements. The number of actually allocated elements is
//!will be assigned to received_size. The elements must be deallocated
//!with deallocate(...)
multiallocation_iterator allocate_many(size_type elem_size, std::size_t num_elements)
multiallocation_chain allocate_many
(size_type elem_size, std::size_t num_elements)
{
return multiallocation_iterator
(mp_mngr->allocate_many(sizeof(T)*elem_size, num_elements));
return multiallocation_chain(mp_mngr->allocate_many(sizeof(T)*elem_size, num_elements));
}
//!Allocates n_elements elements, each one of size elem_sizes[i]in a
//!contiguous block
//!of memory. The elements must be deallocated
multiallocation_iterator allocate_many(const size_type *elem_sizes, size_type n_elements)
multiallocation_chain allocate_many
(const size_type *elem_sizes, size_type n_elements)
{
return multiallocation_iterator
(mp_mngr->allocate_many(elem_sizes, n_elements, sizeof(T)));
multiallocation_chain(mp_mngr->allocate_many(elem_sizes, n_elements, sizeof(T)));
}
//!Allocates many elements of size elem_size in a contiguous block
@@ -210,8 +205,10 @@ class allocator
//!preferred_elements. The number of actually allocated elements is
//!will be assigned to received_size. The elements must be deallocated
//!with deallocate(...)
void deallocate_many(multiallocation_iterator it)
{ return mp_mngr->deallocate_many(it.base()); }
void deallocate_many(multiallocation_chain chain)
{
return mp_mngr->deallocate_many(chain.extract_multiallocation_chain());
}
//!Allocates just one object. Memory allocated with this function
//!must be deallocated only with deallocate_one().
@@ -225,7 +222,8 @@ class allocator
//!preferred_elements. The number of actually allocated elements is
//!will be assigned to received_size. Memory allocated with this function
//!must be deallocated only with deallocate_one().
multiallocation_iterator allocate_individual(std::size_t num_elements)
multiallocation_chain allocate_individual
(std::size_t num_elements)
{ return this->allocate_many(1, num_elements); }
//!Deallocates memory previously allocated with allocate_one().
@@ -240,8 +238,8 @@ class allocator
//!preferred_elements. The number of actually allocated elements is
//!will be assigned to received_size. Memory allocated with this function
//!must be deallocated only with deallocate_one().
void deallocate_individual(multiallocation_iterator it)
{ return this->deallocate_many(it); }
void deallocate_individual(multiallocation_chain chain)
{ return this->deallocate_many(boost::interprocess::move(chain)); }
//!Returns address of mutable object.
//!Never throws

View File

@@ -23,7 +23,7 @@
#include <boost/interprocess/allocators/detail/allocator_common.hpp>
#include <boost/interprocess/detail/utilities.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/interprocess/detail/version_type.hpp>
#include <boost/interprocess/containers/version_type.hpp>
#include <boost/interprocess/allocators/detail/node_tools.hpp>
#include <cstddef>
@@ -143,7 +143,7 @@ class cached_adaptive_pool
, 2> base_t;
public:
typedef detail::version_type<cached_adaptive_pool, 2> version;
typedef boost::interprocess::version_type<cached_adaptive_pool, 2> version;
template<class T2>
struct rebind
@@ -267,7 +267,7 @@ class cached_adaptive_pool
size_type size(const pointer &p) const;
std::pair<pointer, bool>
allocation_command(allocation_type command,
allocation_command(boost::interprocess::allocation_type command,
size_type limit_size,
size_type preferred_size,
size_type &received_size, const pointer &reuse = 0);
@@ -278,12 +278,12 @@ class cached_adaptive_pool
//!preferred_elements. The number of actually allocated elements is
//!will be assigned to received_size. The elements must be deallocated
//!with deallocate(...)
multiallocation_iterator allocate_many(size_type elem_size, std::size_t num_elements);
multiallocation_chain allocate_many(size_type elem_size, std::size_t num_elements);
//!Allocates n_elements elements, each one of size elem_sizes[i]in a
//!contiguous block
//!of memory. The elements must be deallocated
multiallocation_iterator allocate_many(const size_type *elem_sizes, size_type n_elements);
multiallocation_chain allocate_many(const size_type *elem_sizes, size_type n_elements);
//!Allocates many elements of size elem_size in a contiguous block
//!of memory. The minimum number to be allocated is min_elements,
@@ -291,7 +291,7 @@ class cached_adaptive_pool
//!preferred_elements. The number of actually allocated elements is
//!will be assigned to received_size. The elements must be deallocated
//!with deallocate(...)
void deallocate_many(multiallocation_iterator it);
void deallocate_many(multiallocation_chain chain);
//!Allocates just one object. Memory allocated with this function
//!must be deallocated only with deallocate_one().
@@ -304,7 +304,7 @@ class cached_adaptive_pool
//!preferred_elements. The number of actually allocated elements is
//!will be assigned to received_size. Memory allocated with this function
//!must be deallocated only with deallocate_one().
multiallocation_iterator allocate_individual(std::size_t num_elements);
multiallocation_chain allocate_individual(std::size_t num_elements);
//!Deallocates memory previously allocated with allocate_one().
//!You should never use deallocate_one to deallocate memory allocated
@@ -317,7 +317,7 @@ class cached_adaptive_pool
//!preferred_elements. The number of actually allocated elements is
//!will be assigned to received_size. Memory allocated with this function
//!must be deallocated only with deallocate_one().
void deallocate_individual(multiallocation_iterator it);
void deallocate_individual(multiallocation_chain chain);
//!Sets the new max cached nodes value. This can provoke deallocations
//!if "newmax" is less than current cached nodes. Never throws
void set_max_cached_nodes(std::size_t newmax);

View File

@@ -23,7 +23,7 @@
#include <boost/interprocess/allocators/detail/allocator_common.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/interprocess/detail/utilities.hpp>
#include <boost/interprocess/detail/version_type.hpp>
#include <boost/interprocess/containers/version_type.hpp>
#include <boost/interprocess/allocators/detail/node_tools.hpp>
#include <cstddef>
@@ -115,7 +115,7 @@ class cached_node_allocator
, 2> base_t;
public:
typedef detail::version_type<cached_node_allocator, 2> version;
typedef boost::interprocess::version_type<cached_node_allocator, 2> version;
template<class T2>
struct rebind
@@ -238,7 +238,7 @@ class cached_node_allocator
size_type size(const pointer &p) const;
std::pair<pointer, bool>
allocation_command(allocation_type command,
allocation_command(boost::interprocess::allocation_type command,
size_type limit_size,
size_type preferred_size,
size_type &received_size, const pointer &reuse = 0);
@@ -249,12 +249,12 @@ class cached_node_allocator
//!preferred_elements. The number of actually allocated elements is
//!will be assigned to received_size. The elements must be deallocated
//!with deallocate(...)
multiallocation_iterator allocate_many(size_type elem_size, std::size_t num_elements);
multiallocation_chain allocate_many(size_type elem_size, std::size_t num_elements);
//!Allocates n_elements elements, each one of size elem_sizes[i]in a
//!contiguous block
//!of memory. The elements must be deallocated
multiallocation_iterator allocate_many(const size_type *elem_sizes, size_type n_elements);
multiallocation_chain allocate_many(const size_type *elem_sizes, size_type n_elements);
//!Allocates many elements of size elem_size in a contiguous block
//!of memory. The minimum number to be allocated is min_elements,
@@ -262,7 +262,7 @@ class cached_node_allocator
//!preferred_elements. The number of actually allocated elements is
//!will be assigned to received_size. The elements must be deallocated
//!with deallocate(...)
void deallocate_many(multiallocation_iterator it);
void deallocate_many(multiallocation_chain chain);
//!Allocates just one object. Memory allocated with this function
//!must be deallocated only with deallocate_one().
@@ -275,7 +275,7 @@ class cached_node_allocator
//!preferred_elements. The number of actually allocated elements is
//!will be assigned to received_size. Memory allocated with this function
//!must be deallocated only with deallocate_one().
multiallocation_iterator allocate_individual(std::size_t num_elements);
multiallocation_chain allocate_individual(std::size_t num_elements);
//!Deallocates memory previously allocated with allocate_one().
//!You should never use deallocate_one to deallocate memory allocated
@@ -288,7 +288,7 @@ class cached_node_allocator
//!preferred_elements. The number of actually allocated elements is
//!will be assigned to received_size. Memory allocated with this function
//!must be deallocated only with deallocate_one().
void deallocate_individual(multiallocation_iterator it);
void deallocate_individual(multiallocation_chain it);
//!Sets the new max cached nodes value. This can provoke deallocations
//!if "newmax" is less than current cached nodes. Never throws
void set_max_cached_nodes(std::size_t newmax);

View File

@@ -17,6 +17,7 @@
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/pointer_to_other.hpp>
#include <boost/interprocess/interprocess_fwd.hpp>
#include <boost/interprocess/sync/interprocess_mutex.hpp>
#include <boost/interprocess/detail/utilities.hpp>
@@ -27,6 +28,7 @@
#include <boost/intrusive/slist.hpp>
#include <boost/math/common_factor_ct.hpp>
#include <boost/interprocess/detail/type_traits.hpp>
#include <boost/interprocess/mem_algo/detail/mem_algo_common.hpp>
#include <boost/interprocess/allocators/detail/node_tools.hpp>
#include <boost/interprocess/allocators/detail/allocator_common.hpp>
#include <cstddef>
@@ -53,7 +55,6 @@ class private_adaptive_node_pool_impl
public:
typedef typename node_slist<void_pointer>::node_t node_t;
typedef typename node_slist<void_pointer>::node_slist_t free_nodes_t;
typedef typename SegmentManagerBase::multiallocation_iterator multiallocation_iterator;
typedef typename SegmentManagerBase::multiallocation_chain multiallocation_chain;
private:
@@ -200,8 +201,9 @@ class private_adaptive_node_pool_impl
//!Deallocates an array pointed by ptr. Never throws
void deallocate_node(void *pElem)
{
this->priv_reinsert_nodes_in_block
(multiallocation_iterator::create_simple_range(pElem));
multiallocation_chain chain;
chain.push_front(void_pointer(pElem));
this->priv_reinsert_nodes_in_block(chain, 1);
//Update free block count
if(m_totally_free_blocks > m_max_free_blocks){
this->priv_deallocate_free_blocks(m_max_free_blocks);
@@ -209,13 +211,14 @@ class private_adaptive_node_pool_impl
priv_invariants();
}
//!Allocates a singly linked list of n nodes ending in null pointer.
//!can throw boost::interprocess::bad_alloc
void allocate_nodes(multiallocation_chain &nodes, const std::size_t n)
//!Allocates n nodes.
//!Can throw boost::interprocess::bad_alloc
multiallocation_chain allocate_nodes(const std::size_t n)
{
multiallocation_chain chain;
std::size_t i = 0;
try{
priv_invariants();
std::size_t i = 0;
while(i != n){
//If there are no free nodes we allocate all needed blocks
if (m_block_multiset.empty()){
@@ -230,9 +233,9 @@ class private_adaptive_node_pool_impl
for(std::size_t j = 0; j != num_elems; ++j){
void *new_node = &free_nodes.front();
free_nodes.pop_front();
nodes.push_back(new_node);
chain.push_back(new_node);
}
if(free_nodes.empty()){
m_block_multiset.erase(m_block_multiset.begin());
}
@@ -240,41 +243,23 @@ class private_adaptive_node_pool_impl
}
}
catch(...){
this->deallocate_nodes(nodes, nodes.size());
this->deallocate_nodes(chain, i);
throw;
}
priv_invariants();
}
//!Allocates n nodes, pointed by the multiallocation_iterator.
//!Can throw boost::interprocess::bad_alloc
multiallocation_iterator allocate_nodes(const std::size_t n)
{
multiallocation_chain chain;
this->allocate_nodes(chain, n);
return chain.get_it();
return boost::interprocess::move(chain);
}
//!Deallocates a linked list of nodes. Never throws
void deallocate_nodes(multiallocation_chain &nodes)
void deallocate_nodes(multiallocation_chain nodes)
{
this->deallocate_nodes(nodes.get_it());
nodes.reset();
return deallocate_nodes(nodes, nodes.size());
}
//!Deallocates the first n nodes of a linked list of nodes. Never throws
void deallocate_nodes(multiallocation_chain &nodes, std::size_t n)
{
assert(nodes.size() >= n);
for(std::size_t i = 0; i < n; ++i){
this->deallocate_node(nodes.pop_front());
}
}
//!Deallocates the nodes pointed by the multiallocation iterator. Never throws
void deallocate_nodes(multiallocation_iterator it)
{
this->priv_reinsert_nodes_in_block(it);
this->priv_reinsert_nodes_in_block(nodes, n);
if(m_totally_free_blocks > m_max_free_blocks){
this->priv_deallocate_free_blocks(m_max_free_blocks);
}
@@ -331,13 +316,12 @@ class private_adaptive_node_pool_impl
}
}
void priv_reinsert_nodes_in_block(multiallocation_iterator it)
void priv_reinsert_nodes_in_block(multiallocation_chain &chain, std::size_t n)
{
multiallocation_iterator itend;
block_iterator block_it(m_block_multiset.end());
while(it != itend){
void *pElem = &*it;
++it;
while(n--){
void *pElem = detail::get_pointer(chain.front());
chain.pop_front();
priv_invariants();
block_info_t *block_info = this->priv_block_from_node(pElem);
assert(block_info->free_nodes.size() < m_real_num_node);
@@ -484,6 +468,7 @@ class private_adaptive_node_pool_impl
std::size_t num_free_nodes = 0;
for(; it != itend; ++it){
//Check for memory leak
std::size_t n = (std::size_t)it->free_nodes.size(); (void)n;
assert(it->free_nodes.size() == m_real_num_node);
++num_free_nodes;
}
@@ -565,7 +550,7 @@ class private_adaptive_node_pool_impl
}
private:
typedef typename pointer_to_other
typedef typename boost::pointer_to_other
<void_pointer, segment_manager_base_type>::type segment_mngr_base_ptr_t;
const std::size_t m_max_free_blocks;

View File

@@ -8,25 +8,63 @@
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTERPROCESS_DETAIL_NODE_ALLOCATOR_COMMON_HPP
#define BOOST_INTERPROCESS_DETAIL_NODE_ALLOCATOR_COMMON_HPP
#ifndef BOOST_INTERPROCESS_ALLOCATOR_DETAIL_ALLOCATOR_COMMON_HPP
#define BOOST_INTERPROCESS_ALLOCATOR_DETAIL_ALLOCATOR_COMMON_HPP
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/interprocess/segment_manager.hpp>
#include <boost/pointer_to_other.hpp>
#include <boost/interprocess/interprocess_fwd.hpp>
#include <boost/interprocess/detail/utilities.hpp> //pointer_to_other, get_pointer
#include <boost/interprocess/detail/utilities.hpp> //get_pointer
#include <utility> //std::pair
#include <boost/utility/addressof.hpp> //boost::addressof
#include <boost/assert.hpp> //BOOST_ASSERT
#include <boost/interprocess/exceptions.hpp> //bad_alloc
#include <boost/interprocess/sync/scoped_lock.hpp> //scoped_lock
#include <boost/interprocess/allocators/allocation_type.hpp> //allocation_type
#include <boost/interprocess/containers/allocation_type.hpp> //boost::interprocess::allocation_type
#include <boost/interprocess/mem_algo/detail/mem_algo_common.hpp>
#include <boost/interprocess/detail/segment_manager_helper.hpp>
#include <algorithm> //std::swap
#include <boost/interprocess/detail/move.hpp>
#include <boost/interprocess/detail/type_traits.hpp>
#include <boost/interprocess/detail/utilities.hpp>
namespace boost {
namespace interprocess {
template <class T>
struct sizeof_value
{
static const std::size_t value = sizeof(T);
};
template <>
struct sizeof_value<void>
{
static const std::size_t value = sizeof(void*);
};
template <>
struct sizeof_value<const void>
{
static const std::size_t value = sizeof(void*);
};
template <>
struct sizeof_value<volatile void>
{
static const std::size_t value = sizeof(void*);
};
template <>
struct sizeof_value<const volatile void>
{
static const std::size_t value = sizeof(void*);
};
namespace detail {
//!Object function that creates the node allocator if it is not created and
@@ -41,7 +79,7 @@ struct get_or_create_node_pool_func
{
//Find or create the node_pool_t
mp_node_pool = mp_segment_manager->template find_or_construct
<NodePool>(unique_instance)(mp_segment_manager);
<NodePool>(boost::interprocess::unique_instance)(mp_segment_manager);
//If valid, increment link count
if(mp_node_pool != 0)
mp_node_pool->inc_ref_count();
@@ -78,7 +116,7 @@ struct destroy_if_last_link_func
if(mp_node_pool->dec_ref_count() != 0) return;
//Last link, let's destroy the segment_manager
mp_node_pool->get_segment_manager()->template destroy<NodePool>(unique_instance);
mp_node_pool->get_segment_manager()->template destroy<NodePool>(boost::interprocess::unique_instance);
}
//!Constructor. Initializes function
@@ -106,16 +144,15 @@ template<class NodePool>
class cache_impl
{
typedef typename NodePool::segment_manager::
void_pointer void_pointer;
void_pointer void_pointer;
typedef typename pointer_to_other
<void_pointer, NodePool>::type node_pool_ptr;
typedef typename NodePool::multiallocation_chain multiallocation_chain;
node_pool_ptr mp_node_pool;
multiallocation_chain m_cached_nodes;
std::size_t m_max_cached_nodes;
<void_pointer, NodePool>::type node_pool_ptr;
typedef typename NodePool::multiallocation_chain multiallocation_chain;
node_pool_ptr mp_node_pool;
multiallocation_chain m_cached_nodes;
std::size_t m_max_cached_nodes;
public:
typedef typename NodePool::multiallocation_iterator multiallocation_iterator;
typedef typename NodePool::segment_manager segment_manager;
cache_impl(segment_manager *segment_mngr, std::size_t max_cached_nodes)
@@ -149,31 +186,34 @@ class cache_impl
{
//If don't have any cached node, we have to get a new list of free nodes from the pool
if(m_cached_nodes.empty()){
mp_node_pool->allocate_nodes(m_cached_nodes, m_max_cached_nodes/2);
m_cached_nodes = mp_node_pool->allocate_nodes(m_max_cached_nodes/2);
}
return m_cached_nodes.pop_front();
void *ret = detail::get_pointer(m_cached_nodes.front());
m_cached_nodes.pop_front();
return ret;
}
multiallocation_iterator cached_allocation(std::size_t n)
multiallocation_chain cached_allocation(std::size_t n)
{
multiallocation_chain chain;
std::size_t count = n;
std::size_t count = n, allocated(0);
BOOST_TRY{
//If don't have any cached node, we have to get a new list of free nodes from the pool
while(!m_cached_nodes.empty() && count--){
void *ret = m_cached_nodes.pop_front();
void *ret = detail::get_pointer(m_cached_nodes.front());
m_cached_nodes.pop_front();
chain.push_back(ret);
++allocated;
}
if(chain.size() != n){
mp_node_pool->allocate_nodes(chain, n - chain.size());
if(allocated != n){
multiallocation_chain chain2(mp_node_pool->allocate_nodes(n - allocated));
chain.splice_after(chain.last(), chain2, chain2.before_begin(), chain2.last(), n - allocated);
}
assert(chain.size() == n);
chain.splice_back(m_cached_nodes);
return multiallocation_iterator(chain.get_it());
return boost::interprocess::move(chain);
}
BOOST_CATCH(...){
this->cached_deallocation(multiallocation_iterator(chain.get_it()));
this->cached_deallocation(boost::interprocess::move(chain));
BOOST_RETHROW
}
BOOST_CATCH_END
@@ -192,15 +232,9 @@ class cache_impl
m_cached_nodes.push_front(ptr);
}
void cached_deallocation(multiallocation_iterator it)
void cached_deallocation(multiallocation_chain chain)
{
multiallocation_iterator itend;
while(it != itend){
void *addr = &*it;
++it;
m_cached_nodes.push_front(addr);
}
m_cached_nodes.splice_after(m_cached_nodes.before_begin(), chain);
//Check if cache is full
if(m_cached_nodes.size() >= m_max_cached_nodes){
@@ -225,7 +259,7 @@ class cache_impl
void deallocate_all_cached_nodes()
{
if(m_cached_nodes.empty()) return;
mp_node_pool->deallocate_nodes(m_cached_nodes);
mp_node_pool->deallocate_nodes(boost::interprocess::move(m_cached_nodes));
}
private:
@@ -257,9 +291,9 @@ class array_allocation_impl
typedef typename SegmentManager::void_pointer void_pointer;
public:
typedef typename detail::
typedef typename boost::
pointer_to_other<void_pointer, T>::type pointer;
typedef typename detail::
typedef typename boost::
pointer_to_other<void_pointer, const T>::type const_pointer;
typedef T value_type;
typedef typename detail::add_reference
@@ -268,12 +302,9 @@ class array_allocation_impl
<const value_type>::type const_reference;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
typedef transform_iterator
< typename SegmentManager::
multiallocation_iterator
, detail::cast_functor <T> > multiallocation_iterator;
typedef typename SegmentManager::
multiallocation_chain multiallocation_chain;
typedef detail::transform_multiallocation_chain
<typename SegmentManager::multiallocation_chain, T>multiallocation_chain;
public:
//!Returns maximum the number of objects the previously allocated memory
@@ -285,7 +316,7 @@ class array_allocation_impl
}
std::pair<pointer, bool>
allocation_command(allocation_type command,
allocation_command(boost::interprocess::allocation_type command,
size_type limit_size,
size_type preferred_size,
size_type &received_size, const pointer &reuse = 0)
@@ -300,19 +331,17 @@ class array_allocation_impl
//!preferred_elements. The number of actually allocated elements is
//!will be assigned to received_size. The elements must be deallocated
//!with deallocate(...)
multiallocation_iterator allocate_many(size_type elem_size, std::size_t num_elements)
multiallocation_chain allocate_many(size_type elem_size, std::size_t num_elements)
{
return multiallocation_iterator
(this->derived()->get_segment_manager()->allocate_many(sizeof(T)*elem_size, num_elements));
return this->derived()->get_segment_manager()->allocate_many(sizeof(T)*elem_size, num_elements);
}
//!Allocates n_elements elements, each one of size elem_sizes[i]in a
//!contiguous block
//!of memory. The elements must be deallocated
multiallocation_iterator allocate_many(const size_type *elem_sizes, size_type n_elements)
multiallocation_chain allocate_many(const size_type *elem_sizes, size_type n_elements)
{
return multiallocation_iterator
(this->derived()->get_segment_manager()->allocate_many(elem_sizes, n_elements, sizeof(T)));
return this->derived()->get_segment_manager()->allocate_many(elem_sizes, n_elements, sizeof(T));
}
//!Allocates many elements of size elem_size in a contiguous block
@@ -321,8 +350,8 @@ class array_allocation_impl
//!preferred_elements. The number of actually allocated elements is
//!will be assigned to received_size. The elements must be deallocated
//!with deallocate(...)
void deallocate_many(multiallocation_iterator it)
{ return this->derived()->get_segment_manager()->deallocate_many(it.base()); }
void deallocate_many(multiallocation_chain chain)
{ return this->derived()->get_segment_manager()->deallocate_many(boost::interprocess::move(chain)); }
//!Returns the number of elements that could be
//!allocated. Never throws
@@ -369,13 +398,13 @@ class node_pool_allocation_impl
{ return static_cast<Derived*>(this); }
typedef typename SegmentManager::void_pointer void_pointer;
typedef typename detail::
typedef typename boost::
pointer_to_other<void_pointer, const void>::type cvoid_pointer;
public:
typedef typename detail::
typedef typename boost::
pointer_to_other<void_pointer, T>::type pointer;
typedef typename detail::
typedef typename boost::
pointer_to_other<void_pointer, const T>::type const_pointer;
typedef T value_type;
typedef typename detail::add_reference
@@ -384,12 +413,9 @@ class node_pool_allocation_impl
<const value_type>::type const_reference;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
typedef transform_iterator
< typename SegmentManager::
multiallocation_iterator
, detail::cast_functor <T> > multiallocation_iterator;
typedef typename SegmentManager::
multiallocation_chain multiallocation_chain;
typedef detail::transform_multiallocation_chain
<typename SegmentManager::multiallocation_chain, T>multiallocation_chain;
template <int Dummy>
struct node_pool
@@ -445,11 +471,11 @@ class node_pool_allocation_impl
//!preferred_elements. The number of actually allocated elements is
//!will be assigned to received_size. Memory allocated with this function
//!must be deallocated only with deallocate_one().
multiallocation_iterator allocate_individual(std::size_t num_elements)
multiallocation_chain allocate_individual(std::size_t num_elements)
{
typedef typename node_pool<0>::type node_pool_t;
node_pool_t *pool = node_pool<0>::get(this->derived()->get_node_pool());
return multiallocation_iterator(pool->allocate_nodes(num_elements));
return multiallocation_chain(pool->allocate_nodes(num_elements));
}
//!Deallocates memory previously allocated with allocate_one().
@@ -468,8 +494,11 @@ class node_pool_allocation_impl
//!preferred_elements. The number of actually allocated elements is
//!will be assigned to received_size. Memory allocated with this function
//!must be deallocated only with deallocate_one().
void deallocate_individual(multiallocation_iterator it)
{ node_pool<0>::get(this->derived()->get_node_pool())->deallocate_nodes(it.base()); }
void deallocate_individual(multiallocation_chain chain)
{
node_pool<0>::get(this->derived()->get_node_pool())->deallocate_nodes
(chain.extract_multiallocation_chain());
}
//!Deallocates all free blocks of the pool
void deallocate_free_blocks()
@@ -497,11 +526,10 @@ class cached_allocator_impl
typedef NodePool node_pool_t;
typedef typename NodePool::segment_manager segment_manager;
typedef typename segment_manager::void_pointer void_pointer;
typedef typename detail::
typedef typename boost::
pointer_to_other<void_pointer, const void>::type cvoid_pointer;
typedef typename base_t::pointer pointer;
typedef typename base_t::size_type size_type;
typedef typename base_t::multiallocation_iterator multiallocation_iterator;
typedef typename base_t::multiallocation_chain multiallocation_chain;
typedef typename base_t::value_type value_type;
@@ -587,8 +615,8 @@ class cached_allocator_impl
//!preferred_elements. The number of actually allocated elements is
//!will be assigned to received_size. Memory allocated with this function
//!must be deallocated only with deallocate_one().
multiallocation_iterator allocate_individual(std::size_t num_elements)
{ return multiallocation_iterator(this->m_cache.cached_allocation(num_elements)); }
multiallocation_chain allocate_individual(std::size_t num_elements)
{ return multiallocation_chain(this->m_cache.cached_allocation(num_elements)); }
//!Deallocates memory previously allocated with allocate_one().
//!You should never use deallocate_one to deallocate memory allocated
@@ -602,8 +630,12 @@ class cached_allocator_impl
//!preferred_elements. The number of actually allocated elements is
//!will be assigned to received_size. Memory allocated with this function
//!must be deallocated only with deallocate_one().
void deallocate_individual(multiallocation_iterator it)
{ m_cache.cached_deallocation(it.base()); }
void deallocate_individual(multiallocation_chain chain)
{
typename node_pool_t::multiallocation_chain mem
(chain.extract_multiallocation_chain());
m_cache.cached_deallocation(boost::interprocess::move(mem));
}
//!Deallocates all free blocks of the pool
void deallocate_free_blocks()
@@ -655,11 +687,10 @@ class shared_pool_impl
{
public:
//!Segment manager typedef
typedef typename private_node_allocator_t::segment_manager segment_manager;
typedef typename private_node_allocator_t::
multiallocation_iterator multiallocation_iterator;
segment_manager segment_manager;
typedef typename private_node_allocator_t::
multiallocation_chain multiallocation_chain;
multiallocation_chain multiallocation_chain;
private:
typedef typename segment_manager::mutex_family::mutex_type mutex_type;
@@ -691,7 +722,7 @@ class shared_pool_impl
//-----------------------
private_node_allocator_t::deallocate_node(ptr);
}
/*
//!Allocates a singly linked list of n nodes ending in null pointer.
//!can throw boost::interprocess::bad_alloc
void allocate_nodes(multiallocation_chain &nodes, std::size_t n)
@@ -701,10 +732,10 @@ class shared_pool_impl
//-----------------------
return private_node_allocator_t::allocate_nodes(nodes, n);
}
//!Allocates n nodes, pointed by the multiallocation_iterator.
*/
//!Allocates n nodes.
//!Can throw boost::interprocess::bad_alloc
multiallocation_iterator allocate_nodes(const std::size_t n)
multiallocation_chain allocate_nodes(const std::size_t n)
{
//-----------------------
boost::interprocess::scoped_lock<mutex_type> guard(m_header);
@@ -721,22 +752,13 @@ class shared_pool_impl
private_node_allocator_t::deallocate_nodes(nodes, num);
}
//!Deallocates a linked list of nodes ending in null pointer. Never throws
void deallocate_nodes(multiallocation_chain &nodes)
{
//-----------------------
boost::interprocess::scoped_lock<mutex_type> guard(m_header);
//-----------------------
private_node_allocator_t::deallocate_nodes(nodes);
}
//!Deallocates the nodes pointed by the multiallocation iterator. Never throws
void deallocate_nodes(multiallocation_iterator it)
void deallocate_nodes(multiallocation_chain chain)
{
//-----------------------
boost::interprocess::scoped_lock<mutex_type> guard(m_header);
//-----------------------
private_node_allocator_t::deallocate_nodes(it);
private_node_allocator_t::deallocate_nodes(boost::interprocess::move(chain));
}
//!Deallocates all the free blocks of memory. Never throws
@@ -814,4 +836,4 @@ class shared_pool_impl
#include <boost/interprocess/detail/config_end.hpp>
#endif //#ifndef BOOST_INTERPROCESS_DETAIL_NODE_ALLOCATOR_COMMON_HPP
#endif //#ifndef BOOST_INTERPROCESS_ALLOCATOR_DETAIL_ALLOCATOR_COMMON_HPP

View File

@@ -18,14 +18,17 @@
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/intrusive/slist.hpp>
#include <boost/math/common_factor_ct.hpp>
#include <boost/pointer_to_other.hpp>
#include <boost/interprocess/sync/interprocess_mutex.hpp>
#include <boost/interprocess/detail/utilities.hpp>
#include <boost/interprocess/exceptions.hpp>
#include <boost/intrusive/slist.hpp>
#include <boost/math/common_factor_ct.hpp>
#include <boost/interprocess/detail/math_functions.hpp>
#include <boost/interprocess/detail/type_traits.hpp>
#include <boost/interprocess/allocators/detail/node_tools.hpp>
#include <boost/interprocess/mem_algo/detail/mem_algo_common.hpp>
#include <boost/interprocess/allocators/detail/allocator_common.hpp>
#include <cstddef>
#include <functional>
@@ -53,7 +56,6 @@ class private_node_pool_impl
typedef typename node_slist<void_pointer>::slist_hook_t slist_hook_t;
typedef typename node_slist<void_pointer>::node_t node_t;
typedef typename node_slist<void_pointer>::node_slist_t free_nodes_t;
typedef typename SegmentManagerBase::multiallocation_iterator multiallocation_iterator;
typedef typename SegmentManagerBase::multiallocation_chain multiallocation_chain;
private:
@@ -112,25 +114,9 @@ class private_node_pool_impl
--m_allocated;
}
//!Allocates a singly linked list of n nodes ending in null pointer and pushes them in the chain.
//!can throw boost::interprocess::bad_alloc
void allocate_nodes(multiallocation_chain &nodes, const std::size_t n)
{
std::size_t i = 0;
try{
for(; i < n; ++i){
nodes.push_front(this->allocate_node());
}
}
catch(...){
this->deallocate_nodes(nodes, i);
throw;
}
}
//!Allocates a singly linked list of n nodes ending in null pointer
//!can throw boost::interprocess::bad_alloc
multiallocation_iterator allocate_nodes(const std::size_t n)
multiallocation_chain allocate_nodes(const std::size_t n)
{
multiallocation_chain nodes;
std::size_t i = 0;
@@ -143,32 +129,26 @@ class private_node_pool_impl
this->deallocate_nodes(nodes, i);
throw;
}
return nodes.get_it();
}
//!Deallocates a linked list of nodes. Never throws
void deallocate_nodes(multiallocation_chain &nodes)
{
this->deallocate_nodes(nodes.get_it());
nodes.reset();
return boost::interprocess::move(nodes);
}
//!Deallocates the first n nodes of a linked list of nodes. Never throws
void deallocate_nodes(multiallocation_chain &nodes, std::size_t num)
void deallocate_nodes(multiallocation_chain &nodes, std::size_t n)
{
assert(nodes.size() >= num);
for(std::size_t i = 0; i < num; ++i){
deallocate_node(nodes.pop_front());
for(std::size_t i = 0; i < n; ++i){
void *p = detail::get_pointer(nodes.front());
assert(p);
nodes.pop_front();
this->deallocate_node(p);
}
}
//!Deallocates the nodes pointed by the multiallocation iterator. Never throws
void deallocate_nodes(multiallocation_iterator it)
void deallocate_nodes(multiallocation_chain chain)
{
multiallocation_iterator itend;
while(it != itend){
void *addr = &*it;
++it;
while(!chain.empty()){
void *addr = detail::get_pointer(chain.front());
chain.pop_front();
deallocate_node(addr);
}
}
@@ -347,7 +327,7 @@ class private_node_pool_impl
}
private:
typedef typename pointer_to_other
typedef typename boost::pointer_to_other
<void_pointer, segment_manager_base_type>::type segment_mngr_base_ptr_t;
const std::size_t m_nodes_per_block;

View File

@@ -18,6 +18,8 @@
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/pointer_to_other.hpp>
#include <boost/interprocess/interprocess_fwd.hpp>
#include <boost/assert.hpp>
#include <boost/utility/addressof.hpp>
@@ -77,9 +79,9 @@ class node_allocator_base
public:
//-------
typedef typename detail::
typedef typename boost::
pointer_to_other<void_pointer, T>::type pointer;
typedef typename detail::
typedef typename boost::
pointer_to_other<void_pointer, const T>::type const_pointer;
typedef T value_type;
typedef typename detail::add_reference
@@ -89,13 +91,9 @@ class node_allocator_base
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
typedef detail::version_type<node_allocator_base, Version> version;
typedef transform_iterator
< typename SegmentManager::
multiallocation_iterator
, detail::cast_functor <T> > multiallocation_iterator;
typedef typename SegmentManager::
multiallocation_chain multiallocation_chain;
typedef boost::interprocess::version_type<node_allocator_base, Version> version;
typedef detail::transform_multiallocation_chain
<typename SegmentManager::multiallocation_chain, T>multiallocation_chain;
//!Obtains node_allocator_base from
//!node_allocator_base
@@ -251,7 +249,7 @@ class node_allocator
typedef detail::node_allocator_base
< 2, T, SegmentManager, NodesPerBlock> base_t;
public:
typedef detail::version_type<node_allocator, 2> version;
typedef boost::interprocess::version_type<node_allocator, 2> version;
template<class T2>
struct rebind
@@ -373,7 +371,7 @@ class node_allocator
size_type size(const pointer &p) const;
std::pair<pointer, bool>
allocation_command(allocation_type command,
allocation_command(boost::interprocess::allocation_type command,
size_type limit_size,
size_type preferred_size,
size_type &received_size, const pointer &reuse = 0);
@@ -384,12 +382,12 @@ class node_allocator
//!preferred_elements. The number of actually allocated elements is
//!will be assigned to received_size. The elements must be deallocated
//!with deallocate(...)
multiallocation_iterator allocate_many(size_type elem_size, std::size_t num_elements);
multiallocation_chain allocate_many(size_type elem_size, std::size_t num_elements);
//!Allocates n_elements elements, each one of size elem_sizes[i]in a
//!contiguous block
//!of memory. The elements must be deallocated
multiallocation_iterator allocate_many(const size_type *elem_sizes, size_type n_elements);
multiallocation_chain allocate_many(const size_type *elem_sizes, size_type n_elements);
//!Allocates many elements of size elem_size in a contiguous block
//!of memory. The minimum number to be allocated is min_elements,
@@ -397,7 +395,7 @@ class node_allocator
//!preferred_elements. The number of actually allocated elements is
//!will be assigned to received_size. The elements must be deallocated
//!with deallocate(...)
void deallocate_many(multiallocation_iterator it);
void deallocate_many(multiallocation_chain chain);
//!Allocates just one object. Memory allocated with this function
//!must be deallocated only with deallocate_one().
@@ -410,7 +408,7 @@ class node_allocator
//!preferred_elements. The number of actually allocated elements is
//!will be assigned to received_size. Memory allocated with this function
//!must be deallocated only with deallocate_one().
multiallocation_iterator allocate_individual(std::size_t num_elements);
multiallocation_chain allocate_individual(std::size_t num_elements);
//!Deallocates memory previously allocated with allocate_one().
//!You should never use deallocate_one to deallocate memory allocated
@@ -423,7 +421,7 @@ class node_allocator
//!preferred_elements. The number of actually allocated elements is
//!will be assigned to received_size. Memory allocated with this function
//!must be deallocated only with deallocate_one().
void deallocate_individual(multiallocation_iterator it);
void deallocate_individual(multiallocation_chain chain);
#endif
};

View File

@@ -18,6 +18,8 @@
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/pointer_to_other.hpp>
#include <boost/interprocess/interprocess_fwd.hpp>
#include <boost/assert.hpp>
#include <boost/utility/addressof.hpp>
@@ -78,9 +80,9 @@ class private_adaptive_pool_base
/// @endcond
public:
typedef typename detail::
typedef typename boost::
pointer_to_other<void_pointer, T>::type pointer;
typedef typename detail::
typedef typename boost::
pointer_to_other<void_pointer, const T>::type const_pointer;
typedef T value_type;
typedef typename detail::add_reference
@@ -89,14 +91,10 @@ class private_adaptive_pool_base
<const value_type>::type const_reference;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
typedef detail::version_type
typedef boost::interprocess::version_type
<private_adaptive_pool_base, Version> version;
typedef transform_iterator
< typename SegmentManager::
multiallocation_iterator
, detail::cast_functor <T> > multiallocation_iterator;
typedef typename SegmentManager::
multiallocation_chain multiallocation_chain;
typedef detail::transform_multiallocation_chain
<typename SegmentManager::multiallocation_chain, T>multiallocation_chain;
//!Obtains node_allocator from other node_allocator
template<class T2>
@@ -264,7 +262,7 @@ class private_adaptive_pool
typedef detail::private_adaptive_pool_base
< 2, T, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> base_t;
public:
typedef detail::version_type<private_adaptive_pool, 2> version;
typedef boost::interprocess::version_type<private_adaptive_pool, 2> version;
template<class T2>
struct rebind
@@ -388,7 +386,7 @@ class private_adaptive_pool
size_type size(const pointer &p) const;
std::pair<pointer, bool>
allocation_command(allocation_type command,
allocation_command(boost::interprocess::allocation_type command,
size_type limit_size,
size_type preferred_size,
size_type &received_size, const pointer &reuse = 0);
@@ -399,12 +397,12 @@ class private_adaptive_pool
//!preferred_elements. The number of actually allocated elements is
//!will be assigned to received_size. The elements must be deallocated
//!with deallocate(...)
multiallocation_iterator allocate_many(size_type elem_size, std::size_t num_elements);
multiallocation_chain allocate_many(size_type elem_size, std::size_t num_elements);
//!Allocates n_elements elements, each one of size elem_sizes[i]in a
//!contiguous block
//!of memory. The elements must be deallocated
multiallocation_iterator allocate_many(const size_type *elem_sizes, size_type n_elements);
multiallocation_chain allocate_many(const size_type *elem_sizes, size_type n_elements);
//!Allocates many elements of size elem_size in a contiguous block
//!of memory. The minimum number to be allocated is min_elements,
@@ -412,7 +410,7 @@ class private_adaptive_pool
//!preferred_elements. The number of actually allocated elements is
//!will be assigned to received_size. The elements must be deallocated
//!with deallocate(...)
void deallocate_many(multiallocation_iterator it);
void deallocate_many(multiallocation_chain chain);
//!Allocates just one object. Memory allocated with this function
//!must be deallocated only with deallocate_one().
@@ -425,7 +423,7 @@ class private_adaptive_pool
//!preferred_elements. The number of actually allocated elements is
//!will be assigned to received_size. Memory allocated with this function
//!must be deallocated only with deallocate_one().
multiallocation_iterator allocate_individual(std::size_t num_elements);
multiallocation_chain allocate_individual(std::size_t num_elements);
//!Deallocates memory previously allocated with allocate_one().
//!You should never use deallocate_one to deallocate memory allocated
@@ -438,7 +436,7 @@ class private_adaptive_pool
//!preferred_elements. The number of actually allocated elements is
//!will be assigned to received_size. Memory allocated with this function
//!must be deallocated only with deallocate_one().
void deallocate_individual(multiallocation_iterator it);
void deallocate_individual(multiallocation_chain chain);
#endif
};

View File

@@ -18,6 +18,8 @@
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/pointer_to_other.hpp>
#include <boost/interprocess/interprocess_fwd.hpp>
#include <boost/assert.hpp>
#include <boost/utility/addressof.hpp>
@@ -72,9 +74,9 @@ class private_node_allocator_base
/// @endcond
public:
typedef typename detail::
typedef typename boost::
pointer_to_other<void_pointer, T>::type pointer;
typedef typename detail::
typedef typename boost::
pointer_to_other<void_pointer, const T>::type const_pointer;
typedef T value_type;
typedef typename detail::add_reference
@@ -83,14 +85,10 @@ class private_node_allocator_base
<const value_type>::type const_reference;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
typedef detail::version_type
typedef boost::interprocess::version_type
<private_node_allocator_base, Version> version;
typedef transform_iterator
< typename SegmentManager::
multiallocation_iterator
, detail::cast_functor <T> > multiallocation_iterator;
typedef typename SegmentManager::
multiallocation_chain multiallocation_chain;
typedef detail::transform_multiallocation_chain
<typename SegmentManager::multiallocation_chain, T>multiallocation_chain;
//!Obtains node_allocator from other node_allocator
template<class T2>
@@ -240,7 +238,7 @@ class private_node_allocator
typedef detail::private_node_allocator_base
< 2, T, SegmentManager, NodesPerBlock> base_t;
public:
typedef detail::version_type<private_node_allocator, 2> version;
typedef boost::interprocess::version_type<private_node_allocator, 2> version;
template<class T2>
struct rebind
@@ -364,7 +362,7 @@ class private_node_allocator
size_type size(const pointer &p) const;
std::pair<pointer, bool>
allocation_command(allocation_type command,
allocation_command(boost::interprocess::allocation_type command,
size_type limit_size,
size_type preferred_size,
size_type &received_size, const pointer &reuse = 0);
@@ -375,12 +373,12 @@ class private_node_allocator
//!preferred_elements. The number of actually allocated elements is
//!will be assigned to received_size. The elements must be deallocated
//!with deallocate(...)
multiallocation_iterator allocate_many(size_type elem_size, std::size_t num_elements);
multiallocation_chain allocate_many(size_type elem_size, std::size_t num_elements);
//!Allocates n_elements elements, each one of size elem_sizes[i]in a
//!contiguous block
//!of memory. The elements must be deallocated
multiallocation_iterator allocate_many(const size_type *elem_sizes, size_type n_elements);
multiallocation_chain allocate_many(const size_type *elem_sizes, size_type n_elements);
//!Allocates many elements of size elem_size in a contiguous block
//!of memory. The minimum number to be allocated is min_elements,
@@ -388,7 +386,7 @@ class private_node_allocator
//!preferred_elements. The number of actually allocated elements is
//!will be assigned to received_size. The elements must be deallocated
//!with deallocate(...)
void deallocate_many(multiallocation_iterator it);
void deallocate_many(multiallocation_chain chain);
//!Allocates just one object. Memory allocated with this function
//!must be deallocated only with deallocate_one().
@@ -401,7 +399,7 @@ class private_node_allocator
//!preferred_elements. The number of actually allocated elements is
//!will be assigned to received_size. Memory allocated with this function
//!must be deallocated only with deallocate_one().
multiallocation_iterator allocate_individual(std::size_t num_elements);
multiallocation_chain allocate_individual(std::size_t num_elements);
//!Deallocates memory previously allocated with allocate_one().
//!You should never use deallocate_one to deallocate memory allocated
@@ -414,7 +412,7 @@ class private_node_allocator
//!preferred_elements. The number of actually allocated elements is
//!will be assigned to received_size. Memory allocated with this function
//!must be deallocated only with deallocate_one().
void deallocate_individual(multiallocation_iterator it);
void deallocate_individual(multiallocation_chain chain);
#endif
};

View File

@@ -19,7 +19,7 @@
#include <boost/interprocess/mapped_region.hpp>
#include <cstddef>
#if (!defined(BOOST_WINDOWS)) || defined(BOOST_DISABLE_WIN32)
#if (!defined(BOOST_INTERPROCESS_WINDOWS))
# include <fcntl.h> //open, O_CREAT, O_*...
# include <sys/mman.h> //mmap
# include <sys/stat.h> //mode_t, S_IRWXG, S_IRWXO, S_IRWXU,
@@ -42,12 +42,7 @@ namespace detail{
class raw_mapped_region_creator
{
public:
static
#ifdef BOOST_INTERPROCESS_RVALUE_REFERENCE
mapped_region
#else
move_return<mapped_region>
#endif
static mapped_region
create_posix_mapped_region(void *address, offset_t offset, std::size_t size)
{
mapped_region region;
@@ -67,14 +62,10 @@ namespace detail{
//!Otherwise the operating system will choose the mapping address.
//!The function returns a mapped_region holding that segment or throws
//!interprocess_exception if the function fails.
static
#ifdef BOOST_INTERPROCESS_RVALUE_REFERENCE
mapped_region
#else
detail::move_return<mapped_region>
#endif
//static mapped_region
static mapped_region
anonymous_shared_memory(std::size_t size, void *address = 0)
#if (!defined(BOOST_WINDOWS)) || defined(BOOST_DISABLE_WIN32)
#if (!defined(BOOST_INTERPROCESS_WINDOWS))
{
int flags;
int fd = -1;
@@ -115,8 +106,7 @@ anonymous_shared_memory(std::size_t size, void *address = 0)
#else
{
windows_shared_memory anonymous_mapping(create_only, 0, read_write, size);
mapped_region region(anonymous_mapping, read_write, 0, size, address);
return region;
return mapped_region(anonymous_mapping, read_write, 0, size, address);
}
#endif

View File

@@ -0,0 +1,40 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2008-2009. 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.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTERPROCESS_CONTAINERS_ALLOCATION_TYPE_HPP
#define BOOST_INTERPROCESS_CONTAINERS_ALLOCATION_TYPE_HPP
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/containers/container/detail/allocation_type.hpp>
namespace boost {
namespace interprocess {
/// @cond
typedef int allocation_type;
/// @endcond
static const allocation_type allocate_new = boost::interprocess_container::allocate_new;
static const allocation_type expand_fwd = boost::interprocess_container::expand_fwd;
static const allocation_type expand_bwd = boost::interprocess_container::expand_bwd;
static const allocation_type shrink_in_place = boost::interprocess_container::shrink_in_place;
static const allocation_type try_shrink_in_place= boost::interprocess_container::try_shrink_in_place;
static const allocation_type nothrow_allocation = boost::interprocess_container::nothrow_allocation;
static const allocation_type zero_memory = boost::interprocess_container::zero_memory;
} //namespace interprocess {
} //namespace boost {
#include <boost/interprocess/detail/config_end.hpp>
#endif // #ifndef BOOST_INTERPROCESS_CONTAINERS_VERSION_TYPE_HPP

View File

@@ -0,0 +1,153 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005-2008. 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/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINERS_CONTAINERS_FWD_HPP
#define BOOST_CONTAINERS_CONTAINERS_FWD_HPP
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif
//////////////////////////////////////////////////////////////////////////////
// Standard predeclarations
//////////////////////////////////////////////////////////////////////////////
/// @cond
namespace boost{
namespace intrusive{
//Create namespace to avoid compilation errors
}}
namespace boost{ namespace interprocess_container{ namespace containers_detail{
namespace bi = boost::intrusive;
}}}
namespace std {
template <class T>
class allocator;
template <class T>
struct less;
template <class T1, class T2>
struct pair;
template <class CharType>
struct char_traits;
} //namespace std {
/// @endcond
//////////////////////////////////////////////////////////////////////////////
// Containers
//////////////////////////////////////////////////////////////////////////////
#ifdef BOOST_INTERPROCESS_DOXYGEN_INVOKED
namespace boost {
namespace interprocess {
#else
namespace boost {
namespace interprocess_container {
#endif
//vector class
template <class T
,class A = std::allocator<T> >
class vector;
//vector class
template <class T
,class A = std::allocator<T> >
class deque;
//list class
template <class T
,class A = std::allocator<T> >
class list;
//slist class
template <class T
,class Alloc = std::allocator<T> >
class slist;
//set class
template <class T
,class Pred = std::less<T>
,class Alloc = std::allocator<T> >
class set;
//multiset class
template <class T
,class Pred = std::less<T>
,class Alloc = std::allocator<T> >
class multiset;
//map class
template <class Key
,class T
,class Pred = std::less<Key>
,class Alloc = std::allocator<std::pair<const Key, T> > >
class map;
//multimap class
template <class Key
,class T
,class Pred = std::less<Key>
,class Alloc = std::allocator<std::pair<const Key, T> > >
class multimap;
//flat_set class
template <class T
,class Pred = std::less<T>
,class Alloc = std::allocator<T> >
class flat_set;
//flat_multiset class
template <class T
,class Pred = std::less<T>
,class Alloc = std::allocator<T> >
class flat_multiset;
//flat_map class
template <class Key
,class T
,class Pred = std::less<Key>
,class Alloc = std::allocator<std::pair<Key, T> > >
class flat_map;
//flat_multimap class
template <class Key
,class T
,class Pred = std::less<Key>
,class Alloc = std::allocator<std::pair<Key, T> > >
class flat_multimap;
//basic_string class
template <class CharT
,class Traits = std::char_traits<CharT>
,class Alloc = std::allocator<CharT> >
class basic_string;
//string class
typedef basic_string
<char
,std::char_traits<char>
,std::allocator<char> >
string;
}} //namespace boost { namespace interprocess_container {
#endif //#ifndef BOOST_CONTAINERS_CONTAINERS_FWD_HPP

File diff suppressed because it is too large Load Diff

View File

@@ -4,26 +4,26 @@
// 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.
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTERPROCESS_ADVANCED_INSERT_INT_HPP
#define BOOST_INTERPROCESS_ADVANCED_INSERT_INT_HPP
#ifndef BOOST_CONTAINERS_ADVANCED_INSERT_INT_HPP
#define BOOST_CONTAINERS_ADVANCED_INSERT_INT_HPP
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/interprocess/containers/container/detail/config_begin.hpp>
#include <boost/interprocess/containers/container/detail/workaround.hpp>
#include <boost/interprocess/detail/move.hpp>
#include <iterator> //std::iterator_traits
#include <algorithm> //std::copy, std::uninitialized_copy
#include <new> //placement new
#include <cassert>
namespace boost { namespace interprocess { namespace detail {
namespace boost { namespace interprocess_container { namespace containers_detail {
//This class will be interface for operations dependent on FwdIt types used advanced_insert_aux_impl
template<class T, class Iterator>
@@ -51,21 +51,21 @@ struct advanced_insert_aux_proxy
{}
virtual void copy_all_to(Iterator p)
{ *std::copy(first_, last_, p); }
{ std::copy(first_, last_, p); }
virtual void uninitialized_copy_all_to(Iterator p)
{ std::uninitialized_copy(first_, last_, p); }
{ boost::interprocess::uninitialized_copy_or_move(first_, last_, p); }
virtual void uninitialized_copy_some_and_update(Iterator pos, difference_type division_count, bool first_n)
{
FwdIt mid = first_;
std::advance(mid, division_count);
if(first_n){
std::uninitialized_copy(first_, mid, pos);
boost::interprocess::uninitialized_copy_or_move(first_, mid, pos);
first_ = mid;
}
else{
std::uninitialized_copy(mid, last_, pos);
boost::interprocess::uninitialized_copy_or_move(mid, last_, pos);
last_ = mid;
}
}
@@ -104,12 +104,12 @@ struct default_construct_aux_proxy
SizeType i = 0;
try{
for(; i < n; ++i, ++p){
new(detail::get_pointer(&*p))T();
new(containers_detail::get_pointer(&*p))T();
}
}
catch(...){
while(i--){
detail::get_pointer(&*orig_p++)->~T();
containers_detail::get_pointer(&*orig_p++)->~T();
}
throw;
}
@@ -159,18 +159,18 @@ struct default_construct_aux_proxy
SizeType count_;
};
}}} //namespace boost { namespace interprocess { namespace detail {
}}} //namespace boost { namespace interprocess_container { namespace containers_detail {
#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
#include <boost/interprocess/detail/variadic_templates_tools.hpp>
#include <boost/interprocess/containers/container/detail/variadic_templates_tools.hpp>
#include <boost/interprocess/detail/move.hpp>
#include <typeinfo>
//#include <iostream> //For debugging purposes
namespace boost {
namespace interprocess {
namespace detail {
namespace interprocess_container {
namespace containers_detail {
//This class template will adapt each FwIt types to advanced_insert_aux_int
template<class T, class Iterator, class ...Args>
@@ -204,8 +204,8 @@ struct advanced_insert_aux_emplace
void priv_copy_all_to(const index_tuple<IdxPack...>&, Iterator p)
{
if(!used_){
T object(detail::forward_impl<Args>(get<IdxPack>(args_))...);
*p = detail::move_impl(object);
T object(boost::interprocess::forward<Args>(get<IdxPack>(args_))...);
*p = boost::interprocess::move(object);
used_ = true;
}
}
@@ -214,7 +214,7 @@ struct advanced_insert_aux_emplace
void priv_uninitialized_copy_all_to(const index_tuple<IdxPack...>&, Iterator p)
{
if(!used_){
new(detail::get_pointer(&*p))T(detail::forward_impl<Args>(get<IdxPack>(args_))...);
new(containers_detail::get_pointer(&*p))T(boost::interprocess::forward<Args>(get<IdxPack>(args_))...);
used_ = true;
}
}
@@ -225,7 +225,7 @@ struct advanced_insert_aux_emplace
assert(division_count <=1);
if((first_n && division_count == 1) || (!first_n && division_count == 0)){
if(!used_){
new(detail::get_pointer(&*p))T(detail::forward_impl<Args>(get<IdxPack>(args_))...);
new(containers_detail::get_pointer(&*p))T(boost::interprocess::forward<Args>(get<IdxPack>(args_))...);
used_ = true;
}
}
@@ -237,8 +237,8 @@ struct advanced_insert_aux_emplace
assert(division_count <=1);
if((first_n && division_count == 1) || (!first_n && division_count == 0)){
if(!used_){
T object(detail::forward_impl<Args>(get<IdxPack>(args_))...);
*p = detail::move_impl(object);
T object(boost::interprocess::forward<Args>(get<IdxPack>(args_))...);
*p = boost::interprocess::move(object);
used_ = true;
}
}
@@ -247,25 +247,16 @@ struct advanced_insert_aux_emplace
bool used_;
};
}}} //namespace boost { namespace interprocess { namespace detail {
}}} //namespace boost { namespace interprocess_container { namespace containers_detail {
#else //#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
#else //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
#include <boost/interprocess/detail/preprocessor.hpp>
#include <boost/interprocess/containers/container/detail/preprocessor.hpp>
#include <boost/interprocess/containers/container/detail/value_init.hpp>
namespace boost {
namespace interprocess {
namespace detail {
template<class T>
struct value_init_helper
{
value_init_helper()
: m_t()
{}
T m_t;
};
namespace interprocess_container {
namespace containers_detail {
//This class template will adapt each FwIt types to advanced_insert_aux_int
template<class T, class Iterator>
@@ -283,8 +274,8 @@ struct advanced_insert_aux_emplace
virtual void copy_all_to(Iterator p)
{
if(!used_){
value_init_helper<T>v;
*p = detail::move_impl(v.m_t);
value_init<T>v;
*p = boost::interprocess::move(v.m_t);
used_ = true;
}
}
@@ -292,7 +283,7 @@ struct advanced_insert_aux_emplace
virtual void uninitialized_copy_all_to(Iterator p)
{
if(!used_){
new(detail::get_pointer(&*p))T();
new(containers_detail::get_pointer(&*p))T();
used_ = true;
}
}
@@ -302,7 +293,7 @@ struct advanced_insert_aux_emplace
assert(division_count <=1);
if((first_n && division_count == 1) || (!first_n && division_count == 0)){
if(!used_){
new(detail::get_pointer(&*p))T();
new(containers_detail::get_pointer(&*p))T();
used_ = true;
}
}
@@ -313,8 +304,8 @@ struct advanced_insert_aux_emplace
assert(division_count <=1);
if((first_n && division_count == 1) || (!first_n && division_count == 0)){
if(!used_){
value_init_helper<T>v;
*p = detail::move_impl(v.m_t);
value_init<T>v;
*p = boost::interprocess::move(v.m_t);
used_ = true;
}
}
@@ -331,14 +322,14 @@ struct advanced_insert_aux_emplace
typedef typename advanced_insert_aux_int<T, Iterator>::difference_type difference_type; \
\
BOOST_PP_CAT(BOOST_PP_CAT(advanced_insert_aux_emplace, n), arg) \
( BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_LIST, _) ) \
: used_(false), BOOST_PP_ENUM(n, BOOST_INTERPROCESS_AUX_PARAM_INIT, _) {} \
( BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _) ) \
: used_(false), BOOST_PP_ENUM(n, BOOST_CONTAINERS_AUX_PARAM_INIT, _) {} \
\
virtual void copy_all_to(Iterator p) \
{ \
if(!used_){ \
T v(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_MEMBER_FORWARD, _)); \
*p = detail::move_impl(v); \
T v(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_MEMBER_FORWARD, _)); \
*p = boost::interprocess::move(v); \
used_ = true; \
} \
} \
@@ -346,8 +337,8 @@ struct advanced_insert_aux_emplace
virtual void uninitialized_copy_all_to(Iterator p) \
{ \
if(!used_){ \
new(detail::get_pointer(&*p))T \
(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_MEMBER_FORWARD, _)); \
new(containers_detail::get_pointer(&*p))T \
(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_MEMBER_FORWARD, _)); \
used_ = true; \
} \
} \
@@ -358,8 +349,8 @@ struct advanced_insert_aux_emplace
assert(division_count <=1); \
if((first_n && division_count == 1) || (!first_n && division_count == 0)){ \
if(!used_){ \
new(detail::get_pointer(&*p))T \
(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_MEMBER_FORWARD, _)); \
new(containers_detail::get_pointer(&*p))T \
(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_MEMBER_FORWARD, _)); \
used_ = true; \
} \
} \
@@ -371,25 +362,25 @@ struct advanced_insert_aux_emplace
assert(division_count <=1); \
if((first_n && division_count == 1) || (!first_n && division_count == 0)){ \
if(!used_){ \
T v(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_MEMBER_FORWARD, _)); \
*p = detail::move_impl(v); \
T v(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_MEMBER_FORWARD, _)); \
*p = boost::interprocess::move(v); \
used_ = true; \
} \
} \
} \
\
bool used_; \
BOOST_PP_REPEAT(n, BOOST_INTERPROCESS_AUX_PARAM_DEFINE, _) \
BOOST_PP_REPEAT(n, BOOST_CONTAINERS_AUX_PARAM_DEFINE, _) \
}; \
//!
#define BOOST_PP_LOCAL_LIMITS (1, BOOST_INTERPROCESS_MAX_CONSTRUCTOR_PARAMETERS)
#define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINERS_MAX_CONSTRUCTOR_PARAMETERS)
#include BOOST_PP_LOCAL_ITERATE()
}}} //namespace boost { namespace interprocess { namespace detail {
}}} //namespace boost { namespace interprocess_container { namespace containers_detail {
#endif //#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
#endif //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
#include <boost/interprocess/detail/config_end.hpp>
#include <boost/interprocess/containers/container/detail/config_end.hpp>
#endif //#ifndef BOOST_INTERPROCESS_ADVANCED_INSERT_INT_HPP
#endif //#ifndef BOOST_CONTAINERS_ADVANCED_INSERT_INT_HPP

View File

@@ -6,59 +6,63 @@
// (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.
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTERPROCESS_DETAIL_ALGORITHMS_HPP
#define BOOST_INTERPROCESS_DETAIL_ALGORITHMS_HPP
#ifndef BOOST_CONTAINERS_DETAIL_ALGORITHMS_HPP
#define BOOST_CONTAINERS_DETAIL_ALGORITHMS_HPP
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/interprocess/detail/iterators.hpp>
#include <boost/interprocess/detail/type_traits.hpp>
#include <boost/interprocess/containers/container/detail/config_begin.hpp>
#include <boost/interprocess/containers/container/detail/workaround.hpp>
#include <boost/type_traits/has_trivial_copy.hpp>
#include <boost/type_traits/has_trivial_assign.hpp>
#include <boost/detail/no_exceptions_support.hpp>
#include <boost/get_pointer.hpp>
#include <boost/interprocess/containers/container/detail/type_traits.hpp>
#include <boost/interprocess/containers/container/detail/mpl.hpp>
#include <boost/interprocess/containers/container/detail/iterators.hpp>
#include <cstring>
namespace boost {
namespace interprocess {
#if !defined(BOOST_INTERPROCESS_RVALUE_REFERENCE) || !defined(BOOST_INTERPROCESS_RVALUE_PAIR)
namespace interprocess_container {
#if !defined(BOOST_HAS_RVALUE_REFS)
template<class T>
struct has_own_construct_from_it
{
static const bool value = false;
};
namespace detail {
namespace containers_detail {
template<class T, class InpIt>
inline void construct_in_place_impl(T* dest, const InpIt &source, detail::true_)
inline void construct_in_place_impl(T* dest, const InpIt &source, containers_detail::true_)
{
T::construct(dest, *source);
}
template<class T, class InpIt>
inline void construct_in_place_impl(T* dest, const InpIt &source, detail::false_)
inline void construct_in_place_impl(T* dest, const InpIt &source, containers_detail::false_)
{
new((void*)dest)T(*source);
}
} //namespace detail {
} //namespace containers_detail {
template<class T, class InpIt>
inline void construct_in_place(T* dest, InpIt source)
{
typedef detail::bool_<has_own_construct_from_it<T>::value> boolean_t;
detail::construct_in_place_impl(dest, source, boolean_t());
typedef containers_detail::bool_<has_own_construct_from_it<T>::value> boolean_t;
containers_detail::construct_in_place_impl(dest, source, boolean_t());
}
#else
@@ -73,6 +77,12 @@ inline void construct_in_place(T *dest, default_construct_iterator<U, D>)
new((void*)dest)T();
}
template<class T, class U, class E>
inline void construct_in_place(T *dest, emplace_iterator<U, E> ei)
{
ei.construct_in_place(dest);
}
template<class InIt, class OutIt>
struct optimize_assign
{
@@ -108,7 +118,7 @@ struct optimize_copy<T*, T*>
{};
template<class InIt, class OutIt> inline
OutIt copy_n_dispatch(InIt first, typename std::iterator_traits<InIt>::difference_type length, OutIt dest, detail::bool_<false>)
OutIt copy_n_dispatch(InIt first, typename std::iterator_traits<InIt>::difference_type length, OutIt dest, containers_detail::bool_<false>)
{
for (; length--; ++dest, ++first)
*dest = *first;
@@ -116,7 +126,7 @@ OutIt copy_n_dispatch(InIt first, typename std::iterator_traits<InIt>::differenc
}
template<class T> inline
T *copy_n_dispatch(const T *first, typename std::iterator_traits<const T*>::difference_type length, T *dest, detail::bool_<true>)
T *copy_n_dispatch(const T *first, typename std::iterator_traits<const T*>::difference_type length, T *dest, containers_detail::bool_<true>)
{
std::size_t size = length*sizeof(T);
return (static_cast<T*>(std::memmove(dest, first, size))) + size;
@@ -126,14 +136,14 @@ template<class InIt, class OutIt> inline
OutIt copy_n(InIt first, typename std::iterator_traits<InIt>::difference_type length, OutIt dest)
{
const bool do_optimized_assign = optimize_assign<InIt, OutIt>::value;
return copy_n_dispatch(first, length, dest, detail::bool_<do_optimized_assign>());
return copy_n_dispatch(first, length, dest, containers_detail::bool_<do_optimized_assign>());
}
template<class InIt, class FwdIt> inline
FwdIt uninitialized_copy_n_dispatch
(InIt first,
typename std::iterator_traits<InIt>::difference_type count,
FwdIt dest, detail::bool_<false>)
FwdIt dest, containers_detail::bool_<false>)
{
typedef typename std::iterator_traits<FwdIt>::value_type value_type;
//Save initial destination position
@@ -143,14 +153,14 @@ FwdIt uninitialized_copy_n_dispatch
BOOST_TRY{
//Try to build objects
for (; --new_count; ++dest, ++first){
construct_in_place(detail::get_pointer(&*dest), first);
construct_in_place(containers_detail::get_pointer(&*dest), first);
}
}
BOOST_CATCH(...){
//Call destructors
new_count = count - new_count;
for (; new_count--; ++dest_init){
detail::get_pointer(&*dest_init)->~value_type();
containers_detail::get_pointer(&*dest_init)->~value_type();
}
BOOST_RETHROW
}
@@ -158,7 +168,7 @@ FwdIt uninitialized_copy_n_dispatch
return dest;
}
template<class T> inline
T *uninitialized_copy_n_dispatch(const T *first, typename std::iterator_traits<const T*>::difference_type length, T *dest, detail::bool_<true>)
T *uninitialized_copy_n_dispatch(const T *first, typename std::iterator_traits<const T*>::difference_type length, T *dest, containers_detail::bool_<true>)
{
std::size_t size = length*sizeof(T);
return (static_cast<T*>(std::memmove(dest, first, size))) + size;
@@ -171,7 +181,7 @@ FwdIt uninitialized_copy_n
FwdIt dest)
{
const bool do_optimized_copy = optimize_copy<InIt, FwdIt>::value;
return uninitialized_copy_n_dispatch(first, count, dest, detail::bool_<do_optimized_copy>());
return uninitialized_copy_n_dispatch(first, count, dest, containers_detail::bool_<do_optimized_copy>());
}
// uninitialized_copy_copy
@@ -189,17 +199,17 @@ FwdIt uninitialized_copy_copy
}
BOOST_CATCH(...){
for(;result != mid; ++result){
detail::get_pointer(&*result)->~value_type();
containers_detail::get_pointer(&*result)->~value_type();
}
BOOST_RETHROW
}
BOOST_CATCH_END
}
} //namespace interprocess {
} //namespace interprocess_container {
} //namespace boost {
#include <boost/interprocess/detail/config_end.hpp>
#include <boost/interprocess/containers/container/detail/config_end.hpp>
#endif //#ifndef BOOST_INTERPROCESS_DETAIL_ALGORITHMS_HPP
#endif //#ifndef BOOST_CONTAINERS_DETAIL_ALGORITHMS_HPP

View File

@@ -4,22 +4,22 @@
// 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.
// See http://www.boost.org/libs/container for documentation.
//
///////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTERPROCESS_TYPE_COMMAND_HPP
#define BOOST_INTERPROCESS_TYPE_COMMAND_HPP
#ifndef BOOST_CONTAINERS_ALLOCATION_TYPE_HPP
#define BOOST_CONTAINERS_ALLOCATION_TYPE_HPP
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/interprocess/containers/container/detail/config_begin.hpp>
#include <boost/interprocess/containers/container/detail/workaround.hpp>
namespace boost {
namespace interprocess {
namespace interprocess_container {
/// @cond
enum allocation_type_v
@@ -46,10 +46,9 @@ static const allocation_type try_shrink_in_place= (allocation_type)try_shrink_in
static const allocation_type nothrow_allocation = (allocation_type)nothrow_allocation_v;
static const allocation_type zero_memory = (allocation_type)zero_memory_v;
} //namespace interprocess {
} //namespace interprocess_container {
} //namespace boost {
#include <boost/interprocess/detail/config_end.hpp>
#endif //BOOST_INTERPROCESS_TYPE_COMMAND_HPP
#include <boost/interprocess/containers/container/detail/config_end.hpp>
#endif //BOOST_CONTAINERS_ALLOCATION_TYPE_HPP

View File

@@ -0,0 +1,47 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005-2008. 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/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINERS_CONTAINER_DETAIL_CONFIG_INCLUDED
#define BOOST_CONTAINERS_CONTAINER_DETAIL_CONFIG_INCLUDED
#include <boost/config.hpp>
#endif
#ifdef BOOST_MSVC
#ifndef _CRT_SECURE_NO_DEPRECATE
#define BOOST_CONTAINERS_DETAIL_CRT_SECURE_NO_DEPRECATE
#define _CRT_SECURE_NO_DEPRECATE
#endif
#pragma warning (push)
#pragma warning (disable : 4702) // unreachable code
#pragma warning (disable : 4706) // assignment within conditional expression
#pragma warning (disable : 4127) // conditional expression is constant
#pragma warning (disable : 4146) // unary minus operator applied to unsigned type, result still unsigned
#pragma warning (disable : 4284) // odd return type for operator->
#pragma warning (disable : 4244) // possible loss of data
#pragma warning (disable : 4251) // "identifier" : class "type" needs to have dll-interface to be used by clients of class "type2"
#pragma warning (disable : 4267) // conversion from "X" to "Y", possible loss of data
#pragma warning (disable : 4275) // non DLL-interface classkey "identifier" used as base for DLL-interface classkey "identifier"
#pragma warning (disable : 4355) // "this" : used in base member initializer list
#pragma warning (disable : 4503) // "identifier" : decorated name length exceeded, name was truncated
#pragma warning (disable : 4511) // copy constructor could not be generated
#pragma warning (disable : 4512) // assignment operator could not be generated
#pragma warning (disable : 4514) // unreferenced inline removed
#pragma warning (disable : 4521) // Disable "multiple copy constructors specified"
#pragma warning (disable : 4522) // "class" : multiple assignment operators specified
#pragma warning (disable : 4675) // "method" should be declared "static" and have exactly one parameter
#pragma warning (disable : 4710) // function not inlined
#pragma warning (disable : 4711) // function selected for automatic inline expansion
#pragma warning (disable : 4786) // identifier truncated in debug info
#pragma warning (disable : 4996) // "function": was declared deprecated
#pragma warning (disable : 4197) // top-level volatile in cast is ignored
#pragma warning (disable : 4541) // 'typeid' used on polymorphic type 'boost::exception'
// with /GR-; unpredictable behavior may result
#pragma warning (disable : 4673) // throwing '' the following types will not be considered at the catch site
#pragma warning (disable : 4671) // the copy constructor is inaccessible
#endif

View File

@@ -0,0 +1,17 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005-2008. 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/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#if defined BOOST_MSVC
#pragma warning (pop)
#ifdef BOOST_CONTAINERS_DETAIL_CRT_SECURE_NO_DEPRECATE
#undef BOOST_CONTAINERS_DETAIL_CRT_SECURE_NO_DEPRECATE
#undef _CRT_SECURE_NO_DEPRECATE
#endif
#endif

View File

@@ -0,0 +1,154 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005-2009.
//
// 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/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINERS_DESTROYERS_HPP
#define BOOST_CONTAINERS_DESTROYERS_HPP
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif
#include <boost/interprocess/containers/container/detail/config_begin.hpp>
#include <boost/interprocess/containers/container/detail/workaround.hpp>
#include <boost/interprocess/containers/container/detail/version_type.hpp>
#include <boost/interprocess/containers/container/detail/utilities.hpp>
namespace boost {
namespace interprocess_container {
namespace containers_detail {
//!A deleter for scoped_ptr that deallocates the memory
//!allocated for an array of objects using a STL allocator.
template <class Allocator>
struct scoped_array_deallocator
{
typedef typename Allocator::pointer pointer;
typedef typename Allocator::size_type size_type;
scoped_array_deallocator(pointer p, Allocator& a, size_type length)
: m_ptr(p), m_alloc(a), m_length(length) {}
~scoped_array_deallocator()
{ if (m_ptr) m_alloc.deallocate(m_ptr, m_length); }
void release()
{ m_ptr = 0; }
private:
pointer m_ptr;
Allocator& m_alloc;
size_type m_length;
};
template <class Allocator>
struct null_scoped_array_deallocator
{
typedef typename Allocator::pointer pointer;
typedef typename Allocator::size_type size_type;
null_scoped_array_deallocator(pointer, Allocator&, size_type)
{}
void release()
{}
};
//!A deleter for scoped_ptr that destroys
//!an object using a STL allocator.
template <class Allocator>
struct scoped_destructor_n
{
typedef typename Allocator::pointer pointer;
typedef typename Allocator::value_type value_type;
typedef typename Allocator::size_type size_type;
pointer m_p;
size_type m_n;
scoped_destructor_n(pointer p, size_type n)
: m_p(p), m_n(n)
{}
void release()
{ m_p = 0; }
void increment_size(size_type inc)
{ m_n += inc; }
~scoped_destructor_n()
{
if(!m_p) return;
value_type *raw_ptr = containers_detail::get_pointer(m_p);
for(std::size_t i = 0; i < m_n; ++i, ++raw_ptr)
raw_ptr->~value_type();
}
};
//!A deleter for scoped_ptr that destroys
//!an object using a STL allocator.
template <class Allocator>
struct null_scoped_destructor_n
{
typedef typename Allocator::pointer pointer;
typedef typename Allocator::size_type size_type;
null_scoped_destructor_n(pointer, size_type)
{}
void increment_size(size_type)
{}
void release()
{}
};
template <class A>
class allocator_destroyer
{
typedef typename A::value_type value_type;
typedef containers_detail::integral_constant<unsigned,
boost::interprocess_container::containers_detail::
version<A>::value> alloc_version;
typedef containers_detail::integral_constant<unsigned, 1> allocator_v1;
typedef containers_detail::integral_constant<unsigned, 2> allocator_v2;
private:
A & a_;
private:
void priv_deallocate(const typename A::pointer &p, allocator_v1)
{ a_.deallocate(p, 1); }
void priv_deallocate(const typename A::pointer &p, allocator_v2)
{ a_.deallocate_one(p); }
public:
allocator_destroyer(A &a)
: a_(a)
{}
void operator()(const typename A::pointer &p)
{
containers_detail::get_pointer(p)->~value_type();
priv_deallocate(p, alloc_version());
}
};
} //namespace containers_detail {
} //namespace interprocess_container {
} //namespace boost {
#include <boost/interprocess/containers/container/detail/config_end.hpp>
#endif //#ifndef BOOST_CONTAINERS_DESTROYERS_HPP

View File

@@ -4,7 +4,7 @@
// 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.
// See http://www.boost.org/libs/container for documentation.
//
////////////////////////////////////////////////////////////////////////////////
// The Loki Library
@@ -25,35 +25,40 @@
//
////////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTERPROCESS_FLAT_TREE_HPP
#define BOOST_INTERPROCESS_FLAT_TREE_HPP
#ifndef BOOST_CONTAINERS_FLAT_TREE_HPP
#define BOOST_CONTAINERS_FLAT_TREE_HPP
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/interprocess/containers/container/detail/config_begin.hpp>
#include <boost/interprocess/containers/container/detail/workaround.hpp>
#include <boost/interprocess/containers/vector.hpp>
#include <boost/interprocess/detail/utilities.hpp>
#include <boost/interprocess/detail/move.hpp>
#include <boost/type_traits/has_trivial_destructor.hpp>
#include <algorithm>
#include <functional>
#include <utility>
#include <boost/type_traits/has_trivial_destructor.hpp>
#include <boost/interprocess/detail/move.hpp>
#include <boost/interprocess/containers/container/detail/utilities.hpp>
#include <boost/interprocess/containers/container/detail/pair.hpp>
#include <boost/interprocess/containers/container/vector.hpp>
#include <boost/interprocess/containers/container/detail/value_init.hpp>
#include <boost/interprocess/containers/container/detail/destroyers.hpp>
namespace boost {
namespace interprocess {
namespace interprocess_container {
namespace detail {
namespace containers_detail {
template <class Key, class Value, class KeyOfValue,
class Compare, class Alloc>
class flat_tree
{
typedef boost::interprocess::vector<Value, Alloc> vector_t;
typedef boost::interprocess_container::vector<Value, Alloc> vector_t;
typedef Alloc allocator_t;
public:
@@ -105,6 +110,7 @@ class flat_tree
Data m_data;
public:
BOOST_INTERPROCESS_ENABLE_MOVE_EMULATION(flat_tree)
typedef typename vector_t::value_type value_type;
typedef typename vector_t::pointer pointer;
@@ -133,15 +139,9 @@ class flat_tree
: m_data(x.m_data, x.m_data.m_vect)
{ }
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
flat_tree(detail::moved_object<flat_tree> x)
: m_data(detail::move_impl(x.get().m_data))
flat_tree(BOOST_INTERPROCESS_RV_REF(flat_tree) x)
: m_data(boost::interprocess::move(x.m_data))
{ }
#else
flat_tree(flat_tree &&x)
: m_data(detail::move_impl(x.m_data))
{ }
#endif
~flat_tree()
{ }
@@ -149,13 +149,8 @@ class flat_tree
flat_tree& operator=(const flat_tree& x)
{ m_data = x.m_data; return *this; }
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
flat_tree& operator=(detail::moved_object<flat_tree> mx)
{ m_data = detail::move_impl(mx.get().m_data); return *this; }
#else
flat_tree& operator=(flat_tree &&mx)
{ m_data = detail::move_impl(mx.m_data); return *this; }
#endif
flat_tree& operator=(BOOST_INTERPROCESS_RV_REF(flat_tree) mx)
{ m_data = boost::interprocess::move(mx.m_data); return *this; }
public:
// accessors:
@@ -220,20 +215,12 @@ class flat_tree
{
value_compare& mycomp = this->m_data;
value_compare& othercomp = other.m_data;
detail::do_swap(mycomp, othercomp);
containers_detail::do_swap(mycomp, othercomp);
vector_t & myvect = this->m_data.m_vect;
vector_t & othervect = other.m_data.m_vect;
myvect.swap(othervect);
}
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
void swap(detail::moved_object<flat_tree> other)
{ this->swap(other.get()); }
#else
void swap(flat_tree &&other)
{ this->swap(other); }
#endif
public:
// insert/erase
std::pair<iterator,bool> insert_unique(const value_type& val)
@@ -246,18 +233,12 @@ class flat_tree
return ret;
}
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
std::pair<iterator,bool> insert_unique(detail::moved_object<value_type> mval)
std::pair<iterator,bool> insert_unique(BOOST_INTERPROCESS_RV_REF(value_type) val)
{
value_type &val = mval.get();
#else
std::pair<iterator,bool> insert_unique(value_type && val)
{
#endif
insert_commit_data data;
std::pair<iterator,bool> ret = priv_insert_unique_prepare(val, data);
if(ret.second){
ret.first = priv_insert_commit(data, detail::move_impl(val));
ret.first = priv_insert_commit(data, boost::interprocess::move(val));
}
return ret;
}
@@ -270,21 +251,12 @@ class flat_tree
return i;
}
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
iterator insert_equal(detail::moved_object<value_type> mval)
{
iterator i = this->upper_bound(KeyOfValue()(mval.get()));
i = this->m_data.m_vect.insert(i, mval);
return i;
}
#else
iterator insert_equal(value_type && mval)
iterator insert_equal(BOOST_INTERPROCESS_RV_REF(value_type) mval)
{
iterator i = this->upper_bound(KeyOfValue()(mval));
i = this->m_data.m_vect.insert(i, detail::move_impl(mval));
i = this->m_data.m_vect.insert(i, boost::interprocess::move(mval));
return i;
}
#endif
iterator insert_unique(const_iterator pos, const value_type& val)
{
@@ -296,27 +268,15 @@ class flat_tree
return ret.first;
}
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
iterator insert_unique(const_iterator pos, detail::moved_object<value_type> mval)
{
insert_commit_data data;
std::pair<iterator,bool> ret = priv_insert_unique_prepare(pos, mval.get(), data);
if(ret.second){
ret.first = priv_insert_commit(data, mval);
}
return ret.first;
}
#else
iterator insert_unique(const_iterator pos, value_type&&mval)
iterator insert_unique(const_iterator pos, BOOST_INTERPROCESS_RV_REF(value_type) mval)
{
insert_commit_data data;
std::pair<iterator,bool> ret = priv_insert_unique_prepare(pos, mval, data);
if(ret.second){
ret.first = priv_insert_commit(data, detail::move_impl(mval));
ret.first = priv_insert_commit(data, boost::interprocess::move(mval));
}
return ret.first;
}
#endif
iterator insert_equal(const_iterator pos, const value_type& val)
{
@@ -325,21 +285,12 @@ class flat_tree
return priv_insert_commit(data, val);
}
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
iterator insert_equal(const_iterator pos, detail::moved_object<value_type> mval)
{
insert_commit_data data;
priv_insert_equal_prepare(pos, mval.get(), data);
return priv_insert_commit(data, mval);
}
#else
iterator insert_equal(const_iterator pos, value_type && mval)
iterator insert_equal(const_iterator pos, BOOST_INTERPROCESS_RV_REF(value_type) mval)
{
insert_commit_data data;
priv_insert_equal_prepare(pos, mval, data);
return priv_insert_commit(data, detail::move_impl(mval));
return priv_insert_commit(data, boost::interprocess::move(mval));
}
#endif
template <class InIt>
void insert_unique(InIt first, InIt last)
@@ -356,17 +307,17 @@ class flat_tree
priv_insert_equal(first, last, ItCat());
}
#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
template <class... Args>
iterator emplace_unique(Args&&... args)
{
value_type val(detail::forward_impl<Args>(args)...);
value_type val(boost::interprocess::forward<Args>(args)...);
insert_commit_data data;
std::pair<iterator,bool> ret =
priv_insert_unique_prepare(val, data);
if(ret.second){
ret.first = priv_insert_commit(data, detail::move_impl<value_type>(val));
ret.first = priv_insert_commit(data, boost::interprocess::move<value_type>(val));
}
return ret.first;
}
@@ -374,11 +325,11 @@ class flat_tree
template <class... Args>
iterator emplace_hint_unique(const_iterator hint, Args&&... args)
{
value_type val(detail::forward_impl<Args>(args)...);
value_type val(boost::interprocess::forward<Args>(args)...);
insert_commit_data data;
std::pair<iterator,bool> ret = priv_insert_unique_prepare(hint, val, data);
if(ret.second){
ret.first = priv_insert_commit(data, detail::move_impl<value_type>(val));
ret.first = priv_insert_commit(data, boost::interprocess::move<value_type>(val));
}
return ret.first;
}
@@ -386,115 +337,115 @@ class flat_tree
template <class... Args>
iterator emplace_equal(Args&&... args)
{
value_type val(detail::forward_impl<Args>(args)...);
value_type val(boost::interprocess::forward<Args>(args)...);
iterator i = this->upper_bound(KeyOfValue()(val));
i = this->m_data.m_vect.insert(i, detail::move_impl<value_type>(val));
i = this->m_data.m_vect.insert(i, boost::interprocess::move<value_type>(val));
return i;
}
template <class... Args>
iterator emplace_hint_equal(const_iterator hint, Args&&... args)
{
value_type val(detail::forward_impl<Args>(args)...);
value_type val(boost::interprocess::forward<Args>(args)...);
insert_commit_data data;
priv_insert_equal_prepare(hint, val, data);
return priv_insert_commit(data, detail::move_impl<value_type>(val));
return priv_insert_commit(data, boost::interprocess::move<value_type>(val));
}
#else //#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
#else //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
iterator emplace_unique()
{
detail::value_init<value_type> vval;
containers_detail::value_init<value_type> vval;
value_type &val = vval.m_t;
insert_commit_data data;
std::pair<iterator,bool> ret =
priv_insert_unique_prepare(val, data);
if(ret.second){
ret.first = priv_insert_commit(data, detail::move_impl<value_type>(val));
ret.first = priv_insert_commit(data, boost::interprocess::move<value_type>(val));
}
return ret.first;
}
iterator emplace_hint_unique(const_iterator hint)
{
detail::value_init<value_type> vval;
containers_detail::value_init<value_type> vval;
value_type &val = vval.m_t;
insert_commit_data data;
std::pair<iterator,bool> ret = priv_insert_unique_prepare(hint, val, data);
if(ret.second){
ret.first = priv_insert_commit(data, detail::move_impl<value_type>(val));
ret.first = priv_insert_commit(data, boost::interprocess::move<value_type>(val));
}
return ret.first;
}
iterator emplace_equal()
{
detail::value_init<value_type> vval;
containers_detail::value_init<value_type> vval;
value_type &val = vval.m_t;
iterator i = this->upper_bound(KeyOfValue()(val));
i = this->m_data.m_vect.insert(i, detail::move_impl<value_type>(val));
i = this->m_data.m_vect.insert(i, boost::interprocess::move<value_type>(val));
return i;
}
iterator emplace_hint_equal(const_iterator hint)
{
detail::value_init<value_type> vval;
containers_detail::value_init<value_type> vval;
value_type &val = vval.m_t;
insert_commit_data data;
priv_insert_equal_prepare(hint, val, data);
return priv_insert_commit(data, detail::move_impl<value_type>(val));
return priv_insert_commit(data, boost::interprocess::move<value_type>(val));
}
#define BOOST_PP_LOCAL_MACRO(n) \
template<BOOST_PP_ENUM_PARAMS(n, class P)> \
iterator emplace_unique(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_LIST, _)) \
iterator emplace_unique(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \
{ \
value_type val(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_FORWARD, _)); \
value_type val(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)); \
insert_commit_data data; \
std::pair<iterator,bool> ret = priv_insert_unique_prepare(val, data); \
if(ret.second){ \
ret.first = priv_insert_commit(data, detail::move_impl<value_type>(val)); \
ret.first = priv_insert_commit(data, boost::interprocess::move<value_type>(val)); \
} \
return ret.first; \
} \
\
template<BOOST_PP_ENUM_PARAMS(n, class P)> \
iterator emplace_hint_unique(const_iterator hint, \
BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_LIST, _)) \
BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \
{ \
value_type val(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_FORWARD, _)); \
value_type val(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)); \
insert_commit_data data; \
std::pair<iterator,bool> ret = priv_insert_unique_prepare(hint, val, data); \
if(ret.second){ \
ret.first = priv_insert_commit(data, detail::move_impl<value_type>(val)); \
ret.first = priv_insert_commit(data, boost::interprocess::move<value_type>(val)); \
} \
return ret.first; \
} \
\
template<BOOST_PP_ENUM_PARAMS(n, class P)> \
iterator emplace_equal(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_LIST, _)) \
iterator emplace_equal(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \
{ \
value_type val(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_FORWARD, _)); \
value_type val(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)); \
iterator i = this->upper_bound(KeyOfValue()(val)); \
i = this->m_data.m_vect.insert(i, detail::move_impl<value_type>(val)); \
i = this->m_data.m_vect.insert(i, boost::interprocess::move<value_type>(val)); \
return i; \
} \
\
template<BOOST_PP_ENUM_PARAMS(n, class P)> \
iterator emplace_hint_equal(const_iterator hint, \
BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_LIST, _)) \
BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \
{ \
value_type val(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_FORWARD, _)); \
value_type val(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)); \
insert_commit_data data; \
priv_insert_equal_prepare(hint, val, data); \
return priv_insert_commit(data, detail::move_impl<value_type>(val)); \
return priv_insert_commit(data, boost::interprocess::move<value_type>(val)); \
} \
//!
#define BOOST_PP_LOCAL_LIMITS (1, BOOST_INTERPROCESS_MAX_CONSTRUCTOR_PARAMETERS)
#define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINERS_MAX_CONSTRUCTOR_PARAMETERS)
#include BOOST_PP_LOCAL_ITERATE()
#endif //#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
#endif //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
iterator erase(const_iterator position)
{ return this->m_data.m_vect.erase(position); }
@@ -682,17 +633,14 @@ class flat_tree
}
}
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
template<class Convertible>
iterator priv_insert_commit
(insert_commit_data &commit_data, const Convertible &convertible)
{ return this->m_data.m_vect.insert(commit_data.position, convertible); }
#else
template<class Convertible>
iterator priv_insert_commit
(insert_commit_data &commit_data, Convertible &&convertible)
{ return this->m_data.m_vect.insert(commit_data.position, detail::forward_impl<Convertible>(convertible)); }
#endif
(insert_commit_data &commit_data, BOOST_INTERPROCESS_FWD_REF(Convertible) convertible)
{
return this->m_data.m_vect.insert
( commit_data.position
, boost::interprocess::forward<Convertible>(convertible));
}
template <class RanIt>
RanIt priv_lower_bound(RanIt first, RanIt last,
@@ -865,23 +813,25 @@ swap(flat_tree<Key,Value,KeyOfValue,Compare,Alloc>& x,
flat_tree<Key,Value,KeyOfValue,Compare,Alloc>& y)
{ x.swap(y); }
} //namespace detail {
} //namespace containers_detail {
} //namespace interprocess_container {
namespace interprocess {
//!has_trivial_destructor_after_move<> == true_type
//!specialization for optimizations
template <class K, class V, class KOV,
class C, class A>
struct has_trivial_destructor_after_move<detail::flat_tree<K, V, KOV, C, A> >
class C, class A>
struct has_trivial_destructor_after_move<boost::interprocess_container::containers_detail::flat_tree<K, V, KOV, C, A> >
{
enum { value =
has_trivial_destructor<A>::value &&
has_trivial_destructor<C>::value };
static const bool value = has_trivial_destructor<A>::value && has_trivial_destructor<C>::value;
};
} //namespace interprocess {
} //namespace boost {
#include <boost/interprocess/detail/config_end.hpp>
#include <boost/interprocess/containers/container/detail/config_end.hpp>
#endif // BOOST_INTERPROCESS_FLAT_TREE_HPP
#endif // BOOST_CONTAINERS_FLAT_TREE_HPP

View File

@@ -7,27 +7,31 @@
// (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.
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTERPROCESS_DETAIL_ITERATORS_HPP
#define BOOST_INTERPROCESS_DETAIL_ITERATORS_HPP
#ifndef BOOST_CONTAINERS_DETAIL_ITERATORS_HPP
#define BOOST_CONTAINERS_DETAIL_ITERATORS_HPP
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/interprocess/containers/container/detail/config_begin.hpp>
#include <boost/interprocess/containers/container/detail/workaround.hpp>
#include <boost/interprocess/detail/move.hpp>
#include <boost/interprocess/interprocess_fwd.hpp>
#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
#include <boost/interprocess/containers/container/detail/variadic_templates_tools.hpp>
#else
#include <boost/interprocess/containers/container/detail/preprocessor.hpp>
#endif
#include <iterator>
#include <boost/interprocess/detail/type_traits.hpp>
namespace boost {
namespace interprocess {
namespace interprocess_container {
template <class T, class Difference = std::ptrdiff_t>
class constant_iterator
@@ -324,152 +328,165 @@ class repeat_iterator
{ return m_num - other.m_num; }
};
template <class PseudoReference>
struct operator_arrow_proxy
template <class T, class E>
class emplace_iterator
: public std::iterator
<std::random_access_iterator_tag, T, std::ptrdiff_t, const T*, const T &>
{
operator_arrow_proxy(const PseudoReference &px)
: m_value(px)
{}
typedef emplace_iterator this_type;
PseudoReference* operator->() const { return &m_value; }
// This function is needed for MWCW and BCC, which won't call operator->
// again automatically per 13.3.1.2 para 8
// operator T*() const { return &m_value; }
mutable PseudoReference m_value;
};
template <class T>
struct operator_arrow_proxy<T&>
{
operator_arrow_proxy(T &px)
: m_value(px)
{}
T* operator->() const { return &m_value; }
// This function is needed for MWCW and BCC, which won't call operator->
// again automatically per 13.3.1.2 para 8
// operator T*() const { return &m_value; }
mutable T &m_value;
};
template <class Iterator, class UnaryFunction>
class transform_iterator
: public UnaryFunction
, public std::iterator
< typename Iterator::iterator_category
, typename detail::remove_reference<typename UnaryFunction::result_type>::type
, typename Iterator::difference_type
, operator_arrow_proxy<typename UnaryFunction::result_type>
, typename UnaryFunction::result_type>
{
public:
explicit transform_iterator(const Iterator &it, const UnaryFunction &f = UnaryFunction())
: UnaryFunction(f), m_it(it)
{}
explicit emplace_iterator(E&e)
: m_num(1), m_pe(&e){}
explicit transform_iterator()
: UnaryFunction(), m_it()
{}
emplace_iterator()
: m_num(0), m_pe(0){}
//Constructors
transform_iterator& operator++()
this_type& operator++()
{ increment(); return *this; }
transform_iterator operator++(int)
this_type operator++(int)
{
transform_iterator result (*this);
this_type result (*this);
increment();
return result;
}
friend bool operator== (const transform_iterator& i, const transform_iterator& i2)
friend bool operator== (const this_type& i, const this_type& i2)
{ return i.equal(i2); }
friend bool operator!= (const transform_iterator& i, const transform_iterator& i2)
friend bool operator!= (const this_type& i, const this_type& i2)
{ return !(i == i2); }
/*
friend bool operator> (const transform_iterator& i, const transform_iterator& i2)
friend bool operator< (const this_type& i, const this_type& i2)
{ return i.less(i2); }
friend bool operator> (const this_type& i, const this_type& i2)
{ return i2 < i; }
friend bool operator<= (const transform_iterator& i, const transform_iterator& i2)
friend bool operator<= (const this_type& i, const this_type& i2)
{ return !(i > i2); }
friend bool operator>= (const transform_iterator& i, const transform_iterator& i2)
friend bool operator>= (const this_type& i, const this_type& i2)
{ return !(i < i2); }
*/
friend typename Iterator::difference_type operator- (const transform_iterator& i, const transform_iterator& i2)
friend std::ptrdiff_t operator- (const this_type& i, const this_type& i2)
{ return i2.distance_to(i); }
//Arithmetic
transform_iterator& operator+=(typename Iterator::difference_type off)
this_type& operator+=(std::ptrdiff_t off)
{ this->advance(off); return *this; }
transform_iterator operator+(typename Iterator::difference_type off) const
this_type operator+(std::ptrdiff_t off) const
{
transform_iterator other(*this);
this_type other(*this);
other.advance(off);
return other;
}
friend transform_iterator operator+(typename Iterator::difference_type off, const transform_iterator& right)
friend this_type operator+(std::ptrdiff_t off, const this_type& right)
{ return right + off; }
transform_iterator& operator-=(typename Iterator::difference_type off)
this_type& operator-=(std::ptrdiff_t off)
{ this->advance(-off); return *this; }
transform_iterator operator-(typename Iterator::difference_type off) const
this_type operator-(std::ptrdiff_t off) const
{ return *this + (-off); }
typename UnaryFunction::result_type operator*() const
const T& operator*() const
{ return dereference(); }
operator_arrow_proxy<typename UnaryFunction::result_type>
operator->() const
{ return operator_arrow_proxy<typename UnaryFunction::result_type>(dereference()); }
const T* operator->() const
{ return &(dereference()); }
Iterator & base()
{ return m_it; }
const Iterator & base() const
{ return m_it; }
void construct_in_place(T* ptr)
{ (*m_pe)(ptr); }
private:
Iterator m_it;
std::ptrdiff_t m_num;
E * m_pe;
void increment()
{ ++m_it; }
{ --m_num; }
void decrement()
{ --m_it; }
{ ++m_num; }
bool equal(const transform_iterator &other) const
{ return m_it == other.m_it; }
bool equal(const this_type &other) const
{ return m_num == other.m_num; }
bool less(const transform_iterator &other) const
{ return other.m_it < m_it; }
bool less(const this_type &other) const
{ return other.m_num < m_num; }
typename UnaryFunction::result_type dereference() const
{ return UnaryFunction::operator()(*m_it); }
const T & dereference() const
{
static T dummy;
return dummy;
}
void advance(typename Iterator::difference_type n)
{ std::advance(m_it, n); }
void advance(std::ptrdiff_t n)
{ m_num -= n; }
typename Iterator::difference_type distance_to(const transform_iterator &other)const
{ return std::distance(other.m_it, m_it); }
std::ptrdiff_t distance_to(const this_type &other)const
{ return m_num - other.m_num; }
};
template <class Iterator, class UnaryFunc>
transform_iterator<Iterator, UnaryFunc>
make_transform_iterator(Iterator it, UnaryFunc fun)
{
return transform_iterator<Iterator, UnaryFunc>(it, fun);
}
#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
} //namespace interprocess {
template<class T, class ...Args>
struct emplace_functor
{
typedef typename containers_detail::build_number_seq<sizeof...(Args)>::type index_tuple_t;
emplace_functor(Args&&... args)
: args_(args...)
{}
void operator()(T *ptr)
{ emplace_functor::inplace_impl(ptr, index_tuple_t()); }
template<int ...IdxPack>
void inplace_impl(T* ptr, const containers_detail::index_tuple<IdxPack...>&)
{ ::new(ptr) T(boost::interprocess::forward<Args>(containers_detail::get<IdxPack>(args_))...); }
containers_detail::tuple<Args&&...> args_;
};
#else
template<class T>
struct emplace_functor
{
emplace_functor()
{}
void operator()(T *ptr)
{ new(ptr) T(); }
};
#define BOOST_PP_LOCAL_MACRO(n) \
template <class T, BOOST_PP_ENUM_PARAMS(n, class P) > \
struct BOOST_PP_CAT(BOOST_PP_CAT(emplace_functor, n), arg) \
{ \
BOOST_PP_CAT(BOOST_PP_CAT(emplace_functor, n), arg) \
( BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _) ) \
: BOOST_PP_ENUM(n, BOOST_CONTAINERS_AUX_PARAM_INIT, _) {} \
\
void operator()(T *ptr) \
{ \
new(ptr)T (BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_MEMBER_FORWARD, _)); \
} \
BOOST_PP_REPEAT(n, BOOST_CONTAINERS_AUX_PARAM_DEFINE, _) \
}; \
//!
#define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINERS_MAX_CONSTRUCTOR_PARAMETERS)
#include BOOST_PP_LOCAL_ITERATE()
#endif
} //namespace interprocess_container {
} //namespace boost {
#include <boost/interprocess/detail/config_end.hpp>
#include <boost/interprocess/containers/container/detail/config_end.hpp>
#endif //#ifndef BOOST_INTERPROCESS_DETAIL_ITERATORS_HPP
#endif //#ifndef BOOST_CONTAINERS_DETAIL_ITERATORS_HPP

View File

@@ -0,0 +1,152 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005-2008.
//
// 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/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINERS_CONTAINER_DETAIL_MPL_HPP
#define BOOST_CONTAINERS_CONTAINER_DETAIL_MPL_HPP
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif
#include <cstddef>
namespace boost {
namespace interprocess_container {
namespace containers_detail {
template <class T, T val>
struct integral_constant
{
static const T value = val;
typedef integral_constant<T,val> type;
};
template< bool C_ >
struct bool_ : integral_constant<bool, C_>
{
static const bool value = C_;
};
typedef bool_<true> true_;
typedef bool_<false> false_;
typedef true_ true_type;
typedef false_ false_type;
typedef char yes_type;
struct no_type
{
char padding[8];
};
template <bool B, class T = void>
struct enable_if_c {
typedef T type;
};
template <class T>
struct enable_if_c<false, T> {};
template <class Cond, class T = void>
struct enable_if : public enable_if_c<Cond::value, T> {};
template <class Cond, class T = void>
struct disable_if : public enable_if_c<!Cond::value, T> {};
template <class T, class U>
class is_convertible
{
typedef char true_t;
class false_t { char dummy[2]; };
static true_t dispatch(U);
static false_t dispatch(...);
static T trigger();
public:
enum { value = sizeof(dispatch(trigger())) == sizeof(true_t) };
};
template<
bool C
, typename T1
, typename T2
>
struct if_c
{
typedef T1 type;
};
template<
typename T1
, typename T2
>
struct if_c<false,T1,T2>
{
typedef T2 type;
};
template<
typename T1
, typename T2
, typename T3
>
struct if_
{
typedef typename if_c<0 != T1::value, T2, T3>::type type;
};
template <class Pair>
struct select1st
// : public std::unary_function<Pair, typename Pair::first_type>
{
template<class OtherPair>
const typename Pair::first_type& operator()(const OtherPair& x) const
{ return x.first; }
const typename Pair::first_type& operator()(const typename Pair::first_type& x) const
{ return x; }
};
// identity is an extension: it is not part of the standard.
template <class T>
struct identity
// : public std::unary_function<T,T>
{
typedef T type;
const T& operator()(const T& x) const
{ return x; }
};
template<std::size_t S>
struct ls_zeros
{
static const std::size_t value = (S & std::size_t(1)) ? 0 : (1u + ls_zeros<(S >> 1u)>::value);
};
template<>
struct ls_zeros<0>
{
static const std::size_t value = 0;
};
template<>
struct ls_zeros<1>
{
static const std::size_t value = 0;
};
} //namespace containers_detail {
} //namespace interprocess_container {
} //namespace boost {
#endif //#ifndef BOOST_CONTAINERS_CONTAINER_DETAIL_MPL_HPP

View File

@@ -0,0 +1,554 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005-2008. 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/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINERS_DETAIL_MULTIALLOCATION_CHAIN_HPP
#define BOOST_CONTAINERS_DETAIL_MULTIALLOCATION_CHAIN_HPP
#include <boost/interprocess/containers/container/detail/config_begin.hpp>
#include <boost/interprocess/containers/container/detail/utilities.hpp>
#include <boost/interprocess/containers/container/detail/type_traits.hpp>
#include <boost/interprocess/containers/container/detail/transform_iterator.hpp>
namespace boost {
namespace interprocess_container {
namespace containers_detail {
template<class VoidPointer>
class basic_multiallocation_slist
{
public:
typedef VoidPointer void_pointer;
private:
static VoidPointer &priv_get_ref(const VoidPointer &p)
{ return *static_cast<void_pointer*>(containers_detail::get_pointer(p)); }
basic_multiallocation_slist(basic_multiallocation_slist &);
basic_multiallocation_slist &operator=(basic_multiallocation_slist &);
public:
BOOST_INTERPROCESS_ENABLE_MOVE_EMULATION(basic_multiallocation_slist)
//!This iterator is returned by "allocate_many" functions so that
//!the user can access the multiple buffers allocated in a single call
class iterator
: public std::iterator<std::input_iterator_tag, char>
{
friend class basic_multiallocation_slist<void_pointer>;
void unspecified_bool_type_func() const {}
typedef void (iterator::*unspecified_bool_type)() const;
iterator(void_pointer node_range)
: next_node_(node_range)
{}
public:
typedef char value_type;
typedef value_type & reference;
typedef value_type * pointer;
iterator()
: next_node_(0)
{}
iterator &operator=(const iterator &other)
{ next_node_ = other.next_node_; return *this; }
public:
iterator& operator++()
{
next_node_ = *static_cast<void_pointer*>(containers_detail::get_pointer(next_node_));
return *this;
}
iterator operator++(int)
{
iterator result(*this);
++*this;
return result;
}
bool operator== (const iterator& other) const
{ return next_node_ == other.next_node_; }
bool operator!= (const iterator& other) const
{ return !operator== (other); }
reference operator*() const
{ return *static_cast<char*>(containers_detail::get_pointer(next_node_)); }
operator unspecified_bool_type() const
{ return next_node_? &iterator::unspecified_bool_type_func : 0; }
pointer operator->() const
{ return &(*(*this)); }
private:
void_pointer next_node_;
};
private:
iterator it_;
public:
basic_multiallocation_slist()
: it_(iterator())
{}
basic_multiallocation_slist(void_pointer p)
: it_(p ? iterator_to(p) : iterator())
{}
basic_multiallocation_slist(BOOST_INTERPROCESS_RV_REF(basic_multiallocation_slist) other)
: it_(iterator())
{ this->swap(other); }
basic_multiallocation_slist& operator=(BOOST_INTERPROCESS_RV_REF(basic_multiallocation_slist) other)
{
basic_multiallocation_slist tmp(boost::interprocess::move(other));
this->swap(tmp);
return *this;
}
bool empty() const
{ return !it_; }
iterator before_begin() const
{ return iterator(void_pointer(const_cast<void*>(static_cast<const void*>(&it_.next_node_)))); }
iterator begin() const
{ return it_; }
iterator end() const
{ return iterator(); }
void clear()
{ this->it_.next_node_ = void_pointer(0); }
iterator insert_after(iterator it, void_pointer m)
{
priv_get_ref(m) = priv_get_ref(it.next_node_);
priv_get_ref(it.next_node_) = m;
return iterator(m);
}
void push_front(void_pointer m)
{
priv_get_ref(m) = this->it_.next_node_;
this->it_.next_node_ = m;
}
void pop_front()
{ ++it_; }
void *front() const
{ return containers_detail::get_pointer(it_.next_node_); }
void splice_after(iterator after_this, iterator before_begin, iterator before_end)
{
if (after_this != before_begin && after_this != before_end && before_begin != before_end) {
void_pointer next_b = priv_get_ref(before_begin.next_node_);
void_pointer next_e = priv_get_ref(before_end.next_node_);
void_pointer next_p = priv_get_ref(after_this.next_node_);
priv_get_ref(before_begin.next_node_) = next_e;
priv_get_ref(before_end.next_node_) = next_p;
priv_get_ref(after_this.next_node_) = next_b;
}
}
void swap(basic_multiallocation_slist &other_chain)
{
std::swap(this->it_, other_chain.it_);
}
static iterator iterator_to(void_pointer p)
{ return iterator(p); }
void_pointer extract_data()
{
void_pointer ret = empty() ? void_pointer(0) : void_pointer(&*it_);
it_ = iterator();
return ret;
}
};
template<class VoidPointer>
class basic_multiallocation_cached_slist
{
private:
basic_multiallocation_slist<VoidPointer> slist_;
typename basic_multiallocation_slist<VoidPointer>::iterator last_;
basic_multiallocation_cached_slist(basic_multiallocation_cached_slist &);
basic_multiallocation_cached_slist &operator=(basic_multiallocation_cached_slist &);
public:
BOOST_INTERPROCESS_ENABLE_MOVE_EMULATION(basic_multiallocation_cached_slist)
typedef typename basic_multiallocation_slist<VoidPointer>::void_pointer void_pointer;
typedef typename basic_multiallocation_slist<VoidPointer>::iterator iterator;
basic_multiallocation_cached_slist()
: slist_(), last_(slist_.before_begin())
{}
/*
basic_multiallocation_cached_slist(iterator first_node)
: slist_(first_node), last_(slist_.before_begin())
{
iterator end;
while(first_node != end){
++last_;
}
}*/
basic_multiallocation_cached_slist(void_pointer p1, void_pointer p2)
: slist_(p1), last_(p2 ? iterator_to(p2) : slist_.before_begin())
{}
basic_multiallocation_cached_slist(BOOST_INTERPROCESS_RV_REF(basic_multiallocation_cached_slist) other)
: slist_(), last_(slist_.before_begin())
{ this->swap(other); }
basic_multiallocation_cached_slist& operator=(BOOST_INTERPROCESS_RV_REF(basic_multiallocation_cached_slist) other)
{
basic_multiallocation_cached_slist tmp(boost::interprocess::move(other));
this->swap(tmp);
return *this;
}
bool empty() const
{ return slist_.empty(); }
iterator before_begin() const
{ return slist_.before_begin(); }
iterator begin() const
{ return slist_.begin(); }
iterator end() const
{ return slist_.end(); }
iterator last() const
{ return last_; }
void clear()
{
slist_.clear();
last_ = slist_.before_begin();
}
iterator insert_after(iterator it, void_pointer m)
{
slist_.insert_after(it, m);
if(it == last_){
last_ = slist_.iterator_to(m);
}
return iterator_to(m);
}
void push_front(void_pointer m)
{ this->insert_after(this->before_begin(), m); }
void push_back(void_pointer m)
{ this->insert_after(last_, m); }
void pop_front()
{
if(last_ == slist_.begin()){
last_ = slist_.before_begin();
}
slist_.pop_front();
}
void *front() const
{ return slist_.front(); }
void splice_after(iterator after_this, iterator before_begin, iterator before_end)
{
if(before_begin == before_end)
return;
if(after_this == last_){
last_ = before_end;
}
slist_.splice_after(after_this, before_begin, before_end);
}
void swap(basic_multiallocation_cached_slist &x)
{
slist_.swap(x.slist_);
using std::swap;
swap(last_, x.last_);
if(last_ == x.before_begin()){
last_ = this->before_begin();
}
if(x.last_ == this->before_begin()){
x.last_ = x.before_begin();
}
}
static iterator iterator_to(void_pointer p)
{ return basic_multiallocation_slist<VoidPointer>::iterator_to(p); }
std::pair<void_pointer, void_pointer> extract_data()
{
if(this->empty()){
return std::pair<void_pointer, void_pointer>(void_pointer(0), void_pointer(0));
}
else{
void_pointer p1 = slist_.extract_data();
void_pointer p2 = void_pointer(&*last_);
last_ = iterator();
return std::pair<void_pointer, void_pointer>(p1, p2);
}
}
};
template<class MultiallocatorCachedSlist>
class basic_multiallocation_cached_counted_slist
{
private:
MultiallocatorCachedSlist cached_slist_;
std::size_t size_;
basic_multiallocation_cached_counted_slist(basic_multiallocation_cached_counted_slist &);
basic_multiallocation_cached_counted_slist &operator=(basic_multiallocation_cached_counted_slist &);
public:
BOOST_INTERPROCESS_ENABLE_MOVE_EMULATION(basic_multiallocation_cached_counted_slist)
typedef typename MultiallocatorCachedSlist::void_pointer void_pointer;
typedef typename MultiallocatorCachedSlist::iterator iterator;
basic_multiallocation_cached_counted_slist()
: cached_slist_(), size_(0)
{}
basic_multiallocation_cached_counted_slist(void_pointer p1, void_pointer p2, std::size_t n)
: cached_slist_(p1, p2), size_(n)
{}
basic_multiallocation_cached_counted_slist(BOOST_INTERPROCESS_RV_REF(basic_multiallocation_cached_counted_slist) other)
: cached_slist_(), size_(0)
{ this->swap(other); }
basic_multiallocation_cached_counted_slist& operator=(BOOST_INTERPROCESS_RV_REF(basic_multiallocation_cached_counted_slist) other)
{
basic_multiallocation_cached_counted_slist tmp(boost::interprocess::move(other));
this->swap(tmp);
return *this;
}
basic_multiallocation_cached_counted_slist (MultiallocatorCachedSlist mem, std::size_t n)
: cached_slist_(boost::interprocess::move(mem)), size_(n)
{}
bool empty() const
{ return cached_slist_.empty(); }
std::size_t size() const
{ return size_; }
iterator before_begin() const
{ return cached_slist_.before_begin(); }
iterator begin() const
{ return cached_slist_.begin(); }
iterator end() const
{ return cached_slist_.end(); }
iterator last() const
{ return cached_slist_.last(); }
void clear()
{
cached_slist_.clear();
size_ = 0;
}
iterator insert_after(iterator it, void_pointer m)
{
iterator ret = cached_slist_.insert_after(it, m);
++size_;
return ret;
}
void push_front(void_pointer m)
{ this->insert_after(this->before_begin(), m); }
void push_back(void_pointer m)
{ this->insert_after(this->before_begin(), m); }
void pop_front()
{
cached_slist_.pop_front();
--size_;
}
void *front() const
{ return cached_slist_.front(); }
void splice_after(iterator after_this, basic_multiallocation_cached_counted_slist &x, iterator before_begin, iterator before_end)
{
std::size_t n = static_cast<std::size_t>(std::distance(before_begin, before_end));
this->splice_after(after_this, x, before_begin, before_end, n);
}
void splice_after(iterator after_this, basic_multiallocation_cached_counted_slist &x, iterator before_begin, iterator before_end, std::size_t n)
{
cached_slist_.splice_after(after_this, before_begin, before_end);
size_ += n;
x.size_ -= n;
}
void splice_after(iterator after_this, basic_multiallocation_cached_counted_slist &x)
{
cached_slist_.splice_after(after_this, x.before_begin(), x.last());
size_ += x.size_;
x.size_ = 0;
}
void swap(basic_multiallocation_cached_counted_slist &x)
{
cached_slist_.swap(x.cached_slist_);
using std::swap;
swap(size_, x.size_);
}
static iterator iterator_to(void_pointer p)
{ return MultiallocatorCachedSlist::iterator_to(p); }
std::pair<void_pointer, void_pointer> extract_data()
{
size_ = 0;
return cached_slist_.extract_data();
}
};
template<class T>
struct cast_functor
{
typedef typename containers_detail::add_reference<T>::type result_type;
result_type operator()(char &ptr) const
{ return *static_cast<T*>(static_cast<void*>(&ptr)); }
};
template<class MultiallocationChain, class T>
class transform_multiallocation_chain
{
private:
MultiallocationChain holder_;
typedef typename MultiallocationChain::void_pointer void_pointer;
typedef typename boost::pointer_to_other
<void_pointer, T>::type pointer;
transform_multiallocation_chain(transform_multiallocation_chain &);
transform_multiallocation_chain &operator=(transform_multiallocation_chain &);
static pointer cast(void_pointer p)
{
return pointer(static_cast<T*>(containers_detail::get_pointer(p)));
}
public:
BOOST_INTERPROCESS_ENABLE_MOVE_EMULATION(transform_multiallocation_chain)
typedef transform_iterator
< typename MultiallocationChain::iterator
, containers_detail::cast_functor <T> > iterator;
transform_multiallocation_chain(void_pointer p1, void_pointer p2, std::size_t n)
: holder_(p1, p2, n)
{}
transform_multiallocation_chain()
: holder_()
{}
transform_multiallocation_chain(BOOST_INTERPROCESS_RV_REF(transform_multiallocation_chain) other)
: holder_()
{ this->swap(other); }
transform_multiallocation_chain(BOOST_INTERPROCESS_RV_REF(MultiallocationChain) other)
: holder_(boost::interprocess::move(other))
{}
transform_multiallocation_chain& operator=(BOOST_INTERPROCESS_RV_REF(transform_multiallocation_chain) other)
{
transform_multiallocation_chain tmp(boost::interprocess::move(other));
this->swap(tmp);
return *this;
}
void push_front(pointer mem)
{ holder_.push_front(mem); }
void swap(transform_multiallocation_chain &other_chain)
{ holder_.swap(other_chain.holder_); }
/*
void splice_after(iterator after_this, iterator before_begin, iterator before_end)
{ holder_.splice_after(after_this.base(), before_begin.base(), before_end.base()); }
*/
void splice_after(iterator after_this, transform_multiallocation_chain &x, iterator before_begin, iterator before_end, std::size_t n)
{ holder_.splice_after(after_this.base(), x.holder_, before_begin.base(), before_end.base(), n); }
void pop_front()
{ holder_.pop_front(); }
pointer front() const
{ return cast(holder_.front()); }
bool empty() const
{ return holder_.empty(); }
iterator before_begin() const
{ return iterator(holder_.before_begin()); }
iterator begin() const
{ return iterator(holder_.begin()); }
iterator end() const
{ return iterator(holder_.end()); }
iterator last() const
{ return iterator(holder_.last()); }
std::size_t size() const
{ return holder_.size(); }
void clear()
{ holder_.clear(); }
iterator insert_after(iterator it, pointer m)
{ return iterator(holder_.insert_after(it.base(), m)); }
static iterator iterator_to(pointer p)
{ return iterator(MultiallocationChain::iterator_to(p)); }
std::pair<void_pointer, void_pointer> extract_data()
{ return holder_.extract_data(); }
MultiallocationChain extract_multiallocation_chain()
{
return MultiallocationChain(boost::interprocess::move(holder_));
}
};
}}}
// namespace containers_detail {
// namespace interprocess_container {
// namespace boost {
#include <boost/interprocess/containers/container/detail/config_end.hpp>
#endif //BOOST_CONTAINERS_DETAIL_MULTIALLOCATION_CHAIN_HPP

View File

@@ -4,36 +4,137 @@
// 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.
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTERPROCESS_DETAIL_NODE_ALLOC_HPP_
#define BOOST_INTERPROCESS_DETAIL_NODE_ALLOC_HPP_
#ifndef BOOST_CONTAINERS_DETAIL_NODE_ALLOC_HPP_
#define BOOST_CONTAINERS_DETAIL_NODE_ALLOC_HPP_
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/interprocess/interprocess_fwd.hpp>
#include <boost/interprocess/detail/version_type.hpp>
#include <boost/interprocess/detail/move.hpp>
#include <boost/interprocess/detail/algorithms.hpp>
#include <boost/interprocess/detail/type_traits.hpp>
#include <boost/interprocess/detail/utilities.hpp>
#include <boost/interprocess/detail/mpl.hpp>
#include <boost/intrusive/options.hpp>
#include <boost/interprocess/containers/container/detail/config_begin.hpp>
#include <boost/interprocess/containers/container/detail/workaround.hpp>
#include <utility>
#include <functional>
#include <boost/interprocess/detail/move.hpp>
#include <boost/intrusive/options.hpp>
#include <boost/interprocess/containers/container/detail/version_type.hpp>
#include <boost/interprocess/containers/container/detail/type_traits.hpp>
#include <boost/interprocess/containers/container/detail/utilities.hpp>
#include <boost/interprocess/containers/container/detail/mpl.hpp>
#include <boost/interprocess/containers/container/detail/destroyers.hpp>
#ifndef BOOST_CONTAINERS_PERFECT_FORWARDING
#include <boost/interprocess/containers/container/detail/preprocessor.hpp>
#endif
#include <boost/interprocess/containers/container/detail/algorithms.hpp>
namespace boost {
namespace interprocess {
namespace detail {
namespace interprocess_container {
namespace containers_detail {
//!A deleter for scoped_ptr that deallocates the memory
//!allocated for an object using a STL allocator.
template <class Allocator>
struct scoped_deallocator
{
typedef typename Allocator::pointer pointer;
typedef containers_detail::integral_constant<unsigned,
boost::interprocess_container::containers_detail::
version<Allocator>::value> alloc_version;
typedef containers_detail::integral_constant<unsigned, 1> allocator_v1;
typedef containers_detail::integral_constant<unsigned, 2> allocator_v2;
private:
void priv_deallocate(allocator_v1)
{ m_alloc.deallocate(m_ptr, 1); }
void priv_deallocate(allocator_v2)
{ m_alloc.deallocate_one(m_ptr); }
scoped_deallocator(scoped_deallocator &);
scoped_deallocator& operator=(scoped_deallocator &);
public:
BOOST_INTERPROCESS_ENABLE_MOVE_EMULATION(scoped_deallocator)
pointer m_ptr;
Allocator& m_alloc;
scoped_deallocator(pointer p, Allocator& a)
: m_ptr(p), m_alloc(a)
{}
~scoped_deallocator()
{ if (m_ptr)priv_deallocate(alloc_version()); }
scoped_deallocator(BOOST_INTERPROCESS_RV_REF(scoped_deallocator) o)
: m_ptr(o.m_ptr), m_alloc(o.m_alloc)
{ o.release(); }
pointer get() const
{ return m_ptr; }
void release()
{ m_ptr = 0; }
};
template <class A>
class allocator_destroyer_and_chain_builder
{
typedef typename A::value_type value_type;
typedef typename A::multiallocation_chain multiallocation_chain;
A & a_;
multiallocation_chain &c_;
public:
allocator_destroyer_and_chain_builder(A &a, multiallocation_chain &c)
: a_(a), c_(c)
{}
void operator()(const typename A::pointer &p)
{
value_type *vp = containers_detail::get_pointer(p);
vp->~value_type();
c_.push_front(vp);
}
};
template <class A>
class allocator_multialloc_chain_node_deallocator
{
typedef typename A::value_type value_type;
typedef typename A::multiallocation_chain multiallocation_chain;
typedef allocator_destroyer_and_chain_builder<A> chain_builder;
A & a_;
multiallocation_chain c_;
public:
allocator_multialloc_chain_node_deallocator(A &a)
: a_(a), c_()
{}
chain_builder get_chain_builder()
{ return chain_builder(a_, c_); }
~allocator_multialloc_chain_node_deallocator()
{
if(!c_.empty())
a_.deallocate_individual(boost::interprocess::move(c_));
}
};
template<class ValueCompare, class Node>
struct node_compare
@@ -66,18 +167,25 @@ struct node_alloc_holder
typedef typename A::template rebind<Node>::other NodeAlloc;
typedef A ValAlloc;
typedef typename NodeAlloc::pointer NodePtr;
typedef detail::scoped_deallocator<NodeAlloc> Deallocator;
typedef containers_detail::scoped_deallocator<NodeAlloc> Deallocator;
typedef typename NodeAlloc::size_type size_type;
typedef typename NodeAlloc::difference_type difference_type;
typedef detail::integral_constant<unsigned, 1> allocator_v1;
typedef detail::integral_constant<unsigned, 2> allocator_v2;
typedef detail::integral_constant<unsigned,
boost::interprocess::detail::
typedef containers_detail::integral_constant<unsigned, 1> allocator_v1;
typedef containers_detail::integral_constant<unsigned, 2> allocator_v2;
typedef containers_detail::integral_constant<unsigned,
boost::interprocess_container::containers_detail::
version<NodeAlloc>::value> alloc_version;
typedef typename ICont::iterator icont_iterator;
typedef typename ICont::const_iterator icont_citerator;
typedef allocator_destroyer<NodeAlloc> Destroyer;
private:
node_alloc_holder(node_alloc_holder&);
node_alloc_holder & operator=(node_alloc_holder&);
public:
BOOST_INTERPROCESS_ENABLE_MOVE_EMULATION(node_alloc_holder)
node_alloc_holder(const ValAlloc &a)
: members_(a)
{}
@@ -86,32 +194,19 @@ struct node_alloc_holder
: members_(other.node_alloc())
{}
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
node_alloc_holder(detail::moved_object<node_alloc_holder> other)
: members_(detail::move_impl(other.get().node_alloc()))
{ this->swap(other.get()); }
#else
node_alloc_holder(node_alloc_holder &&other)
: members_(detail::move_impl(other.node_alloc()))
node_alloc_holder(BOOST_INTERPROCESS_RV_REF(node_alloc_holder) other)
: members_(boost::interprocess::move(other.node_alloc()))
{ this->swap(other); }
#endif
template<class Pred>
node_alloc_holder(const ValAlloc &a, const Pred &c)
: members_(a, typename ICont::value_compare(c))
{}
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
template<class Pred>
node_alloc_holder(detail::moved_object<ValAlloc> a, const Pred &c)
: members_(a.get(), typename ICont::value_compare(c))
{}
#else
template<class Pred>
node_alloc_holder(ValAlloc &&a, const Pred &c)
node_alloc_holder(BOOST_INTERPROCESS_RV_REF(ValAlloc) a, const Pred &c)
: members_(a, typename ICont::value_compare(c))
{}
#endif
template<class Pred>
node_alloc_holder(const node_alloc_holder &other, const Pred &c)
@@ -142,46 +237,27 @@ struct node_alloc_holder
void deallocate_one(NodePtr p, allocator_v2)
{ this->node_alloc().deallocate_one(p); }
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
template<class Convertible1, class Convertible2>
static void construct(const NodePtr &ptr, detail::moved_object<std::pair<Convertible1, Convertible2> > value)
{
typedef typename Node::hook_type hook_type;
typedef typename Node::value_type::first_type first_type;
typedef typename Node::value_type::second_type second_type;
Node *nodeptr = detail::get_pointer(ptr);
//Hook constructor does not throw
new(static_cast<hook_type*>(nodeptr))hook_type();
//Now construct pair members_holder
value_type *valueptr = &nodeptr->get_data();
new((void*)&valueptr->first) first_type(detail::move_impl(value.get().first));
BOOST_TRY{
new((void*)&valueptr->second) second_type(detail::move_impl(value.get().second));
}
BOOST_CATCH(...){
valueptr->first.~first_type();
static_cast<hook_type*>(nodeptr)->~hook_type();
BOOST_RETHROW
}
BOOST_CATCH_END
}
#else
template<class Convertible1, class Convertible2>
static void construct(const NodePtr &ptr, std::pair<Convertible1, Convertible2> &&value)
static void construct(const NodePtr &ptr,
#ifdef BOOST_HAS_RVALUE_REFS
std::pair<Convertible1, Convertible2> &&
#else
boost::interprocess::rv<std::pair<Convertible1, Convertible2> > &
#endif
value)
{
typedef typename Node::hook_type hook_type;
typedef typename Node::value_type::first_type first_type;
typedef typename Node::value_type::second_type second_type;
Node *nodeptr = detail::get_pointer(ptr);
Node *nodeptr = containers_detail::get_pointer(ptr);
//Hook constructor does not throw
new(static_cast<hook_type*>(nodeptr))hook_type();
//Now construct pair members_holder
value_type *valueptr = &nodeptr->get_data();
new((void*)&valueptr->first) first_type(detail::move_impl(value.first));
new((void*)&valueptr->first) first_type(boost::interprocess::move(value.first));
BOOST_TRY{
new((void*)&valueptr->second) second_type(detail::move_impl(value.second));
new((void*)&valueptr->second) second_type(boost::interprocess::move(value.second));
}
BOOST_CATCH(...){
valueptr->first.~first_type();
@@ -190,44 +266,35 @@ struct node_alloc_holder
}
BOOST_CATCH_END
}
#endif
static void destroy(const NodePtr &ptr)
{ detail::get_pointer(ptr)->~Node(); }
{ containers_detail::get_pointer(ptr)->~Node(); }
#ifdef BOOST_INTERPROCESS_RVALUE_REFERENCE
Deallocator
#else
move_return<Deallocator>
#endif
create_node_and_deallocator()
Deallocator create_node_and_deallocator()
{
NodePtr p = this->allocate_one();
Deallocator node_deallocator(p, this->node_alloc());
return node_deallocator;
return Deallocator(this->allocate_one(), this->node_alloc());
}
#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
template<class ...Args>
static void construct(const NodePtr &ptr, Args &&...args)
{ new((void*)detail::get_pointer(ptr)) Node(detail::forward_impl<Args>(args)...); }
{ new((void*)containers_detail::get_pointer(ptr)) Node(boost::interprocess::forward<Args>(args)...); }
template<class ...Args>
NodePtr create_node(Args &&...args)
{
NodePtr p = this->allocate_one();
Deallocator node_deallocator(p, this->node_alloc());
self_t::construct(p, detail::forward_impl<Args>(args)...);
self_t::construct(p, boost::interprocess::forward<Args>(args)...);
node_deallocator.release();
return (p);
}
#else //#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
#else //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
static void construct(const NodePtr &ptr)
{ new((void*)detail::get_pointer(ptr)) Node(); }
{ new((void*)containers_detail::get_pointer(ptr)) Node(); }
NodePtr create_node()
{
@@ -240,37 +307,37 @@ struct node_alloc_holder
#define BOOST_PP_LOCAL_MACRO(n) \
template<BOOST_PP_ENUM_PARAMS(n, class P)> \
void construct(const NodePtr &ptr, BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_LIST, _)) \
void construct(const NodePtr &ptr, BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \
{ \
new((void*)detail::get_pointer(ptr)) \
Node(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_FORWARD, _)); \
new((void*)containers_detail::get_pointer(ptr)) \
Node(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)); \
} \
//!
#define BOOST_PP_LOCAL_LIMITS (1, BOOST_INTERPROCESS_MAX_CONSTRUCTOR_PARAMETERS)
#define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINERS_MAX_CONSTRUCTOR_PARAMETERS)
#include BOOST_PP_LOCAL_ITERATE()
#define BOOST_PP_LOCAL_MACRO(n) \
template<BOOST_PP_ENUM_PARAMS(n, class P)> \
NodePtr create_node(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_LIST, _)) \
NodePtr create_node(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \
{ \
NodePtr p = this->allocate_one(); \
Deallocator node_deallocator(p, this->node_alloc()); \
self_t::construct(p, BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_FORWARD, _)); \
self_t::construct(p, BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)); \
node_deallocator.release(); \
return (p); \
} \
//!
#define BOOST_PP_LOCAL_LIMITS (1, BOOST_INTERPROCESS_MAX_CONSTRUCTOR_PARAMETERS)
#define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINERS_MAX_CONSTRUCTOR_PARAMETERS)
#include BOOST_PP_LOCAL_ITERATE()
#endif //#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
#endif //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
template<class It>
NodePtr create_node_from_it(It it)
{
NodePtr p = this->allocate_one();
Deallocator node_deallocator(p, this->node_alloc());
::boost::interprocess::construct_in_place(detail::get_pointer(p), it);
::boost::interprocess_container::construct_in_place(containers_detail::get_pointer(p), it);
node_deallocator.release();
return (p);
}
@@ -287,7 +354,7 @@ struct node_alloc_holder
NodeAlloc& other_alloc = x.node_alloc();
if (this_alloc != other_alloc){
detail::do_swap(this_alloc, other_alloc);
containers_detail::do_swap(this_alloc, other_alloc);
}
this->icont().swap(x.icont());
@@ -298,19 +365,19 @@ struct node_alloc_holder
(FwdIterator beg, difference_type n, Inserter inserter)
{
if(n){
typedef typename NodeAlloc::multiallocation_iterator multiallocation_iterator;
typedef typename NodeAlloc::multiallocation_chain multiallocation_chain;
//Try to allocate memory in a single block
multiallocation_iterator itbeg =
this->node_alloc().allocate_individual(n), itend, itold;
multiallocation_chain mem(this->node_alloc().allocate_individual(n));
int constructed = 0;
Node *p = 0;
BOOST_TRY{
for(difference_type i = 0; i < n; ++i, ++beg, --constructed){
p = &*itbeg;
++itbeg;
p = containers_detail::get_pointer(mem.front());
mem.pop_front();
//This can throw
boost::interprocess::construct_in_place(p, beg);
constructed = 0;
boost::interprocess_container::construct_in_place(p, beg);
++constructed;
//This can throw in some containers (predicate might throw)
inserter(*p);
@@ -320,7 +387,7 @@ struct node_alloc_holder
if(constructed){
this->destroy(p);
}
this->node_alloc().deallocate_many(itbeg);
this->node_alloc().deallocate_individual(boost::interprocess::move(mem));
BOOST_RETHROW
}
BOOST_CATCH_END
@@ -334,8 +401,12 @@ struct node_alloc_holder
void clear(allocator_v2)
{
allocator_multialloc_chain_node_deallocator<NodeAlloc> chain_holder(this->node_alloc());
this->icont().clear_and_dispose(chain_holder.get_chain_builder());
typename NodeAlloc::multiallocation_chain chain;
allocator_destroyer_and_chain_builder<NodeAlloc> builder(this->node_alloc(), chain);
this->icont().clear_and_dispose(builder);
BOOST_STATIC_ASSERT((boost::interprocess::is_movable<typename NodeAlloc::multiallocation_chain>::value == true));
if(!chain.empty())
this->node_alloc().deallocate_individual(boost::interprocess::move(chain));
}
icont_iterator erase_range(icont_iterator first, icont_iterator last, allocator_v1)
@@ -419,10 +490,10 @@ struct node_alloc_holder
{ return static_cast<const NodeAlloc &>(this->members_); }
};
} //namespace detail {
} //namespace interprocess {
} //namespace containers_detail {
} //namespace interprocess_container {
} //namespace boost {
#include <boost/interprocess/detail/config_end.hpp>
#include <boost/interprocess/containers/container/detail/config_end.hpp>
#endif // BOOST_INTERPROCESS_DETAIL_NODE_ALLOC_HPP_
#endif // BOOST_CONTAINERS_DETAIL_NODE_ALLOC_HPP_

View File

@@ -0,0 +1,189 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005-2009.
//
// 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/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINERS_CONTAINERS_DETAIL_PAIR_HPP
#define BOOST_CONTAINERS_CONTAINERS_DETAIL_PAIR_HPP
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif
#include <boost/interprocess/containers/container/detail/config_begin.hpp>
#include <boost/interprocess/containers/container/detail/workaround.hpp>
#include <boost/interprocess/containers/container/detail/mpl.hpp>
#include <boost/interprocess/containers/container/detail/type_traits.hpp>
#include <utility> //std::pair
#include <boost/interprocess/detail/move.hpp>
#ifndef BOOST_CONTAINERS_PERFECT_FORWARDING
#include <boost/interprocess/containers/container/detail/preprocessor.hpp>
#endif
namespace boost {
namespace interprocess_container {
namespace containers_detail {
template <class T1, class T2>
struct pair
{
BOOST_INTERPROCESS_ENABLE_MOVE_EMULATION(pair)
typedef T1 first_type;
typedef T2 second_type;
T1 first;
T2 second;
//std::pair compatibility
template <class D, class S>
pair(const std::pair<D, S>& p)
: first(p.first), second(p.second)
{}
//To resolve ambiguity with the variadic constructor of 1 argument
//and the previous constructor
pair(std::pair<T1, T2>& x)
: first(x.first), second(x.second)
{}
template <class D, class S>
pair(BOOST_INTERPROCESS_RV_REF_2_TEMPL_ARGS(std::pair, D, S) p)
: first(boost::interprocess::move(p.first)), second(boost::interprocess::move(p.second))
{}
pair()
: first(), second()
{}
pair(const pair<T1, T2>& x)
: first(x.first), second(x.second)
{}
//To resolve ambiguity with the variadic constructor of 1 argument
//and the copy constructor
pair(pair<T1, T2>& x)
: first(x.first), second(x.second)
{}
pair(BOOST_INTERPROCESS_RV_REF(pair) p)
: first(boost::interprocess::move(p.first)), second(boost::interprocess::move(p.second))
{}
template <class D, class S>
pair(BOOST_INTERPROCESS_RV_REF_2_TEMPL_ARGS(pair, D, S) p)
: first(boost::interprocess::move(p.first)), second(boost::interprocess::move(p.second))
{}
#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
template<class U, class ...Args>
pair(U &&u, Args &&... args)
: first(boost::interprocess::forward<U>(u))
, second(boost::interprocess::forward<Args>(args)...)
{}
#else
template<class U>
pair( BOOST_CONTAINERS_PARAM(U, u)
#ifndef BOOST_HAS_RVALUE_REFS
, typename containers_detail::disable_if
< containers_detail::is_same<U, boost::interprocess::rv<pair> > >::type* = 0
#endif
)
: first(boost::interprocess::forward<U>(const_cast<U&>(u)))
{}
#define BOOST_PP_LOCAL_MACRO(n) \
template<class U, BOOST_PP_ENUM_PARAMS(n, class P)> \
pair(BOOST_CONTAINERS_PARAM(U, u) \
,BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \
: first(boost::interprocess::forward<U>(const_cast<U&>(u))) \
, second(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)) \
{} \
//!
#define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINERS_MAX_CONSTRUCTOR_PARAMETERS)
#include BOOST_PP_LOCAL_ITERATE()
#endif
pair& operator=(BOOST_INTERPROCESS_RV_REF(pair) p)
{
first = boost::interprocess::move(p.first);
second = boost::interprocess::move(p.second);
return *this;
}
pair& operator=(BOOST_INTERPROCESS_RV_REF_2_TEMPL_ARGS(std::pair, T1, T2) p)
{
first = boost::interprocess::move(p.first);
second = boost::interprocess::move(p.second);
return *this;
}
template <class D, class S>
pair& operator=(BOOST_INTERPROCESS_RV_REF_2_TEMPL_ARGS(std::pair, D, S) p)
{
first = boost::interprocess::move(p.first);
second = boost::interprocess::move(p.second);
return *this;
}
void swap(pair& p)
{ std::swap(*this, p); }
};
template <class T1, class T2>
inline bool operator==(const pair<T1,T2>& x, const pair<T1,T2>& y)
{ return static_cast<bool>(x.first == y.first && x.second == y.second); }
template <class T1, class T2>
inline bool operator< (const pair<T1,T2>& x, const pair<T1,T2>& y)
{ return static_cast<bool>(x.first < y.first ||
(!(y.first < x.first) && x.second < y.second)); }
template <class T1, class T2>
inline bool operator!=(const pair<T1,T2>& x, const pair<T1,T2>& y)
{ return static_cast<bool>(!(x == y)); }
template <class T1, class T2>
inline bool operator> (const pair<T1,T2>& x, const pair<T1,T2>& y)
{ return y < x; }
template <class T1, class T2>
inline bool operator>=(const pair<T1,T2>& x, const pair<T1,T2>& y)
{ return static_cast<bool>(!(x < y)); }
template <class T1, class T2>
inline bool operator<=(const pair<T1,T2>& x, const pair<T1,T2>& y)
{ return static_cast<bool>(!(y < x)); }
template <class T1, class T2>
inline pair<T1, T2> make_pair(T1 x, T2 y)
{ return pair<T1, T2>(x, y); }
template <class T1, class T2>
inline void swap(pair<T1, T2>& x, pair<T1, T2>& y)
{
swap(x.first, y.first);
swap(x.second, y.second);
}
} //namespace containers_detail {
} //namespace interprocess_container {
} //namespace boost {
#include <boost/interprocess/containers/container/detail/config_end.hpp>
#endif //#ifndef BOOST_CONTAINERS_DETAIL_PAIR_HPP

View File

@@ -0,0 +1,101 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2008-2008. 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/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINERS_DETAIL_PREPROCESSOR_HPP
#define BOOST_CONTAINERS_DETAIL_PREPROCESSOR_HPP
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif
#include <boost/interprocess/containers/container/detail/config_begin.hpp>
#include <boost/interprocess/containers/container/detail/workaround.hpp>
#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
#error "This file is not needed when perfect forwarding is available"
#endif
#include <boost/preprocessor/iteration/local.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/repetition/enum.hpp>
#include <boost/preprocessor/repetition/repeat.hpp>
#define BOOST_CONTAINERS_MAX_CONSTRUCTOR_PARAMETERS 10
//Note:
//We define template parameters as const references to
//be able to bind temporaries. After that we will un-const them.
//This cast is ugly but it is necessary until "perfect forwarding"
//is achieved in C++0x. Meanwhile, if we want to be able to
//bind rvalues with non-const references, we have to be ugly
#ifdef BOOST_HAS_RVALUE_REFS
#define BOOST_CONTAINERS_PP_PARAM_LIST(z, n, data) \
BOOST_PP_CAT(P, n) && BOOST_PP_CAT(p, n) \
//!
#else
#define BOOST_CONTAINERS_PP_PARAM_LIST(z, n, data) \
const BOOST_PP_CAT(P, n) & BOOST_PP_CAT(p, n) \
//!
#endif
#ifdef BOOST_HAS_RVALUE_REFS
#define BOOST_CONTAINERS_PARAM(U, u) \
U && u \
//!
#else
#define BOOST_CONTAINERS_PARAM(U, u) \
const U & u \
//!
#endif
#ifdef BOOST_HAS_RVALUE_REFS
#define BOOST_CONTAINERS_AUX_PARAM_INIT(z, n, data) \
BOOST_PP_CAT(m_p, n) (BOOST_PP_CAT(p, n)) \
//!
#else
#define BOOST_CONTAINERS_AUX_PARAM_INIT(z, n, data) \
BOOST_PP_CAT(m_p, n) (const_cast<BOOST_PP_CAT(P, n) &>(BOOST_PP_CAT(p, n))) \
//!
#endif
#define BOOST_CONTAINERS_AUX_PARAM_INC(z, n, data) \
BOOST_PP_CAT(++m_p, n) \
//!
#ifdef BOOST_HAS_RVALUE_REFS
#define BOOST_CONTAINERS_AUX_PARAM_DEFINE(z, n, data) \
BOOST_PP_CAT(P, n) && BOOST_PP_CAT(m_p, n); \
//!
#else
#define BOOST_CONTAINERS_AUX_PARAM_DEFINE(z, n, data) \
BOOST_PP_CAT(P, n) & BOOST_PP_CAT(m_p, n); \
//!
#endif
#define BOOST_CONTAINERS_PP_PARAM_FORWARD(z, n, data) \
boost::interprocess::forward< BOOST_PP_CAT(P, n) >( BOOST_PP_CAT(p, n) ) \
//!
#define BOOST_CONTAINERS_PP_MEMBER_FORWARD(z, n, data) \
boost::interprocess::forward< BOOST_PP_CAT(P, n) >( BOOST_PP_CAT(m_p, n) ) \
//!
#define BOOST_CONTAINERS_PP_MEMBER_IT_FORWARD(z, n, data) \
BOOST_PP_CAT(*m_p, n) \
//!
#include <boost/interprocess/containers/container/detail/config_end.hpp>
#else
#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
#error "This file is not needed when perfect forwarding is available"
#endif
#endif //#ifndef BOOST_CONTAINERS_DETAIL_PREPROCESSOR_HPP

View File

@@ -0,0 +1,176 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005-2008.
// (C) Copyright Gennaro Prota 2003 - 2004.
//
// 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/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINERS_DETAIL_TRANSFORM_ITERATORS_HPP
#define BOOST_CONTAINERS_DETAIL_TRANSFORM_ITERATORS_HPP
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif
#include <boost/interprocess/containers/container/detail/config_begin.hpp>
#include <boost/interprocess/containers/container/detail/workaround.hpp>
#include <boost/interprocess/containers/container/detail/type_traits.hpp>
#include <iterator>
namespace boost {
namespace interprocess_container {
template <class PseudoReference>
struct operator_arrow_proxy
{
operator_arrow_proxy(const PseudoReference &px)
: m_value(px)
{}
PseudoReference* operator->() const { return &m_value; }
// This function is needed for MWCW and BCC, which won't call operator->
// again automatically per 13.3.1.2 para 8
// operator T*() const { return &m_value; }
mutable PseudoReference m_value;
};
template <class T>
struct operator_arrow_proxy<T&>
{
operator_arrow_proxy(T &px)
: m_value(px)
{}
T* operator->() const { return &m_value; }
// This function is needed for MWCW and BCC, which won't call operator->
// again automatically per 13.3.1.2 para 8
// operator T*() const { return &m_value; }
mutable T &m_value;
};
template <class Iterator, class UnaryFunction>
class transform_iterator
: public UnaryFunction
, public std::iterator
< typename Iterator::iterator_category
, typename containers_detail::remove_reference<typename UnaryFunction::result_type>::type
, typename Iterator::difference_type
, operator_arrow_proxy<typename UnaryFunction::result_type>
, typename UnaryFunction::result_type>
{
public:
explicit transform_iterator(const Iterator &it, const UnaryFunction &f = UnaryFunction())
: UnaryFunction(f), m_it(it)
{}
explicit transform_iterator()
: UnaryFunction(), m_it()
{}
//Constructors
transform_iterator& operator++()
{ increment(); return *this; }
transform_iterator operator++(int)
{
transform_iterator result (*this);
increment();
return result;
}
friend bool operator== (const transform_iterator& i, const transform_iterator& i2)
{ return i.equal(i2); }
friend bool operator!= (const transform_iterator& i, const transform_iterator& i2)
{ return !(i == i2); }
/*
friend bool operator> (const transform_iterator& i, const transform_iterator& i2)
{ return i2 < i; }
friend bool operator<= (const transform_iterator& i, const transform_iterator& i2)
{ return !(i > i2); }
friend bool operator>= (const transform_iterator& i, const transform_iterator& i2)
{ return !(i < i2); }
*/
friend typename Iterator::difference_type operator- (const transform_iterator& i, const transform_iterator& i2)
{ return i2.distance_to(i); }
//Arithmetic
transform_iterator& operator+=(typename Iterator::difference_type off)
{ this->advance(off); return *this; }
transform_iterator operator+(typename Iterator::difference_type off) const
{
transform_iterator other(*this);
other.advance(off);
return other;
}
friend transform_iterator operator+(typename Iterator::difference_type off, const transform_iterator& right)
{ return right + off; }
transform_iterator& operator-=(typename Iterator::difference_type off)
{ this->advance(-off); return *this; }
transform_iterator operator-(typename Iterator::difference_type off) const
{ return *this + (-off); }
typename UnaryFunction::result_type operator*() const
{ return dereference(); }
operator_arrow_proxy<typename UnaryFunction::result_type>
operator->() const
{ return operator_arrow_proxy<typename UnaryFunction::result_type>(dereference()); }
Iterator & base()
{ return m_it; }
const Iterator & base() const
{ return m_it; }
private:
Iterator m_it;
void increment()
{ ++m_it; }
void decrement()
{ --m_it; }
bool equal(const transform_iterator &other) const
{ return m_it == other.m_it; }
bool less(const transform_iterator &other) const
{ return other.m_it < m_it; }
typename UnaryFunction::result_type dereference() const
{ return UnaryFunction::operator()(*m_it); }
void advance(typename Iterator::difference_type n)
{ std::advance(m_it, n); }
typename Iterator::difference_type distance_to(const transform_iterator &other)const
{ return std::distance(other.m_it, m_it); }
};
template <class Iterator, class UnaryFunc>
transform_iterator<Iterator, UnaryFunc>
make_transform_iterator(Iterator it, UnaryFunc fun)
{
return transform_iterator<Iterator, UnaryFunc>(it, fun);
}
} //namespace interprocess_container {
} //namespace boost {
#include <boost/interprocess/containers/container/detail/config_end.hpp>
#endif //#ifndef BOOST_CONTAINERS_DETAIL_TRANSFORM_ITERATORS_HPP

View File

@@ -4,7 +4,7 @@
// 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.
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
//
@@ -39,21 +39,25 @@
* purpose. It is provided "as is" without express or implied warranty.
*
*/
#ifndef BOOST_INTERPROCESS_TREE_HPP
#define BOOST_INTERPROCESS_TREE_HPP
#ifndef BOOST_CONTAINERS_TREE_HPP
#define BOOST_CONTAINERS_TREE_HPP
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/interprocess/containers/container/detail/config_begin.hpp>
#include <boost/interprocess/containers/container/detail/workaround.hpp>
#include <boost/interprocess/detail/move.hpp>
#include <boost/interprocess/detail/utilities.hpp>
#include <boost/interprocess/detail/algorithms.hpp>
#include <boost/pointer_to_other.hpp>
#include <boost/type_traits/has_trivial_destructor.hpp>
#include <boost/detail/no_exceptions_support.hpp>
#include <boost/interprocess/containers/detail/node_alloc_holder.hpp>
#include <boost/intrusive/rbtree.hpp>
#ifndef BOOST_INTERPROCESS_PERFECT_FORWARDING
#include <boost/interprocess/detail/preprocessor.hpp>
#include <boost/interprocess/containers/container/detail/utilities.hpp>
#include <boost/interprocess/containers/container/detail/algorithms.hpp>
#include <boost/interprocess/containers/container/detail/node_alloc_holder.hpp>
#include <boost/interprocess/containers/container/detail/destroyers.hpp>
#include <boost/interprocess/containers/container/detail/pair.hpp>
#ifndef BOOST_CONTAINERS_PERFECT_FORWARDING
#include <boost/interprocess/containers/container/detail/preprocessor.hpp>
#endif
#include <utility> //std::pair
@@ -61,8 +65,8 @@
#include <algorithm>
namespace boost {
namespace interprocess {
namespace detail {
namespace interprocess_container {
namespace containers_detail {
template<class Key, class Value, class KeyCompare, class KeyOfValue>
struct value_compare_impl
@@ -91,10 +95,10 @@ struct value_compare_impl
template<class VoidPointer>
struct rbtree_hook
{
typedef typename bi::make_set_base_hook
< bi::void_pointer<VoidPointer>
, bi::link_mode<bi::normal_link>
, bi::optimize_size<true>
typedef typename containers_detail::bi::make_set_base_hook
< containers_detail::bi::void_pointer<VoidPointer>
, containers_detail::bi::link_mode<containers_detail::bi::normal_link>
, containers_detail::bi::optimize_size<true>
>::type type;
};
@@ -107,7 +111,7 @@ struct rbtree_type
template<class T1, class T2>
struct rbtree_type< std::pair<T1, T2> >
{
typedef detail::pair<T1, T2> type;
typedef pair<T1, T2> type;
};
template <class T, class VoidPointer>
@@ -121,28 +125,32 @@ struct rbtree_node
typedef rbtree_node<T, VoidPointer> node_type;
#ifndef BOOST_INTERPROCESS_PERFECT_FORWARDING
#ifndef BOOST_CONTAINERS_PERFECT_FORWARDING
rbtree_node()
: m_data()
{}
rbtree_node(const rbtree_node &other)
: m_data(other.m_data)
{}
#define BOOST_PP_LOCAL_MACRO(n) \
template<BOOST_PP_ENUM_PARAMS(n, class P)> \
rbtree_node(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_LIST, _)) \
: m_data(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_FORWARD, _)) \
rbtree_node(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \
: m_data(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)) \
{} \
//!
#define BOOST_PP_LOCAL_LIMITS (1, BOOST_INTERPROCESS_MAX_CONSTRUCTOR_PARAMETERS)
#define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINERS_MAX_CONSTRUCTOR_PARAMETERS)
#include BOOST_PP_LOCAL_ITERATE()
#else //#ifndef BOOST_INTERPROCESS_PERFECT_FORWARDING
#else //#ifndef BOOST_CONTAINERS_PERFECT_FORWARDING
template<class ...Args>
rbtree_node(Args &&...args)
: m_data(detail::forward_impl<Args>(args)...)
: m_data(boost::interprocess::forward<Args>(args)...)
{}
#endif//#ifndef BOOST_INTERPROCESS_PERFECT_FORWARDING
#endif//#ifndef BOOST_CONTAINERS_PERFECT_FORWARDING
rbtree_node &operator=(const rbtree_node &other)
{ do_assign(other.m_data); return *this; }
@@ -170,7 +178,7 @@ struct rbtree_node
}
template<class A, class B>
void do_assign(const detail::pair<const A, B> &p)
void do_assign(const pair<const A, B> &p)
{
const_cast<A&>(m_data.first) = p.first;
m_data.second = p.second;
@@ -182,64 +190,58 @@ struct rbtree_node
public:
template<class Convertible>
static void construct(node_type *ptr
#if !defined(BOOST_INTERPROCESS_RVALUE_REFERENCE)
, const Convertible &value)
#else
, Convertible &&value)
#endif
{ new(ptr) node_type(detail::forward_impl<Convertible>(value)); }
static void construct(node_type *ptr, BOOST_INTERPROCESS_FWD_REF(Convertible) convertible)
{ new(ptr) node_type(boost::interprocess::forward<Convertible>(convertible)); }
};
}//namespace detail {
#if !defined(BOOST_INTERPROCESS_RVALUE_REFERENCE) || !defined(BOOST_INTERPROCESS_RVALUE_PAIR)
}//namespace containers_detail {
#if !defined(BOOST_HAS_RVALUE_REFS)
template<class T, class VoidPointer>
struct has_own_construct_from_it
< boost::interprocess::detail::rbtree_node<T, VoidPointer> >
< boost::interprocess_container::containers_detail::rbtree_node<T, VoidPointer> >
{
static const bool value = true;
};
#endif
namespace detail {
namespace containers_detail {
template<class A, class ValueCompare>
struct intrusive_rbtree_type
{
typedef typename A::value_type value_type;
typedef typename detail::pointer_to_other
typedef typename boost::pointer_to_other
<typename A::pointer, void>::type void_pointer;
typedef typename detail::rbtree_node
typedef typename containers_detail::rbtree_node
<value_type, void_pointer> node_type;
typedef node_compare<ValueCompare, node_type> node_compare_type;
typedef typename bi::make_rbtree
typedef typename containers_detail::bi::make_rbtree
<node_type
,bi::compare<node_compare_type>
,bi::base_hook<typename rbtree_hook<void_pointer>::type>
,bi::constant_time_size<true>
,bi::size_type<typename A::size_type>
,containers_detail::bi::compare<node_compare_type>
,containers_detail::bi::base_hook<typename rbtree_hook<void_pointer>::type>
,containers_detail::bi::constant_time_size<true>
,containers_detail::bi::size_type<typename A::size_type>
>::type container_type;
typedef container_type type ;
};
} //namespace detail {
} //namespace containers_detail {
namespace detail {
namespace containers_detail {
template <class Key, class Value, class KeyOfValue,
class KeyCompare, class A>
class rbtree
: protected detail::node_alloc_holder
<A, typename detail::intrusive_rbtree_type
: protected containers_detail::node_alloc_holder
<A, typename containers_detail::intrusive_rbtree_type
<A, value_compare_impl<Key, Value, KeyCompare, KeyOfValue>
>::type
>
{
typedef typename detail::intrusive_rbtree_type
typedef typename containers_detail::intrusive_rbtree_type
<A, value_compare_impl
<Key, Value, KeyCompare, KeyOfValue>
>::type Icont;
typedef detail::node_alloc_holder<A, Icont> AllocHolder;
typedef containers_detail::node_alloc_holder<A, Icont> AllocHolder;
typedef typename AllocHolder::NodePtr NodePtr;
typedef rbtree < Key, Value, KeyOfValue
, KeyCompare, A> ThisType;
@@ -248,7 +250,7 @@ class rbtree
typedef typename AllocHolder::Node Node;
typedef typename Icont::iterator iiterator;
typedef typename Icont::const_iterator iconst_iterator;
typedef detail::allocator_destroyer<NodeAlloc> Destroyer;
typedef containers_detail::allocator_destroyer<NodeAlloc> Destroyer;
typedef typename AllocHolder::allocator_v1 allocator_v1;
typedef typename AllocHolder::allocator_v2 allocator_v2;
typedef typename AllocHolder::alloc_version alloc_version;
@@ -293,6 +295,8 @@ class rbtree
};
public:
BOOST_INTERPROCESS_ENABLE_MOVE_EMULATION(rbtree)
typedef Key key_type;
typedef Value value_type;
typedef A allocator_type;
@@ -450,15 +454,9 @@ class rbtree
(x.icont(), typename AllocHolder::cloner(*this), Destroyer(this->node_alloc()));
}
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
rbtree(detail::moved_object<rbtree> x)
: AllocHolder(x.get(), x.get().key_comp())
{ this->swap(x.get()); }
#else
rbtree(rbtree &&x)
rbtree(BOOST_INTERPROCESS_RV_REF(rbtree) x)
: AllocHolder(x, x.key_comp())
{ this->swap(x); }
#endif
~rbtree()
{} //AllocHolder clears the tree
@@ -488,13 +486,8 @@ class rbtree
return *this;
}
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
rbtree& operator=(detail::moved_object<rbtree> mx)
{ this->clear(); this->swap(mx.get()); return *this; }
#else
rbtree& operator=(rbtree &&mx)
rbtree& operator=(BOOST_INTERPROCESS_RV_REF(rbtree) mx)
{ this->clear(); this->swap(mx); return *this; }
#endif
public:
// accessors:
@@ -583,14 +576,6 @@ class rbtree
void swap(ThisType& x)
{ AllocHolder::swap(x); }
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
void swap(detail::moved_object<rbtree> mt)
{ this->swap(mt.get()); }
#else
void swap(rbtree &&mt)
{ this->swap(mt); }
#endif
public:
typedef typename Icont::insert_commit_data insert_commit_data;
@@ -619,25 +604,14 @@ class rbtree
return iterator(it);
}
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
template<class MovableConvertible>
iterator insert_unique_commit
(detail::moved_object<MovableConvertible> mv, insert_commit_data &data)
(BOOST_INTERPROCESS_FWD_REF(MovableConvertible) mv, insert_commit_data &data)
{
NodePtr tmp = AllocHolder::create_node(mv);
NodePtr tmp = AllocHolder::create_node(boost::interprocess::forward<MovableConvertible>(mv));
iiterator it(this->icont().insert_unique_commit(*tmp, data));
return iterator(it);
}
#else
template<class MovableConvertible>
iterator insert_unique_commit
(MovableConvertible && mv, insert_commit_data &data)
{
NodePtr tmp = AllocHolder::create_node(detail::forward_impl<MovableConvertible>(mv));
iiterator it(this->icont().insert_unique_commit(*tmp, data));
return iterator(it);
}
#endif
std::pair<iterator,bool> insert_unique(const value_type& v)
{
@@ -650,21 +624,8 @@ class rbtree
(this->insert_unique_commit(v, data), true);
}
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
template<class MovableConvertible>
std::pair<iterator,bool> insert_unique(detail::moved_object<MovableConvertible> mv)
{
insert_commit_data data;
std::pair<iterator,bool> ret =
this->insert_unique_check(KeyOfValue()(mv.get()), data);
if(!ret.second)
return ret;
return std::pair<iterator,bool>
(this->insert_unique_commit(mv, data), true);
}
#else
template<class MovableConvertible>
std::pair<iterator,bool> insert_unique(MovableConvertible &&mv)
std::pair<iterator,bool> insert_unique(BOOST_INTERPROCESS_FWD_REF(MovableConvertible) mv)
{
insert_commit_data data;
std::pair<iterator,bool> ret =
@@ -672,9 +633,8 @@ class rbtree
if(!ret.second)
return ret;
return std::pair<iterator,bool>
(this->insert_unique_commit(detail::forward_impl<MovableConvertible>(mv), data), true);
(this->insert_unique_commit(boost::interprocess::forward<MovableConvertible>(mv), data), true);
}
#endif
private:
iterator emplace_unique_impl(NodePtr p)
@@ -705,31 +665,31 @@ class rbtree
public:
#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
template <class... Args>
iterator emplace_unique(Args&&... args)
{ return this->emplace_unique_impl(AllocHolder::create_node(detail::forward_impl<Args>(args)...)); }
{ return this->emplace_unique_impl(AllocHolder::create_node(boost::interprocess::forward<Args>(args)...)); }
template <class... Args>
iterator emplace_hint_unique(const_iterator hint, Args&&... args)
{ return this->emplace_unique_hint_impl(hint, AllocHolder::create_node(detail::forward_impl<Args>(args)...)); }
{ return this->emplace_unique_hint_impl(hint, AllocHolder::create_node(boost::interprocess::forward<Args>(args)...)); }
template <class... Args>
iterator emplace_equal(Args&&... args)
{
NodePtr p(AllocHolder::create_node(detail::forward_impl<Args>(args)...));
NodePtr p(AllocHolder::create_node(boost::interprocess::forward<Args>(args)...));
return iterator(this->icont().insert_equal(this->icont().end(), *p));
}
template <class... Args>
iterator emplace_hint_equal(const_iterator hint, Args&&... args)
{
NodePtr p(AllocHolder::create_node(detail::forward_impl<Args>(args)...));
NodePtr p(AllocHolder::create_node(boost::interprocess::forward<Args>(args)...));
return iterator(this->icont().insert_equal(hint.get(), *p));
}
#else //#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
#else //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
iterator emplace_unique()
{ return this->emplace_unique_impl(AllocHolder::create_node()); }
@@ -751,37 +711,37 @@ class rbtree
#define BOOST_PP_LOCAL_MACRO(n) \
template<BOOST_PP_ENUM_PARAMS(n, class P)> \
iterator emplace_unique(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_LIST, _)) \
iterator emplace_unique(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \
{ \
return this->emplace_unique_impl \
(AllocHolder::create_node(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_FORWARD, _))); \
(AllocHolder::create_node(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _))); \
} \
\
template<BOOST_PP_ENUM_PARAMS(n, class P)> \
iterator emplace_hint_unique(const_iterator hint, BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_LIST, _)) \
iterator emplace_hint_unique(const_iterator hint, BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \
{ \
return this->emplace_unique_hint_impl \
(hint, AllocHolder::create_node(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_FORWARD, _))); \
(hint, AllocHolder::create_node(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _))); \
} \
\
template<BOOST_PP_ENUM_PARAMS(n, class P)> \
iterator emplace_equal(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_LIST, _)) \
iterator emplace_equal(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \
{ \
NodePtr p(AllocHolder::create_node(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_FORWARD, _))); \
NodePtr p(AllocHolder::create_node(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _))); \
return iterator(this->icont().insert_equal(this->icont().end(), *p)); \
} \
\
template<BOOST_PP_ENUM_PARAMS(n, class P)> \
iterator emplace_hint_equal(const_iterator hint, BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_LIST, _)) \
iterator emplace_hint_equal(const_iterator hint, BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \
{ \
NodePtr p(AllocHolder::create_node(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_FORWARD, _))); \
NodePtr p(AllocHolder::create_node(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _))); \
return iterator(this->icont().insert_equal(hint.get(), *p)); \
} \
//!
#define BOOST_PP_LOCAL_LIMITS (1, BOOST_INTERPROCESS_MAX_CONSTRUCTOR_PARAMETERS)
#define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINERS_MAX_CONSTRUCTOR_PARAMETERS)
#include BOOST_PP_LOCAL_ITERATE()
#endif //#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
#endif //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
iterator insert_unique(const_iterator hint, const value_type& v)
{
@@ -793,30 +753,16 @@ class rbtree
return this->insert_unique_commit(v, data);
}
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
template<class MovableConvertible>
iterator insert_unique(const_iterator hint, detail::moved_object<MovableConvertible> mv)
{
insert_commit_data data;
std::pair<iterator,bool> ret =
this->insert_unique_check(hint, KeyOfValue()(mv.get()), data);
if(!ret.second)
return ret.first;
return this->insert_unique_commit(mv, data);
}
#else
template<class MovableConvertible>
iterator insert_unique
(const_iterator hint, MovableConvertible &&mv)
iterator insert_unique(const_iterator hint, BOOST_INTERPROCESS_FWD_REF(MovableConvertible) mv)
{
insert_commit_data data;
std::pair<iterator,bool> ret =
this->insert_unique_check(hint, KeyOfValue()(mv), data);
if(!ret.second)
return ret.first;
return this->insert_unique_commit(detail::forward_impl<MovableConvertible>(mv), data);
return this->insert_unique_commit(boost::interprocess::forward<MovableConvertible>(mv), data);
}
#endif
template <class InputIterator>
void insert_unique(InputIterator first, InputIterator last)
@@ -840,21 +786,12 @@ class rbtree
return iterator(this->icont().insert_equal(this->icont().end(), *p));
}
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
template<class MovableConvertible>
iterator insert_equal(detail::moved_object<MovableConvertible> mv)
iterator insert_equal(BOOST_INTERPROCESS_FWD_REF(MovableConvertible) mv)
{
NodePtr p(AllocHolder::create_node(mv));
NodePtr p(AllocHolder::create_node(boost::interprocess::forward<MovableConvertible>(mv)));
return iterator(this->icont().insert_equal(this->icont().end(), *p));
}
#else
template<class MovableConvertible>
iterator insert_equal(MovableConvertible &&mv)
{
NodePtr p(AllocHolder::create_node(detail::forward_impl<MovableConvertible>(mv)));
return iterator(this->icont().insert_equal(this->icont().end(), *p));
}
#endif
iterator insert_equal(const_iterator hint, const value_type& v)
{
@@ -862,21 +799,12 @@ class rbtree
return iterator(this->icont().insert_equal(hint.get(), *p));
}
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
template<class MovableConvertible>
iterator insert_equal(const_iterator hint, detail::moved_object<MovableConvertible> mv)
iterator insert_equal(const_iterator hint, BOOST_INTERPROCESS_FWD_REF(MovableConvertible) mv)
{
NodePtr p(AllocHolder::create_node(mv));
NodePtr p(AllocHolder::create_node(boost::interprocess::forward<MovableConvertible>(mv)));
return iterator(this->icont().insert_equal(hint.get(), *p));
}
#else
template<class MovableConvertible>
iterator insert_equal(const_iterator hint, MovableConvertible &&mv)
{
NodePtr p(AllocHolder::create_node(detail::move_impl(mv)));
return iterator(this->icont().insert_equal(hint.get(), *p));
}
#endif
template <class InputIterator>
void insert_equal(InputIterator first, InputIterator last)
@@ -1066,46 +994,25 @@ swap(rbtree<Key,Value,KeyOfValue,KeyCompare,A>& x,
x.swap(y);
}
} //namespace detail {
} //namespace containers_detail {
} //namespace interprocess_container {
//!This class is movable
template <class T, class V, class K, class C, class A>
struct is_movable<detail::rbtree<T, V, K, C, A> >
{
enum { value = true };
};
//!This class is movable
template <class T, class VoidPointer>
struct is_movable<detail::rbtree_node<T, VoidPointer> >
{
enum { value = true };
};
//!This class is movable
/*
template <class A, class C>
struct is_movable<detail::rbtree_alloc<A, C> >
{
enum { value = true };
};
*/
namespace interprocess {
//!has_trivial_destructor_after_move<> == true_type
//!specialization for optimizations
template <class K, class V, class KOV,
class C, class A>
struct has_trivial_destructor_after_move<detail::rbtree<K, V, KOV, C, A> >
class C, class A>
struct has_trivial_destructor_after_move
<boost::interprocess_container::containers_detail::rbtree<K, V, KOV, C, A> >
{
enum { value =
has_trivial_destructor<A>::value &&
has_trivial_destructor<C>::value };
static const bool value = has_trivial_destructor<A>::value && has_trivial_destructor<C>::value;
};
} //namespace interprocess {
} //namespace interprocess {
} //namespace boost {
#include <boost/interprocess/detail/config_end.hpp>
#include <boost/interprocess/containers/container/detail/config_end.hpp>
#endif //BOOST_INTERPROCESS_TREE_HPP
#endif //BOOST_CONTAINERS_TREE_HPP

View File

@@ -0,0 +1,166 @@
//////////////////////////////////////////////////////////////////////////////
// (C) Copyright John Maddock 2000.
// (C) Copyright Ion Gaztanaga 2005-2008.
//
// 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/container for documentation.
//
// The alignment_of implementation comes from John Maddock's boost::alignment_of code
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINERS_CONTAINER_DETAIL_TYPE_TRAITS_HPP
#define BOOST_CONTAINERS_CONTAINER_DETAIL_TYPE_TRAITS_HPP
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif
#include <boost/interprocess/containers/container/detail/config_begin.hpp>
namespace boost {
namespace interprocess_container {
namespace containers_detail {
struct nat{};
//boost::alignment_of yields to 10K lines of preprocessed code, so we
//need an alternative
template <typename T> struct alignment_of;
template <typename T>
struct alignment_of_hack
{
char c;
T t;
alignment_of_hack();
};
template <unsigned A, unsigned S>
struct alignment_logic
{
enum{ value = A < S ? A : S };
};
template< typename T >
struct alignment_of
{
enum{ value = alignment_logic
< sizeof(alignment_of_hack<T>) - sizeof(T)
, sizeof(T)>::value };
};
//This is not standard, but should work with all compilers
union max_align
{
char char_;
short short_;
int int_;
long long_;
#ifdef BOOST_HAS_LONG_LONG
long long long_long_;
#endif
float float_;
double double_;
long double long_double_;
void * void_ptr_;
};
template<class T>
struct remove_reference
{
typedef T type;
};
template<class T>
struct remove_reference<T&>
{
typedef T type;
};
template<class T>
struct is_reference
{
enum { value = false };
};
template<class T>
struct is_reference<T&>
{
enum { value = true };
};
template<class T>
struct is_pointer
{
enum { value = false };
};
template<class T>
struct is_pointer<T*>
{
enum { value = true };
};
template <typename T>
struct add_reference
{
typedef T& type;
};
template<class T>
struct add_reference<T&>
{
typedef T& type;
};
template<>
struct add_reference<void>
{
typedef nat &type;
};
template<>
struct add_reference<const void>
{
typedef const nat &type;
};
template <class T>
struct add_const_reference
{ typedef const T &type; };
template <class T>
struct add_const_reference<T&>
{ typedef T& type; };
template <typename T, typename U>
struct is_same
{
typedef char yes_type;
struct no_type
{
char padding[8];
};
template <typename V>
static yes_type is_same_tester(V*, V*);
static no_type is_same_tester(...);
static T *t;
static U *u;
static const bool value = sizeof(yes_type) == sizeof(is_same_tester(t,u));
};
} // namespace containers_detail
} //namespace interprocess_container {
} //namespace boost {
#endif //#ifndef BOOST_CONTAINERS_CONTAINER_DETAIL_TYPE_TRAITS_HPP
#include <boost/interprocess/containers/container/detail/config_end.hpp>

View File

@@ -0,0 +1,95 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005-2008. 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/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINERS_DETAIL_UTILITIES_HPP
#define BOOST_CONTAINERS_DETAIL_UTILITIES_HPP
#include <boost/interprocess/containers/container/detail/config_begin.hpp>
#include <cstdio>
#include <algorithm>
namespace boost {
namespace interprocess_container {
namespace containers_detail {
template <class SizeType>
SizeType
get_next_capacity(const SizeType max_size
,const SizeType capacity
,const SizeType n)
{
// if (n > max_size - capacity)
// throw std::length_error("get_next_capacity");
const SizeType m3 = max_size/3;
if (capacity < m3)
return capacity + max_value(3*(capacity+1)/5, n);
if (capacity < m3*2)
return capacity + max_value((capacity+1)/2, n);
return max_size;
}
template<class T>
const T &max_value(const T &a, const T &b)
{ return a > b ? a : b; }
template<class T>
const T &min_value(const T &a, const T &b)
{ return a < b ? a : b; }
template<class SmartPtr>
struct smart_ptr_type
{
typedef typename SmartPtr::value_type value_type;
typedef value_type *pointer;
static pointer get (const SmartPtr &smartptr)
{ return smartptr.get();}
};
template<class T>
struct smart_ptr_type<T*>
{
typedef T value_type;
typedef value_type *pointer;
static pointer get (pointer ptr)
{ return ptr;}
};
//!Overload for smart pointers to avoid ADL problems with get_pointer
template<class Ptr>
inline typename smart_ptr_type<Ptr>::pointer
get_pointer(const Ptr &ptr)
{ return smart_ptr_type<Ptr>::get(ptr); }
//!To avoid ADL problems with swap
template <class T>
inline void do_swap(T& x, T& y)
{
using std::swap;
swap(x, y);
}
template <std::size_t OrigSize, std::size_t RoundTo>
struct ct_rounded_size
{
enum { value = ((OrigSize-1)/RoundTo+1)*RoundTo };
};
} //namespace containers_detail {
} //namespace interprocess_container {
} //namespace boost {
#include <boost/interprocess/containers/container/detail/config_end.hpp>
#endif //#ifndef BOOST_CONTAINERS_DETAIL_UTILITIES_HPP

View File

@@ -0,0 +1,43 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005-2009.
//
// 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/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINERS_DETAIL_VALUE_INIT_HPP
#define BOOST_CONTAINERS_DETAIL_VALUE_INIT_HPP
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif
#include <boost/interprocess/containers/container/detail/config_begin.hpp>
#include <boost/interprocess/containers/container/detail/workaround.hpp>
namespace boost {
namespace interprocess_container {
namespace containers_detail {
template<class T>
struct value_init
{
value_init()
: m_t()
{}
T m_t;
};
} //namespace containers_detail {
} //namespace interprocess_container {
} //namespace boost {
#include <boost/interprocess/containers/container/detail/config_end.hpp>
#endif //#ifndef BOOST_CONTAINERS_DETAIL_VALUE_INIT_HPP

View File

@@ -0,0 +1,153 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2008-2008. 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/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINERS_DETAIL_VARIADIC_TEMPLATES_TOOLS_HPP
#define BOOST_CONTAINERS_DETAIL_VARIADIC_TEMPLATES_TOOLS_HPP
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif
#include <boost/interprocess/containers/container/detail/config_begin.hpp>
#include <boost/interprocess/containers/container/detail/workaround.hpp>
#include <boost/interprocess/containers/container/detail/type_traits.hpp>
#include <cstddef> //std::size_t
namespace boost {
namespace interprocess_container {
namespace containers_detail {
template<typename... Values>
class tuple;
template<> class tuple<>
{};
template<typename Head, typename... Tail>
class tuple<Head, Tail...>
: private tuple<Tail...>
{
typedef tuple<Tail...> inherited;
public:
tuple() { }
// implicit copy-constructor is okay
// Construct tuple from separate arguments.
tuple(typename add_const_reference<Head>::type v,
typename add_const_reference<Tail>::type... vtail)
: inherited(vtail...), m_head(v)
{}
// Construct tuple from another tuple.
template<typename... VValues>
tuple(const tuple<VValues...>& other)
: m_head(other.head()), inherited(other.tail())
{}
template<typename... VValues>
tuple& operator=(const tuple<VValues...>& other)
{
m_head = other.head();
tail() = other.tail();
return this;
}
typename add_reference<Head>::type head() { return m_head; }
typename add_reference<const Head>::type head() const { return m_head; }
inherited& tail() { return *this; }
const inherited& tail() const { return *this; }
protected:
Head m_head;
};
template<typename... Values>
tuple<Values&&...> tie_forward(Values&&... values)
{ return tuple<Values&&...>(values...); }
template<int I, typename Tuple>
struct tuple_element;
template<int I, typename Head, typename... Tail>
struct tuple_element<I, tuple<Head, Tail...> >
{
typedef typename tuple_element<I-1, tuple<Tail...> >::type type;
};
template<typename Head, typename... Tail>
struct tuple_element<0, tuple<Head, Tail...> >
{
typedef Head type;
};
template<int I, typename Tuple>
class get_impl;
template<int I, typename Head, typename... Values>
class get_impl<I, tuple<Head, Values...> >
{
typedef typename tuple_element<I-1, tuple<Values...> >::type Element;
typedef get_impl<I-1, tuple<Values...> > Next;
public:
typedef typename add_reference<Element>::type type;
typedef typename add_const_reference<Element>::type const_type;
static type get(tuple<Head, Values...>& t) { return Next::get(t.tail()); }
static const_type get(const tuple<Head, Values...>& t) { return Next::get(t.tail()); }
};
template<typename Head, typename... Values>
class get_impl<0, tuple<Head, Values...> >
{
public:
typedef typename add_reference<Head>::type type;
typedef typename add_const_reference<Head>::type const_type;
static type get(tuple<Head, Values...>& t) { return t.head(); }
static const_type get(const tuple<Head, Values...>& t){ return t.head(); }
};
template<int I, typename... Values>
typename get_impl<I, tuple<Values...> >::type get(tuple<Values...>& t)
{ return get_impl<I, tuple<Values...> >::get(t); }
template<int I, typename... Values>
typename get_impl<I, tuple<Values...> >::const_type get(const tuple<Values...>& t)
{ return get_impl<I, tuple<Values...> >::get(t); }
////////////////////////////////////////////////////
// Builds an index_tuple<0, 1, 2, ..., Num-1>, that will
// be used to "unpack" into comma-separated values
// in a function call.
////////////////////////////////////////////////////
template<int... Indexes>
struct index_tuple{};
template<std::size_t Num, typename Tuple = index_tuple<> >
struct build_number_seq;
template<std::size_t Num, int... Indexes>
struct build_number_seq<Num, index_tuple<Indexes...> >
: build_number_seq<Num - 1, index_tuple<Indexes..., sizeof...(Indexes)> >
{};
template<int... Indexes>
struct build_number_seq<0, index_tuple<Indexes...> >
{ typedef index_tuple<Indexes...> type; };
}}} //namespace boost { namespace interprocess_container { namespace containers_detail {
#include <boost/interprocess/containers/container/detail/config_end.hpp>
#endif //#ifndef BOOST_CONTAINERS_DETAIL_VARIADIC_TEMPLATES_TOOLS_HPP

View File

@@ -4,7 +4,7 @@
// 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.
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
//
@@ -13,22 +13,22 @@
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTERPROCESS_DETAIL_VERSION_TYPE_HPP
#define BOOST_INTERPROCESS_DETAIL_VERSION_TYPE_HPP
#ifndef BOOST_CONTAINERS_DETAIL_VERSION_TYPE_HPP
#define BOOST_CONTAINERS_DETAIL_VERSION_TYPE_HPP
#include <boost/interprocess/detail/mpl.hpp>
#include <boost/interprocess/detail/type_traits.hpp>
#include <boost/interprocess/containers/container/detail/mpl.hpp>
#include <boost/interprocess/containers/container/detail/type_traits.hpp>
namespace boost{
namespace interprocess{
namespace detail{
namespace interprocess_container {
namespace containers_detail {
//using namespace boost;
template <class T, unsigned V>
struct version_type
: public detail::integral_constant<unsigned, V>
: public containers_detail::integral_constant<unsigned, V>
{
typedef T type;
@@ -38,7 +38,7 @@ struct version_type
namespace impl{
template <class T,
bool = detail::is_convertible<version_type<T, 0>, typename T::version>::value>
bool = containers_detail::is_convertible<version_type<T, 0>, typename T::version>::value>
struct extract_version
{
static const unsigned value = 1;
@@ -78,12 +78,12 @@ struct version<T, true>
template <class T>
struct version
: public detail::integral_constant<unsigned, impl::version<T>::value>
: public containers_detail::integral_constant<unsigned, impl::version<T>::value>
{
};
} //namespace detail{
} //namespace interprocess{
} //namespace containers_detail {
} //namespace interprocess_container {
} //namespace boost{
#endif //#define BOOST_INTERPROCESS_DETAIL_VERSION_TYPE_HPP
#endif //#define BOOST_CONTAINERS_DETAIL_VERSION_TYPE_HPP

View File

@@ -0,0 +1,24 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005-2008. 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/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINERS_DETAIL_WORKAROUND_HPP
#define BOOST_CONTAINERS_DETAIL_WORKAROUND_HPP
#include <boost/interprocess/containers/container/detail/config_begin.hpp>
#if defined(BOOST_HAS_RVALUE_REFS) && defined(BOOST_HAS_VARIADIC_TMPL)\
&& !defined(BOOST_INTERPROCESS_DISABLE_VARIADIC_TMPL)
#define BOOST_CONTAINERS_PERFECT_FORWARDING
#endif
#include <boost/interprocess/containers/container/detail/config_end.hpp>
#endif //#ifndef BOOST_CONTAINERS_DETAIL_WORKAROUND_HPP

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More