mirror of
https://github.com/boostorg/json.git
synced 2025-05-10 09:43:52 +00:00
Add null_resource
This commit is contained in:
parent
fc0be9173c
commit
8bf9ebfd1b
@ -144,6 +144,11 @@ storage, improving performance.
|
||||
|
||||
[doc_quick_look_11]
|
||||
|
||||
With strategic use of the right memory resources, parser instance,
|
||||
and calculated upper limits on buffer sizes, it is possible to parse
|
||||
and examine JSON without ['any] dynamic memory allocations. This is
|
||||
explored in more detail in a later section.
|
||||
|
||||
[/-----------------------------------------------------------------------------]
|
||||
|
||||
[h5 Serializing]
|
||||
|
@ -112,9 +112,9 @@ It is desired to create a single type `T` with the following properties:
|
||||
* `T` supports both shared ownership, and non-ownership
|
||||
* `T` interoperates with code already using `std::pmr`
|
||||
|
||||
The __storage_ptr__ smart pointer container used in Boost.JSON builds
|
||||
and improves upon C++17's memory allocation interfaces, accomplishing
|
||||
the goals above. As a result, libraries which use this type compose
|
||||
The __storage_ptr__ used in Boost.JSON builds and improves
|
||||
upon C++17's memory allocation interfaces, accomplishing the
|
||||
goals above. As a result, libraries which use this type compose
|
||||
more easily and enjoy faster compilation, as container function
|
||||
definitions can be out-of-line.
|
||||
|
||||
@ -124,28 +124,50 @@ definitions can be out-of-line.
|
||||
|
||||
[section:storage_ptr The __storage_ptr__]
|
||||
|
||||
Instances of __value__, __object__, __array__, and __string__ all use
|
||||
dynamically allocated memory. To allow callers to control the strategy
|
||||
used to allocate and deallocate memory, the library provides the smart
|
||||
pointer container __storage_ptr__, similar in function to the C++ standard
|
||||
library's polymorphic allocator but with the following additional features:
|
||||
Variable-length containers in this library all use dynamically allocated
|
||||
memory to store their contents. Callers can gain control over the strategy
|
||||
used for allocation by specifying a __storage_ptr__ in select constructors
|
||||
and function parameter lists. A __storage_ptr__ has these properties:
|
||||
|
||||
* __storage_ptr__ can either function as a reference counted smart pointer or
|
||||
a reference wrapper around a __memory_resource__, allowing for the lifetime of
|
||||
the managed object to be extended.
|
||||
* A storage pointer always points to a valid,
|
||||
type-erased __memory_resource__.
|
||||
|
||||
* An implementation can indicate to the library that deallocation
|
||||
is not necessary, allowing destructor calls to be elided in certain situations.
|
||||
* Default-constructed storage pointers reference the
|
||||
['default resource], an implementation-defined instance
|
||||
which always uses the equivalent of global operator new
|
||||
and delete.
|
||||
|
||||
These types and functions are available:
|
||||
* Storage pointers constructed from a
|
||||
[link json.ref.boost__json__memory_resource `memory_resource*`]
|
||||
or __polymorphic_allocator__ do not acquire ownership; the
|
||||
caller is responsible for ensuring that the lifetime of
|
||||
the resource extends until it is no longer referenced.
|
||||
|
||||
* A storage pointer obtained from __make_counted_resource__
|
||||
acquires shared ownership of the memory resource; the
|
||||
lifetime of the resource is extended until all copies
|
||||
of the storage pointer are destroyed.
|
||||
|
||||
* The storage pointer remembers the value of
|
||||
__is_deallocate_trivial__ before type-erasing the resource,
|
||||
allowing the value to be queried at run-time.
|
||||
|
||||
This lists all of the allocation-related types and functions
|
||||
available when using the library:
|
||||
|
||||
[table Functions and Types
|
||||
[ [Name] [Description] ]
|
||||
[
|
||||
[__is_deallocate_trivial__]
|
||||
[
|
||||
A customization point allowing a memory resource type
|
||||
to indicate that calls to deallocate are trivial.
|
||||
]
|
||||
][
|
||||
[__make_counted_resource__]
|
||||
[
|
||||
A function that returns a reference-counted storage pointer
|
||||
with ownership of a new, dynamically allocated memory resource.
|
||||
A function returning a smart pointer with shared
|
||||
ownership of a newly allocated memory resource.
|
||||
]
|
||||
][
|
||||
[__memory_resource__]
|
||||
@ -155,26 +177,41 @@ These types and functions are available:
|
||||
][
|
||||
[__monotonic_resource__]
|
||||
[
|
||||
A memory resource that allocates zero or more blocks of memory
|
||||
from which allocations are made; block is twice as large as the last.
|
||||
Allocated memory is not freed until the resource is destroyed, making
|
||||
it fast for parsing but not ideal for mutation.
|
||||
A memory resource which allocates large blocks of memory and
|
||||
has a trivial deallocate function. Allocated memory is not
|
||||
freed until the resource is destroyed, making it fast for
|
||||
parsing but not suited for performing modifications.
|
||||
]
|
||||
][
|
||||
[__null_resource__]
|
||||
[
|
||||
A memory resource always throws an exception upon allocation.
|
||||
This is used to to achieve the invariant that no parsing
|
||||
or container operation will dynamically allocate memory.
|
||||
]
|
||||
][
|
||||
[__polymorphic_allocator__]
|
||||
[
|
||||
An __Allocator__ which uses a reference to a
|
||||
__memory_resource__ to perform allocations.
|
||||
]
|
||||
][
|
||||
[__static_resource__]
|
||||
[
|
||||
A memory resource that uses a single caller provided
|
||||
buffer, from which individual allocations are made.
|
||||
No dynamic allocations are used.
|
||||
buffer. No dynamic allocations are used. This is fast for
|
||||
parsing but not suited for performing modifications.
|
||||
]
|
||||
][
|
||||
[__storage_ptr__]
|
||||
[
|
||||
A smart pointer container through which a __memory_resource__
|
||||
A smart pointer through which a __memory_resource__
|
||||
is managed and accessed.
|
||||
]
|
||||
]]
|
||||
|
||||
[heading Default Resource]
|
||||
|
||||
The library provides a ['default memory resource] object which wraps calls to the
|
||||
global allocation and deallocation functions (`operator new` and `operator delete`).
|
||||
This memory resource is not reference counted, and requires calls to deallocate to
|
||||
|
@ -58,14 +58,14 @@
|
||||
[def __key_value_pair__ [link json.ref.boost__json__key_value_pair `key_value_pair`]]
|
||||
[def __kind__ [link json.ref.boost__json__kind `kind`]]
|
||||
[def __make_counted_resource__ [link json.ref.boost__json__make_counted_resource `make_counted_resource`]]
|
||||
[def __number__ [link json.ref.boost__json__number `number`]]
|
||||
[def __memory_resource__ [link json.ref.boost__json__memory_resource `memory_resource`]]
|
||||
[def __monotonic_resource__ [link json.ref.boost__json__monotonic_resource `monotonic_resource`]]
|
||||
[def __null_resource__ [link json.ref.boost__json__null_resource `null_resource`]]
|
||||
[def __object__ [link json.ref.boost__json__object `object`]]
|
||||
[def __parse__ [link json.ref.boost__json__parse `parse`]]
|
||||
[def __parser__ [link json.ref.boost__json__parser `parser`]]
|
||||
[def __parse_options__ [link json.ref.boost__json__parse_options `parse_options`]]
|
||||
[def __polymorphic_allocator__ [link json.ref.boost__json__polymorphic_allocator `polymorphic_allocator`]]
|
||||
[def __memory_resource__ [link json.ref.boost__json__memory_resource `memory_resource`]]
|
||||
[def __monotonic_resource__ [link json.ref.boost__json__monotonic_resource `monotonic_resource`]]
|
||||
[def __serialize__ [link json.ref.boost__json__serialize `serialize`]]
|
||||
[def __serializer__ [link json.ref.boost__json__serializer `serializer`]]
|
||||
[def __static_resource__ [link json.ref.boost__json__static_resource `static_resource`]]
|
||||
@ -95,15 +95,6 @@
|
||||
|
||||
[/-----------------------------------------------------------------------------]
|
||||
|
||||
[import ../../example/pretty.cpp]
|
||||
[import ../../example/validate.cpp]
|
||||
[import ../../include/boost/json/impl/serialize.ipp]
|
||||
[import ../../test/doc_quick_look.cpp]
|
||||
[import ../../test/memory_resource.cpp]
|
||||
[import ../../test/snippets.cpp]
|
||||
|
||||
[/-----------------------------------------------------------------------------]
|
||||
|
||||
Boost.JSON is a portable C++ library which implements the
|
||||
[@https://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf JSON Data Interchange Syntax],
|
||||
providing algorithms for parsing and serialization, as well as a robust
|
||||
@ -149,6 +140,16 @@ in memory.
|
||||
]]
|
||||
]
|
||||
|
||||
[/-----------------------------------------------------------------------------]
|
||||
|
||||
[import ../../example/pretty.cpp]
|
||||
[import ../../example/validate.cpp]
|
||||
[import ../../include/boost/json/impl/serialize.ipp]
|
||||
[import ../../test/doc_allocators.cpp]
|
||||
[import ../../test/doc_quick_look.cpp]
|
||||
[import ../../test/memory_resource.cpp]
|
||||
[import ../../test/snippets.cpp]
|
||||
|
||||
[include 01_overview.qbk]
|
||||
[include 02_00_usage.qbk]
|
||||
[include 03_examples.qbk]
|
||||
|
@ -24,6 +24,7 @@
|
||||
<member><link linkend="json.ref.boost__json__basic_parser">basic_parser</link></member>
|
||||
<member><link linkend="json.ref.boost__json__key_value_pair">key_value_pair</link></member>
|
||||
<member><link linkend="json.ref.boost__json__monotonic_resource">monotonic_resource</link></member>
|
||||
<member><link linkend="json.ref.boost__json__null_resource">null_resource</link></member>
|
||||
<member><link linkend="json.ref.boost__json__object">object</link></member>
|
||||
<member><link linkend="json.ref.boost__json__parser">parser</link></member>
|
||||
<member><link linkend="json.ref.boost__json__parse_options">parse_options</link></member>
|
||||
|
@ -15,11 +15,15 @@
|
||||
#include <boost/json/array.hpp>
|
||||
#include <boost/json/error.hpp>
|
||||
#include <boost/json/kind.hpp>
|
||||
#include <boost/json/memory_resource.hpp>
|
||||
#include <boost/json/monotonic_resource.hpp>
|
||||
#include <boost/json/null_resource.hpp>
|
||||
#include <boost/json/number_cast.hpp>
|
||||
#include <boost/json/object.hpp>
|
||||
#include <boost/json/parse.hpp>
|
||||
#include <boost/json/parse_options.hpp>
|
||||
#include <boost/json/parser.hpp>
|
||||
#include <boost/json/pilfer.hpp>
|
||||
#include <boost/json/serialize.hpp>
|
||||
#include <boost/json/serializer.hpp>
|
||||
#include <boost/json/static_resource.hpp>
|
||||
@ -28,6 +32,8 @@
|
||||
#include <boost/json/system_error.hpp>
|
||||
#include <boost/json/value.hpp>
|
||||
#include <boost/json/value_from.hpp>
|
||||
#include <boost/json/value_ref.hpp>
|
||||
#include <boost/json/value_stack.hpp>
|
||||
#include <boost/json/value_to.hpp>
|
||||
|
||||
// Intentionally excluded
|
||||
|
48
include/boost/json/impl/null_resource.ipp
Normal file
48
include/boost/json/impl/null_resource.ipp
Normal file
@ -0,0 +1,48 @@
|
||||
//
|
||||
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
|
||||
//
|
||||
// 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)
|
||||
//
|
||||
// Official repository: https://github.com/cppalliance/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_IMPL_NULL_RESOURCE_IPP
|
||||
#define BOOST_JSON_IMPL_NULL_RESOURCE_IPP
|
||||
|
||||
#include <boost/json/null_resource.hpp>
|
||||
#include <boost/json/detail/except.hpp>
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
|
||||
void*
|
||||
null_resource::
|
||||
do_allocate(
|
||||
std::size_t,
|
||||
std::size_t)
|
||||
{
|
||||
detail::throw_bad_alloc(
|
||||
BOOST_CURRENT_LOCATION);
|
||||
}
|
||||
|
||||
void
|
||||
null_resource::
|
||||
do_deallocate(
|
||||
void*,
|
||||
std::size_t,
|
||||
std::size_t)
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
bool
|
||||
null_resource::
|
||||
do_is_equal(
|
||||
memory_resource const& mr) const noexcept
|
||||
{
|
||||
return this == &mr;
|
||||
}
|
||||
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#endif
|
83
include/boost/json/null_resource.hpp
Normal file
83
include/boost/json/null_resource.hpp
Normal file
@ -0,0 +1,83 @@
|
||||
//
|
||||
// Copyright (c) 2020 Vinnie Falco (vinnie.falco@gmail.com)
|
||||
//
|
||||
// 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)
|
||||
//
|
||||
// Official repository: https://github.com/cppalliance/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_NULL_RESOURCE_HPP
|
||||
#define BOOST_JSON_NULL_RESOURCE_HPP
|
||||
|
||||
#include <boost/json/detail/config.hpp>
|
||||
#include <boost/json/memory_resource.hpp>
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
|
||||
//----------------------------------------------------------
|
||||
|
||||
/** A resource which always fails.
|
||||
|
||||
This memory resource always throws the exception
|
||||
`std::bad_alloc` in calls to `allocate`.
|
||||
*/
|
||||
class BOOST_JSON_CLASS_DECL
|
||||
null_resource final
|
||||
: public memory_resource
|
||||
{
|
||||
public:
|
||||
/// Copy constructor (deleted)
|
||||
null_resource(
|
||||
null_resource const&) = delete;
|
||||
|
||||
/// Copy assignment (deleted)
|
||||
null_resource& operator=(
|
||||
null_resource const&) = delete;
|
||||
|
||||
/// Destructor
|
||||
~null_resource() noexcept = default;
|
||||
|
||||
/** Constructor
|
||||
|
||||
This constructors the resource.
|
||||
|
||||
@par Complexity
|
||||
Constant.
|
||||
|
||||
@par Exception Safety
|
||||
No-throw guarantee.
|
||||
*/
|
||||
/** @{ */
|
||||
null_resource() noexcept = default;
|
||||
|
||||
protected:
|
||||
#ifndef BOOST_JSON_DOCS
|
||||
void*
|
||||
do_allocate(
|
||||
std::size_t n,
|
||||
std::size_t align) override;
|
||||
|
||||
void
|
||||
do_deallocate(
|
||||
void* p,
|
||||
std::size_t n,
|
||||
std::size_t align) override;
|
||||
|
||||
bool
|
||||
do_is_equal(
|
||||
memory_resource const& mr
|
||||
) const noexcept override;
|
||||
#endif
|
||||
};
|
||||
|
||||
template<>
|
||||
struct is_deallocate_trivial<
|
||||
null_resource>
|
||||
{
|
||||
static constexpr bool value = true;
|
||||
};
|
||||
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#endif
|
@ -31,6 +31,7 @@ in a translation unit of the program.
|
||||
#include <boost/json/impl/array.ipp>
|
||||
#include <boost/json/impl/error.ipp>
|
||||
#include <boost/json/impl/monotonic_resource.ipp>
|
||||
#include <boost/json/impl/null_resource.ipp>
|
||||
#include <boost/json/impl/object.ipp>
|
||||
#include <boost/json/impl/parse.ipp>
|
||||
#include <boost/json/impl/parser.ipp>
|
||||
|
@ -27,12 +27,14 @@ else
|
||||
local SOURCES =
|
||||
array.cpp
|
||||
basic_parser.cpp
|
||||
doc_allocators.cpp
|
||||
doc_quick_look.cpp
|
||||
error.cpp
|
||||
json.cpp
|
||||
kind.cpp
|
||||
monotonic_resource.cpp
|
||||
natvis.cpp
|
||||
null_resource.cpp
|
||||
number_cast.cpp
|
||||
object.cpp
|
||||
parse.cpp
|
||||
|
85
test/doc_allocators.cpp
Normal file
85
test/doc_allocators.cpp
Normal file
@ -0,0 +1,85 @@
|
||||
//
|
||||
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
|
||||
//
|
||||
// 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)
|
||||
//
|
||||
// Official repository: https://github.com/cppalliance/json
|
||||
//
|
||||
|
||||
#include <boost/json.hpp>
|
||||
|
||||
#include "test_suite.hpp"
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
|
||||
//[doc_allocators_1
|
||||
void do_rpc( string_view s )
|
||||
{
|
||||
// The parser will use this storage for its temporary needs
|
||||
unsigned char temp[ 4000 ];
|
||||
|
||||
// The null resource guarantees we will never dynamically allocate
|
||||
null_resource mr1;
|
||||
|
||||
// Construct a strict parser using the temp buffer and no dynamic memory
|
||||
parser p( &mr1, parse_options(), temp );
|
||||
|
||||
// Now we need a buffer to hold the actual JSON values
|
||||
unsigned char buf[ 6000 ];
|
||||
|
||||
// The static resource is monotonic, using only a caller-provided buffer
|
||||
static_resource mr2( buf );
|
||||
|
||||
// We need to catch any exceptions thrown by the two memory resources
|
||||
try
|
||||
{
|
||||
// This error code indicates errors not related to memory exhaustion
|
||||
error_code ec;
|
||||
|
||||
// Parse the entire string we received from the network client
|
||||
p.write( s, ec );
|
||||
|
||||
// Inform the parser that the complete input has been provided
|
||||
if(! ec )
|
||||
p.finish( ec );
|
||||
|
||||
if(! ec )
|
||||
{
|
||||
// Retrieve the value. It will use `buf` for storage.
|
||||
value jv = p.release();
|
||||
|
||||
// At this point we can inspect jv and perform the requested RPC.
|
||||
}
|
||||
else
|
||||
{
|
||||
// An error occurred. A real program would report the error
|
||||
// message back to the network client, indicating that the
|
||||
// received JSON was invalid.
|
||||
}
|
||||
|
||||
}
|
||||
catch(std::bad_alloc const&)
|
||||
{
|
||||
// The memory needed to parse this JSON exceeded our statically
|
||||
// define upper limits. A real program would send an error message
|
||||
// back to the network client informing that their JSON is too large.
|
||||
}
|
||||
}
|
||||
//]
|
||||
|
||||
//----------------------------------------------------------
|
||||
|
||||
class doc_allocators_test
|
||||
{
|
||||
public:
|
||||
void
|
||||
run()
|
||||
{
|
||||
BOOST_TEST_PASS();
|
||||
}
|
||||
};
|
||||
|
||||
TEST_SUITE(doc_allocators_test, "boost.json.doc_allocators");
|
||||
|
||||
BOOST_JSON_NS_END
|
45
test/null_resource.cpp
Normal file
45
test/null_resource.cpp
Normal file
@ -0,0 +1,45 @@
|
||||
//
|
||||
// Copyright (c) 2020 Vinnie Falco (vinnie.falco@gmail.com)
|
||||
//
|
||||
// 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)
|
||||
//
|
||||
// Official repository: https://github.com/cppalliance/json
|
||||
//
|
||||
|
||||
// Test that header file is self-contained.
|
||||
#include <boost/json/null_resource.hpp>
|
||||
|
||||
#include "test_suite.hpp"
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
|
||||
class null_resource_test
|
||||
{
|
||||
public:
|
||||
void
|
||||
test()
|
||||
{
|
||||
null_resource mr;
|
||||
BOOST_TEST_THROWS(
|
||||
mr.allocate(16),
|
||||
std::bad_alloc);
|
||||
char buf[128];
|
||||
// no-op
|
||||
mr.deallocate(&buf[0], 128);
|
||||
|
||||
BOOST_TEST(mr == mr);
|
||||
null_resource mr2;
|
||||
BOOST_TEST(mr != mr2);
|
||||
}
|
||||
|
||||
void
|
||||
run()
|
||||
{
|
||||
test();
|
||||
}
|
||||
};
|
||||
|
||||
TEST_SUITE(null_resource_test, "boost.json.null_resource");
|
||||
|
||||
BOOST_JSON_NS_END
|
Loading…
x
Reference in New Issue
Block a user