1[/ 2 Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com) 3 4 Distributed under the Boost Software License, Version 1.0. (See accompanying 5 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6 7 Official repository: https://github.com/cppalliance/json 8] 9 10[/-----------------------------------------------------------------------------] 11 12[section storage_ptr] 13 14Variable-length containers in this library all use dynamically allocated 15memory to store their contents. Callers can gain control over the strategy 16used for allocation by specifying a __storage_ptr__ in select constructors 17and function parameter lists. A __storage_ptr__ has these properties: 18 19* A storage pointer always points to a valid, 20 type-erased __memory_resource__. 21 22* Default-constructed storage pointers reference the 23 ['default resource], an implementation-defined instance 24 which always uses the equivalent of global operator new 25 and delete. 26 27* Storage pointers constructed from a 28 [link json.ref.boost__json__memory_resource `memory_resource*`] 29 or __polymorphic_allocator__ do not acquire ownership; the 30 caller is responsible for ensuring that the lifetime of 31 the resource extends until it is no longer referenced. 32 33* A storage pointer obtained from __make_shared_resource__ 34 acquires shared ownership of the memory resource; the 35 lifetime of the resource is extended until all copies 36 of the storage pointer are destroyed. 37 38* The storage pointer remembers the value of 39 __is_deallocate_trivial__ before type-erasing the resource, 40 allowing the value to be queried at run-time. 41 42This lists all of the allocation-related types and functions 43available when using the library: 44 45[table Functions and Types 46[ [Name] [Description] ] 47[ 48 [__get_null_resource__] 49 [ 50 Returns a pointer to a memory resource instance which 51 always throws an exception upon allocation. This is 52 used to to achieve the invariant that no parsing or 53 container operation will dynamically allocate memory. 54 ] 55][ 56 [__is_deallocate_trivial__] 57 [ 58 A customization point allowing a memory resource type 59 to indicate that calls to deallocate are trivial. 60 ] 61][ 62 [__make_shared_resource__] 63 [ 64 A function returning a smart pointer with shared 65 ownership of a newly allocated memory resource. 66 ] 67][ 68 [__memory_resource__] 69 [ 70 The abstract base class representing an allocator. 71 ] 72][ 73 [__monotonic_resource__] 74 [ 75 A memory resource which allocates large blocks of memory and 76 has a trivial deallocate function. Allocated memory is not 77 freed until the resource is destroyed, making it fast for 78 parsing but not suited for performing modifications. 79 ] 80][ 81 [__polymorphic_allocator__] 82 [ 83 An __Allocator__ which uses a reference to a 84 __memory_resource__ to perform allocations. 85 ] 86][ 87 [__static_resource__] 88 [ 89 A memory resource that uses a single caller provided 90 buffer. No dynamic allocations are used. This is fast for 91 parsing but not suited for performing modifications. 92 ] 93][ 94 [__storage_ptr__] 95 [ 96 A smart pointer through which a __memory_resource__ 97 is managed and accessed. 98 ] 99]] 100 101[/-----------------------------------------------------------------------------] 102 103[heading Default Memory Resource] 104 105The ['default memory resource] wraps calls to the global heap allocation 106functions. This resource is not reference counted and has a non-trivial 107deallocate function. All default-constructed __storage_ptr__ reference 108the same default memory resource: 109 110[doc_storage_ptr_1] 111 112Default-constructed library containers use the default memory resource: 113 114[doc_storage_ptr_2] 115 116The default memory resource is well suited for general usage. It offers 117reasonable performance for parsing, and conservative memory usage for 118modification of the contents of containers. 119 120[/-----------------------------------------------------------------------------] 121 122[heading Monotonic Resource] 123 124Consider the pattern of memory allocation during parsing: when an array, 125object, or string is encountered the parser accumulates elements in its 126temporary storage area. When all of the elements are known, a single 127memory allocation is requested from the resource when constructing 128the value. Thus, parsing only allocates and constructs containers 129at their final size. Memory is not reallocated; that is, a memory 130buffer never needs to grow by allocating a new larger buffer and 131deallocating the previous buffer. 132 133The __monotonic_resource__ optimizes this memory allocation pattern by 134allocating increasingly large blocks of global memory internally and 135parceling those blocks out in smaller pieces to fulfill allocation 136requests. It has a trivial deallocate function. The monotonic resource 137does not actually deallocate memory until the resource is destroyed. 138Thus, it is ideally suited for the use-case where JSON is parsed, 139and the resulting value is then inspected but not modified. 140 141The resource to use when constructing values may be specified in calls 142to __parse__ as shown here: 143 144[doc_storage_ptr_3] 145 146Or, to parse into a value with shared ownership of the memory resource: 147 148[doc_storage_ptr_4] 149 150A monotonic resource may be optionally constructed with an initial buffer 151to use first, before going to the heap. This allows the caller to use 152stack space and avoid dynamic allocations for most parsed JSON, falling 153back to dynamic allocation from the heap if the input JSON is larger than 154average, as shown here: 155 156[doc_storage_ptr_5] 157 158[/-----------------------------------------------------------------------------] 159 160[heading Static Resource] 161 162A __static_resource__ constructs from a caller-provided buffer, and satisfies 163all memory allocation requests from the buffer. Once the buffer is exhausted, 164subsequent calls to allocate throw the exception `std::bad_alloc`. The 165resource offers a simple invariant: dynamic heap allocations are never 166performed. 167 168To use the resource, construct it with a local buffer: 169 170[doc_storage_ptr_6] 171 172[/-----------------------------------------------------------------------------] 173 174[heading Null Resource] 175 176The function __get_null_resource__ returns a global instance of the 177null resource. This resource offers a simple invariant: all calls to 178allocate will throw the exception `std::bad_alloc`. An instance of 179the null resource can be used to make parsing guarantee that 180allocations from the heap are never made. This is explored 181in more detail in a later section. 182 183[/-----------------------------------------------------------------------------] 184 185[heading Allocator Propagation] 186 187The containers __array__, __object__, and __value__ all propagate the 188memory resource they were constructed with to child elements: 189 190[doc_storage_ptr_7] 191 192This propagation acts recursively, containers within containers will 193all have the resource propagated. Once a container is constructed, 194its memory resource can never be changed. 195 196[/-----------------------------------------------------------------------------] 197 198[heading Resource Lifetime] 199 200It is important to note that __storage_ptr__ supports both 201shared-ownership and reference lifetime models. Construction 202from a memory resource pointer does not transfer ownership: 203 204[doc_storage_ptr_8] 205 206When using a memory resource in this fashion, including the case 207where a storage pointer or container is constructed from a 208__polymorphic_allocator__, the caller must ensure that the 209lifetime of the resource is extended until it is no longer 210referenced by any variables; otherwise, undefined behavior 211is possible. 212 213Shared ownership is achieved using the function __make_shared_resource__, 214which creates a new, reference-counted memory resource using a dynamic memory 215allocation and returns it as a __storage_ptr__: 216 217[doc_storage_ptr_9] 218 219When a storage pointer is constructed this way, the lifetime of 220the referenced memory resource is extended until all variables which 221reference it are destroyed. 222 223[heading User-Defined Resource] 224 225To implement custom memory allocation strategies, derive your class 226from __memory_resource__ and implement the functions `do_allocate`, 227`do_deallocate`, and `do_is_equal` as seen in this example below, 228which logs each operation it performs to the console: 229 230[doc_storage_ptr_10] 231 232[endsect] 233