mirror of
https://github.com/boostorg/json.git
synced 2025-05-11 05:33:57 +00:00
null_resource is a singleton
This commit is contained in:
parent
7bde63b316
commit
a2917e736a
@ -158,6 +158,14 @@ available when using the library:
|
||||
[table Functions and Types
|
||||
[ [Name] [Description] ]
|
||||
[
|
||||
[__get_null_resource__]
|
||||
[
|
||||
Returns a pointer to a memory resource instance which
|
||||
always throws an exception upon allocation. This is
|
||||
used to to achieve the invariant that no parsing or
|
||||
container operation will dynamically allocate memory.
|
||||
]
|
||||
][
|
||||
[__is_deallocate_trivial__]
|
||||
[
|
||||
A customization point allowing a memory resource type
|
||||
@ -182,13 +190,6 @@ available when using the library:
|
||||
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__]
|
||||
[
|
||||
@ -285,11 +286,12 @@ To use the resource, construct it with a local buffer:
|
||||
|
||||
[heading Null Resource]
|
||||
|
||||
The __null_resource__ can only be default constructed. It offers a simple
|
||||
invariant: all calls to allocate will throw the exception `std::bad_alloc`.
|
||||
An instance of the null resource can be used to make parsing guarantee
|
||||
that allocations from the heap are never made. This is explored in more
|
||||
detail in a later section.
|
||||
The function __get_null_resource__ returns a global instance of the
|
||||
null resource. This resource offers a simple invariant: all calls to
|
||||
allocate will throw the exception `std::bad_alloc`. An instance of
|
||||
the null resource can be used to make parsing guarantee that
|
||||
allocations from the heap are never made. This is explored
|
||||
in more detail in a later section.
|
||||
|
||||
[/-----------------------------------------------------------------------------]
|
||||
|
||||
|
@ -52,6 +52,7 @@
|
||||
[def __error_code__ [link json.ref.boost__json__error_code `error_code`]]
|
||||
[def __error_condition__ [link json.ref.boost__json__error_condition `error_condition`]]
|
||||
[def __get__ [link json.ref.boost__json__get `get`]]
|
||||
[def __get_null_resource__ [link json.ref.boost__json__get_null_resource `get_null_resource`]]
|
||||
[def __has_value_from__ [link json.ref.boost__json__has_value_from `has_value_from`]]
|
||||
[def __has_value_to__ [link json.ref.boost__json__has_value_to `has_value_to`]]
|
||||
[def __is_deallocate_trivial__ [link json.ref.boost__json__is_deallocate_trivial `is_deallocate_trivial`]]
|
||||
@ -60,7 +61,6 @@
|
||||
[def __make_counted_resource__ [link json.ref.boost__json__make_counted_resource `make_counted_resource`]]
|
||||
[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 __number_cast__ [link json.ref.boost__json__number_cast `number_cast`]]
|
||||
[def __object__ [link json.ref.boost__json__object `object`]]
|
||||
[def __parse__ [link json.ref.boost__json__parse `parse`]]
|
||||
|
@ -24,7 +24,6 @@
|
||||
<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>
|
||||
@ -41,6 +40,7 @@
|
||||
<bridgehead renderas="sect3">Functions</bridgehead>
|
||||
<simplelist type="vert" columns="1">
|
||||
<member><link linkend="json.ref.boost__json__get">get</link></member>
|
||||
<member><link linkend="json.ref.boost__json__get_null_resource">get_null_resource</link></member>
|
||||
<member><link linkend="json.ref.boost__json__make_counted_resource">make_counted_resource</link></member>
|
||||
<member><link linkend="json.ref.boost__json__number_cast">number_cast</link></member>
|
||||
<member><link linkend="json.ref.boost__json__parse">parse</link></member>
|
||||
|
@ -67,8 +67,7 @@ struct FuzzHelper {
|
||||
void useDynLess() {
|
||||
// this is on the heap because the size is chosen dynamically
|
||||
std::unique_ptr<unsigned char[]> temp(new unsigned char[memlimit1]);
|
||||
null_resource nr;
|
||||
parser p(&nr,
|
||||
parser p(get_null_resource(),
|
||||
opt,
|
||||
temp.get(),
|
||||
memlimit1);
|
||||
|
@ -15,32 +15,85 @@
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
|
||||
void*
|
||||
null_resource::
|
||||
do_allocate(
|
||||
std::size_t,
|
||||
std::size_t)
|
||||
{
|
||||
detail::throw_bad_alloc(
|
||||
BOOST_CURRENT_LOCATION);
|
||||
}
|
||||
namespace detail {
|
||||
|
||||
void
|
||||
null_resource::
|
||||
do_deallocate(
|
||||
void*,
|
||||
std::size_t,
|
||||
std::size_t)
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
/** A resource which always fails.
|
||||
|
||||
bool
|
||||
null_resource::
|
||||
do_is_equal(
|
||||
memory_resource const& mr) const noexcept
|
||||
This memory resource always throws the exception
|
||||
`std::bad_alloc` in calls to `allocate`.
|
||||
*/
|
||||
class 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
|
||||
|
||||
This destroys the resource.
|
||||
|
||||
@par Complexity
|
||||
Constant.
|
||||
|
||||
@part Exception Safety
|
||||
No-throw guarantee.
|
||||
*/
|
||||
~null_resource() noexcept = default;
|
||||
|
||||
/** Constructor
|
||||
|
||||
This constructs the resource.
|
||||
|
||||
@par Complexity
|
||||
Constant.
|
||||
|
||||
@par Exception Safety
|
||||
No-throw guarantee.
|
||||
*/
|
||||
/** @{ */
|
||||
null_resource() noexcept = default;
|
||||
|
||||
protected:
|
||||
void*
|
||||
do_allocate(
|
||||
std::size_t,
|
||||
std::size_t) override
|
||||
{
|
||||
detail::throw_bad_alloc(
|
||||
BOOST_CURRENT_LOCATION);
|
||||
}
|
||||
|
||||
void
|
||||
do_deallocate(
|
||||
void*,
|
||||
std::size_t,
|
||||
std::size_t) override
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
bool
|
||||
do_is_equal(
|
||||
memory_resource const& mr
|
||||
) const noexcept override
|
||||
{
|
||||
return this == &mr;
|
||||
}
|
||||
};
|
||||
|
||||
} // detail
|
||||
|
||||
memory_resource*
|
||||
get_null_resource() noexcept
|
||||
{
|
||||
return this == &mr;
|
||||
static detail::null_resource mr;
|
||||
return &mr;
|
||||
}
|
||||
|
||||
BOOST_JSON_NS_END
|
||||
|
@ -15,77 +15,20 @@
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
|
||||
//----------------------------------------------------------
|
||||
|
||||
/** A resource which always fails.
|
||||
/** Return a pointer to the null resource.
|
||||
|
||||
This memory resource always throws the exception
|
||||
`std::bad_alloc` in calls to `allocate`.
|
||||
|
||||
@par Complexity
|
||||
Constant.
|
||||
|
||||
@par Exception Safety
|
||||
No-throw guarantee.
|
||||
*/
|
||||
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
|
||||
|
||||
This destroys the resource.
|
||||
|
||||
@par Complexity
|
||||
Constant.
|
||||
|
||||
@part Exception Safety
|
||||
No-throw guarantee.
|
||||
*/
|
||||
~null_resource() noexcept = default;
|
||||
|
||||
/** Constructor
|
||||
|
||||
This constructs 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_DECL
|
||||
memory_resource*
|
||||
get_null_resource() noexcept;
|
||||
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
|
@ -1053,7 +1053,14 @@ public:
|
||||
return *this = value(init, storage());
|
||||
}
|
||||
|
||||
/** Assignment.
|
||||
/** Assignment
|
||||
|
||||
Assigns `t` to `*this`.
|
||||
|
||||
@par Effects
|
||||
@code
|
||||
*this = value( std::forward<T>(t), this->storage() );
|
||||
@endcode
|
||||
|
||||
@par Constraints
|
||||
@code
|
||||
|
@ -195,9 +195,11 @@ parser p(
|
||||
template< class Handler >
|
||||
void do_rpc( string_view s, Handler&& handler )
|
||||
{
|
||||
null_resource mr1; // The null resource guarantees we will never dynamically allocate
|
||||
unsigned char temp[ 4096 ]; // The parser will use this storage for its temporary needs
|
||||
parser p( &mr1, parse_options(), temp ); // Construct a strict parser using the temp buffer and no dynamic memory
|
||||
parser p( // Construct a strict parser using the temp buffer and no dynamic memory
|
||||
get_null_resource(), // The null resource guarantees we will never dynamically allocate
|
||||
parse_options(), // Default constructed parse options allow only standard JSON
|
||||
temp );
|
||||
|
||||
unsigned char buf[ 16384 ]; // Now we need a buffer to hold the actual JSON values
|
||||
static_resource mr2( buf ); // The static resource is monotonic, using only a caller-provided buffer
|
||||
|
@ -10,6 +10,8 @@
|
||||
// Test that header file is self-contained.
|
||||
#include <boost/json/null_resource.hpp>
|
||||
|
||||
#include <boost/json/storage_ptr.hpp>
|
||||
|
||||
#include "test_suite.hpp"
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
@ -20,17 +22,15 @@ public:
|
||||
void
|
||||
test()
|
||||
{
|
||||
null_resource mr;
|
||||
auto& mr = *get_null_resource();
|
||||
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);
|
||||
BOOST_TEST(
|
||||
mr == *get_null_resource());
|
||||
}
|
||||
|
||||
void
|
||||
|
Loading…
x
Reference in New Issue
Block a user