diff --git a/doc/interprocess.qbk b/doc/interprocess.qbk index 720685a..ba0ebb7 100644 --- a/doc/interprocess.qbk +++ b/doc/interprocess.qbk @@ -3421,74 +3421,57 @@ For more information about managed mapped file capabilities, see [endsect] -[section:managed_memory_segment_features Managed Memory Segment Features] +[section:managed_memory_segment_object_construction Managed Memory Segments: Object construction] -The following features are common to all managed memory segment classes, but +['Note: The following features are common to all managed memory segment classes, but we will use managed shared memory in our examples. We can do the same with -memory mapped files or other managed memory segment classes. +memory mapped files or other managed memory segment classes.] -[section:allocate_deallocate Allocating fragments of a managed memory segment] - -If a basic raw-byte allocation is needed from a managed memory -segment, (for example, a managed shared memory), to implement -top-level interprocess communications, this class offers -[*allocate] and [*deallocate] functions. The allocation function -comes with throwing and no throwing versions. Throwing version throws -boost::interprocess::bad_alloc (which derives from `std::bad_alloc`) -if there is no more memory and the non-throwing version returns 0 pointer. - -[import ../example/doc_managed_raw_allocation.cpp] -[doc_managed_raw_allocation] - -[endsect] - -[section:segment_offset Obtaining handles to identify data] - -The class also offers conversions between absolute addresses that belong to -a managed memory segment and a handle that can be passed using any -interprocess mechanism. That handle can be transformed again to an absolute -address using a managed memory segment that also contains that object. -Handles can be used as keys between processes to identify allocated portions -of a managed memory segment or objects constructed in the managed segment. - -[c++] - - //Process A obtains the offset of the address - managed_shared_memory::handle handle = - segment.get_handle_from_address(processA_address); - - //Process A sends this address using any mechanism to process B - - //Process B obtains the handle and transforms it again to an address - managed_shared_memory::handle handle = ... - void * processB_address = segment.get_address_from_handle(handle); - -[endsect] - -[section:object_constrution Object construction and uses-allocator protocol] +[section:object_construction_api Object construction API for managed memory segments] [*Boost.Interprocess]' managed memory segments allows a varied object -construction styles: associated with a name, anonymous or "singleton-like" -objects. +construction styles: -The object construction API allows constructing both individual elements -and arrays of objects. An array can be constructed with the same -parameters for all objects within the array or we can define a different -parameter from a list of iterators. +* Associated with a name (['named construction]). Objects can be later found using the name as a key. +* Not associated with any name (['anonymous construction]). +* Singleton-like allocation (['unique construction]). A single object of this type can live in the managed segment. + Objects can be found using their type as a key. + +The object construction API allows constructing a type `T` in a managed memory segment instance `ms` as: + +* An individual object: + * Invoked as `ms.construct("Name"/unique_instance/anonymous_instance)(args...)`) + * `T` is constructed as `T(args...)` +* An arrays of `N` objects. Elements of an array can be constructed: + * with the same parameters for all elements: + * Invoked as `ms.construct("Name"/unique_instance/anonymous_instance)[N])(args...)` + * All array elements are constructed as `T(args...)` + * with a different parameter for each element coming from a derefenced iterator `it` + * Invoked as `ms.construct_it("Name"/unique_instance/anonymous_instance)[N])(it)` + * Elements are constructed as `T(*(it++))` + +[endsect] + +[section:uses_allocator Uses-allocator protocol for object construction] Since Boost 1.91, [*Boost.Interprocess] uses [*Boost.Container]'s -extended uses-allocator construction utilities like `uninitialized_construct_using_allocator` +extended [*uses-allocator construction] utilities (see [@https://www.boost.org/doc/libs/latest/doc/html/container/cpp_conformance.html Boost.Container]) -so that constructing objects that use shared-memory allocators is simplified. A -user that defines types taking advantage of the uses-allocator protocol: +so that constructing objects that use [*Boost.Interprocess] allocators is simplified. As a result a user: -* Does not longer need to explicitly pass allocator arguments when constructing an - object and its subjobects. - -* [*Boost.Inteprocess] allocators' `construct` operations, in cooperation with [*Boost.Container] containers +* Does not longer need to explicitly pass allocator arguments (or `segment_manager*` arguments that are convertible + to allocators) when constructing an object and its subobjects. +* [*Boost.Inteprocess] allocators' `construct` methods, in cooperation with [*Boost.Container] containers and uses-allocator utilities, take advantage of the protocol to automatically propagate the state - of the allocator to the compatible types stored in those containers. - Containers of containers automatically propagate the state recursively. + of the allocator to the uses_allocator compatible types stored in those containers. +* Containers of containers automatically propagate the allocator recursively without the user explicitly needing to do so. + +More formally, a type `T` is compatible with the [*Boost.Interprocess] `uses_allocator` protocol for a managed segment `MS` if: + +* Defines `T::allocator_type` as one of [*Boost.Interprocess] allocator types and + uses one of the following conventions when constructed from an argument list `args...` + * The leading-allocator convention: `T` is constructible as `T(allocator_arg, alloc, args...)` --> + * The trailing-allocator convention `T` is constructible as `T(args..., alloc)`. If a managed memory segment's construction utility takes the arguments `par1, par2` to construct a type named `MyType`, then `MyType` instances are constructed as follows: @@ -3652,6 +3635,169 @@ process if that process is inserting elements in a shared memory vector. [endsect] +[section:managed_memory_segment_object_information Obtaining information about a constructed object] + +Once an object is constructed using `construct<>` function family, the +programmer can obtain information about the object using a pointer to the +object. The programmer can obtain the following information: + +* Name of the object: If it's a named instance, the name used in the construction + function is returned, otherwise 0 is returned. + +* Length of the object: Returns the number of elements of the object (1 if it's + a single value, >=1 if it's an array). + +* The type of construction: Whether the object was constructed using a named, + unique or anonymous construction. + +Here is an example showing this functionality: + +[import ../example/doc_managed_construction_info.cpp] +[doc_managed_construction_info] + +[endsect] + +[endsect] + +[section:managed_memory_segment_advanced_features Managed Memory Segment Advanced Features] + +[section:allocate_deallocate Allocating fragments of a managed memory segment] + +If a basic raw-byte allocation is needed from a managed memory +segment, (for example, a managed shared memory), to implement +top-level interprocess communications, this class offers +[*allocate] and [*deallocate] functions. The allocation function +comes with throwing and no throwing versions. Throwing version throws +boost::interprocess::bad_alloc (which derives from `std::bad_alloc`) +if there is no more memory and the non-throwing version returns 0 pointer. + +[import ../example/doc_managed_raw_allocation.cpp] +[doc_managed_raw_allocation] + +[endsect] + +[section:managed_memory_segment_segment_manager Segment Manager] + +All [*Boost.Interprocess] managed memory segment classes construct in their +respective memory segments (shared memory, memory mapped files, heap memory...) +some structures to implement the memory management algorithm, named allocations, +synchronization objects... All these objects are encapsulated in a single object +called [*segment manager]. A managed memory mapped file and a managed shared +memory use the same [*segment manager] to implement all managed memory segment +features, due to the fact that a [*segment manager] is a class that manages +a fixed size memory buffer. Since both shared memory and memory mapped files +are accessed though a mapped region, and a mapped region is a fixed size +memory buffer, a single [*segment manager] class can manage several managed +memory segment types. + +Some [*Boost.Interprocess] classes require a pointer to the segment manager in +their constructors, and the segment manager can be obtained from any managed +memory segment using `get_segment_manager` member: + +[c++] + + managed_shared_memory::segment_manager *seg_manager = + managed_shm.get_segment_manager(); + +[endsect] + +[section:segment_offset Obtaining handles to identify data] + +The class also offers conversions between absolute addresses that belong to +a managed memory segment and a handle that can be passed using any +interprocess mechanism. That handle can be transformed again to an absolute +address using a managed memory segment that also contains that object. +Handles can be used as keys between processes to identify allocated portions +of a managed memory segment or objects constructed in the managed segment. + +[c++] + + //Process A obtains the offset of the address + managed_shared_memory::handle handle = + segment.get_handle_from_address(processA_address); + + //Process A sends this address using any mechanism to process B + + //Process B obtains the handle and transforms it again to an address + managed_shared_memory::handle handle = ... + void * processB_address = segment.get_address_from_handle(handle); + +[endsect] + +[section:managed_memory_segment_atomic_func Executing an object function atomically] + +Sometimes the programmer must execute some code, and needs to execute it with the +guarantee that no other process or thread will create or destroy any named, unique +or anonymous object while executing the functor. A user might want to create several +named objects and initialize them, but those objects should be available for the rest of processes +at once. + +To achieve this, the programmer can use the `atomic_func()` function offered by +managed classes: + +[c++] + + //This object function will create several named objects + create_several_objects_func func(/**/); + + //While executing the function, no other process will be + //able to create or destroy objects + managed_memory.atomic_func(func); + + +Note that `atomic_func` does not prevent other processes from allocating raw memory +or executing member functions for already constructed objects (e.g.: another process +might be pushing elements into a vector placed in the segment). The atomic function +only blocks named, unique and anonymous creation, search and destruction +(concurrent calls to `construct<>`, `find<>`, `find_or_construct<>`, `destroy<>`...) +from other processes. + +[endsect] + +[section:managed_memory_segment_information Obtaining information about the managed segment] + +These functions are available to obtain information about the managed memory segments: + +Obtain the size of the memory segment: + +[c++] + + managed_shm.get_size(); + +Obtain the number of free bytes of the segment: + +[c++] + + managed_shm.get_free_memory(); + +Clear to zero the free memory: + +[c++] + + managed_shm.zero_free_memory(); + +Know if all memory has been deallocated, false otherwise: + +[c++] + + managed_shm.all_memory_deallocated(); + +Test internal structures of the managed segment. Returns true +if no errors are detected: + +[c++] + + managed_shm.check_sanity(); + +Obtain the number of named and unique objects allocated in the segment: + +[c++] + + managed_shm.get_num_named_objects(); + managed_shm.get_num_unique_objects(); + +[endsect] + [section:index_types Index types for name/object mappings] As seen, managed memory segments, when creating named objects, store the name/object @@ -3706,131 +3852,6 @@ your own index type. To know how to do this, go to [endsect] -[section:managed_memory_segment_segment_manager Segment Manager] - -All [*Boost.Interprocess] managed memory segment classes construct in their -respective memory segments (shared memory, memory mapped files, heap memory...) -some structures to implement the memory management algorithm, named allocations, -synchronization objects... All these objects are encapsulated in a single object -called [*segment manager]. A managed memory mapped file and a managed shared -memory use the same [*segment manager] to implement all managed memory segment -features, due to the fact that a [*segment manager] is a class that manages -a fixed size memory buffer. Since both shared memory or memory mapped files -are accessed though a mapped region, and a mapped region is a fixed size -memory buffer, a single [*segment manager] class can manage several managed -memory segment types. - -Some [*Boost.Interprocess] classes require a pointer to the segment manager in -their constructors, and the segment manager can be obtained from any managed -memory segment using `get_segment_manager` member: - -[c++] - - managed_shared_memory::segment_manager *seg_manager = - managed_shm.get_segment_manager(); - -[endsect] - -[section:managed_memory_segment_information Obtaining information about a constructed object] - -Once an object is constructed using `construct<>` function family, the -programmer can obtain information about the object using a pointer to the -object. The programmer can obtain the following information: - -* Name of the object: If it's a named instance, the name used in the construction - function is returned, otherwise 0 is returned. - -* Length of the object: Returns the number of elements of the object (1 if it's - a single value, >=1 if it's an array). - -* The type of construction: Whether the object was constructed using a named, - unique or anonymous construction. - -Here is an example showing this functionality: - -[import ../example/doc_managed_construction_info.cpp] -[doc_managed_construction_info] - -[endsect] - -[section:managed_memory_segment_atomic_func Executing an object function atomically] - -Sometimes the programmer must execute some code, and needs to execute it with the -guarantee that no other process or thread will create or destroy any named, unique -or anonymous object while executing the functor. A user might want to create several -named objects and initialize them, but those objects should be available for the rest of processes -at once. - -To achieve this, the programmer can use the `atomic_func()` function offered by -managed classes: - -[c++] - - //This object function will create several named objects - create_several_objects_func func(/**/); - - //While executing the function, no other process will be - //able to create or destroy objects - managed_memory.atomic_func(func); - - -Note that `atomic_func` does not prevent other processes from allocating raw memory -or executing member functions for already constructed objects (e.g.: another process -might be pushing elements into a vector placed in the segment). The atomic function -only blocks named, unique and anonymous creation, search and destruction -(concurrent calls to `construct<>`, `find<>`, `find_or_construct<>`, `destroy<>`...) -from other processes. - -[endsect] - -[endsect] - -[section:managed_memory_segment_advanced_features Managed Memory Segment Advanced Features] - -[section:managed_memory_segment_information Obtaining information about the managed segment] - -These functions are available to obtain information about the managed memory segments: - -Obtain the size of the memory segment: - -[c++] - - managed_shm.get_size(); - -Obtain the number of free bytes of the segment: - -[c++] - - managed_shm.get_free_memory(); - -Clear to zero the free memory: - -[c++] - - managed_shm.zero_free_memory(); - -Know if all memory has been deallocated, false otherwise: - -[c++] - - managed_shm.all_memory_deallocated(); - -Test internal structures of the managed segment. Returns true -if no errors are detected: - -[c++] - - managed_shm.check_sanity(); - -Obtain the number of named and unique objects allocated in the segment: - -[c++] - - managed_shm.get_num_named_objects(); - managed_shm.get_num_unique_objects(); - -[endsect] - [section:growing_managed_memory Growing managed segments] Once a managed segment is created the managed segment can't be grown. The limitation @@ -4664,7 +4685,7 @@ pool is used for each node size. This is not possible if you try to share a node allocator between processes. To achieve this sharing [classref boost::interprocess::node_allocator node_allocator] uses the segment manager's unique type allocation service -(see [link interprocess.managed_memory_segments.managed_memory_segment_features.unique Unique instance construction] section). +(see [link interprocess.managed_memory_segments.managed_memory_segment_object_construction.unique Unique instance construction] section). In the initialization, a [classref boost::interprocess::node_allocator node_allocator]