mirror of
https://github.com/boostorg/interprocess.git
synced 2026-01-19 04:12:13 +00:00
Changes for Boost.1.39
[SVN r51964]
This commit is contained in:
@@ -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"
|
||||
;
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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) ;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
//]
|
||||
@@ -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;
|
||||
}
|
||||
//]
|
||||
@@ -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;
|
||||
}
|
||||
//]
|
||||
68
example/comp_doc_anonymous_mutexB.cpp
Normal file
68
example/comp_doc_anonymous_mutexB.cpp
Normal 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>
|
||||
64
example/comp_doc_anonymous_semaphoreA.cpp
Normal file
64
example/comp_doc_anonymous_semaphoreA.cpp
Normal 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>
|
||||
61
example/comp_doc_anonymous_semaphoreB.cpp
Normal file
61
example/comp_doc_anonymous_semaphoreB.cpp
Normal 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>
|
||||
72
example/comp_doc_anonymous_upgradable_mutexA.cpp
Normal file
72
example/comp_doc_anonymous_upgradable_mutexA.cpp
Normal 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>
|
||||
70
example/comp_doc_anonymous_upgradable_mutexB.cpp
Normal file
70
example/comp_doc_anonymous_upgradable_mutexB.cpp
Normal 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>
|
||||
@@ -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;
|
||||
}
|
||||
//]
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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;
|
||||
}
|
||||
//]
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
//]
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
//]
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
//]
|
||||
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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;
|
||||
}
|
||||
//]
|
||||
|
||||
@@ -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>
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
72
example/doc_ipc_message.cpp
Normal file
72
example/doc_ipc_message.cpp
Normal 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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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;
|
||||
}
|
||||
//]
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
//]
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
//]
|
||||
|
||||
@@ -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");
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
//]
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
//]
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
//]
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
//]
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
//]
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
//]
|
||||
@@ -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>
|
||||
@@ -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;
|
||||
}
|
||||
//]
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
//]
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
//]
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
//]
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
//]
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
//]
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
@@ -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;
|
||||
}
|
||||
//]
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
//]
|
||||
|
||||
79
example/doc_spawn_vector.cpp
Normal file
79
example/doc_spawn_vector.cpp
Normal 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>
|
||||
@@ -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;
|
||||
}
|
||||
//]
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
//]
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
//]
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
//]
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
40
include/boost/interprocess/containers/allocation_type.hpp
Normal file
40
include/boost/interprocess/containers/allocation_type.hpp
Normal 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
|
||||
@@ -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
|
||||
|
||||
1482
include/boost/interprocess/containers/container/deque.hpp
Normal file
1482
include/boost/interprocess/containers/container/deque.hpp
Normal file
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
152
include/boost/interprocess/containers/container/detail/mpl.hpp
Normal file
152
include/boost/interprocess/containers/container/detail/mpl.hpp
Normal 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
|
||||
|
||||
@@ -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
|
||||
@@ -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_
|
||||
189
include/boost/interprocess/containers/container/detail/pair.hpp
Normal file
189
include/boost/interprocess/containers/container/detail/pair.hpp
Normal 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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
1390
include/boost/interprocess/containers/container/flat_map.hpp
Normal file
1390
include/boost/interprocess/containers/container/flat_map.hpp
Normal file
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
Reference in New Issue
Block a user