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