Add block_storage default storage

This commit is contained in:
Vinnie Falco 2019-10-27 14:43:16 -07:00
parent 3aae726eb1
commit c99bec33ec
10 changed files with 234 additions and 6 deletions

View File

@ -114,7 +114,11 @@ public:
int repeat) const override
{
while(repeat--)
json::parse(s);
{
auto sp = json::make_storage<
json::block_storage>();
json::parse(s, sp);
}
}
void

View File

@ -14,6 +14,7 @@
#include <boost/json/assign_string.hpp>
#include <boost/json/assign_vector.hpp>
#include <boost/json/basic_parser.hpp>
#include <boost/json/block_storage.hpp>
#include <boost/json/error.hpp>
#include <boost/json/fixed_storage.hpp>
#include <boost/json/ieee_decimal.hpp>

View File

@ -0,0 +1,141 @@
//
// Copyright (c) 2018-2019 Vinnie Falco (vinnie dot falco at gmail dot 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/vinniefalco/json
//
#ifndef BOOST_JSON_BLOCK_STORAGE_HPP
#define BOOST_JSON_BLOCK_STORAGE_HPP
#include <boost/json/detail/config.hpp>
#include <boost/json/detail/assert.hpp>
#include <boost/json/storage.hpp>
#include <cstddef>
#include <memory>
#include <stdexcept>
namespace boost {
namespace json {
/** A storage which uses a multiple fixed size blocks
*/
class block_storage : public storage
{
struct block
{
std::size_t const size;
std::size_t used;
block* next;
char*
begin() noexcept
{
return reinterpret_cast<
char*>(this+1);
}
char*
end() noexcept
{
return begin() + size;
}
};
std::size_t const block_size_;
std::size_t refs_ = 0;
block* head_ = nullptr;
public:
~block_storage()
{
std::allocator<block> a;
auto b = head_;
while(b)
{
auto next = b->next;
a.deallocate(b,
sizeof(*b) + b->size);
b = next;
}
}
explicit
block_storage(
std::size_t block_size = 256 * 1024)
: block_size_(block_size)
{
}
private:
block&
alloc_block(std::size_t size)
{
std::allocator<block> a;
auto const n = (
size + sizeof(block) - 1) /
sizeof(block);
auto& b = *::new(
a.allocate(n + 1)) block{
n * sizeof(block),
0,
head_};
head_ = &b;
return b;
}
void*
do_allocate(
std::size_t n,
std::size_t align) override
{
(void)align;
// must be power of 2
BOOST_JSON_ASSERT(
(align & (align - 1)) == 0);
// cannot exceed max alignment
BOOST_JSON_ASSERT(
align <= sizeof(std::max_align_t));
auto const needed =
[&]
{
if(n < block_size_)
return block_size_;
return n + sizeof(block);
};
if(head_)
{
auto const avail =
head_->size - head_->used;
if(avail < n)
alloc_block(needed());
}
else
{
alloc_block(needed());
}
++refs_;
auto p =
head_->begin() + head_->used;
head_->used += n;
return p;
}
void
do_deallocate(
void*,
std::size_t,
std::size_t) noexcept override
{
if(--refs_ > 0)
return;
//clear();
}
};
} // json
} // boost
#endif

View File

@ -11,7 +11,10 @@
#define BOOST_JSON_FIXED_STORAGE_HPP
#include <boost/json/detail/config.hpp>
#include <boost/json/detail/assert.hpp>
#include <boost/json/storage.hpp>
#include <cstddef>
#include <memory>
#include <stdexcept>
namespace boost {
@ -21,22 +24,32 @@ namespace json {
*/
class fixed_storage : public storage
{
char* const base_;
std::size_t const size_;
char* const base_;
std::size_t used_ = 0;
std::size_t refs_ = 0;
public:
~fixed_storage()
{
delete[] base_;
std::allocator<
char>{}.deallocate(base_, size_);
}
explicit
fixed_storage(
std::size_t bytes)
: base_(new char[bytes])
, size_(bytes)
: size_(
[bytes]
{
auto const align =
sizeof(std::max_align_t) - 1;
if(bytes & align)
return bytes | align;
return bytes;
}())
, base_(std::allocator<
char>{}.allocate(size_))
{
}
@ -46,6 +59,7 @@ protected:
std::size_t n,
std::size_t align) override
{
(void)align;
// must be power of 2
BOOST_JSON_ASSERT(
(align & (align - 1)) == 0);

View File

@ -12,6 +12,7 @@
#include <boost/json/parser.hpp>
#include <boost/json/error.hpp>
#include <boost/json/block_storage.hpp>
#include <boost/json/detail/assert.hpp>
#include <stdexcept>
#include <utility>
@ -54,6 +55,8 @@ parser::
parser::
parser()
: jv_(make_storage<
block_storage>())
{
}

View File

@ -14,7 +14,6 @@
#include <boost/json/basic_parser.hpp>
#include <boost/json/storage.hpp>
#include <boost/json/value.hpp>
#include <boost/json/storage.hpp>
#include <boost/json/detail/string.hpp>
#include <new>
#include <string>

View File

@ -34,7 +34,9 @@ add_executable (json-tests
assign_string.cpp
assign_vector.cpp
basic_parser.cpp
block_storage.cpp
error.cpp
fixed_storage.cpp
ieee_decimal.cpp
json.cpp
kind.cpp

View File

@ -30,7 +30,9 @@ local SOURCES =
assign_string.cpp
assign_vector.cpp
basic_parser.cpp
block_storage.cpp
error.cpp
fixed_storage.cpp
ieee_decimal.cpp
json.cpp
kind.cpp

31
test/block_storage.cpp Normal file
View File

@ -0,0 +1,31 @@
//
// Copyright (c) 2018-2019 Vinnie Falco (vinnie dot falco at gmail dot 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/vinniefalco/json
//
// Test that header file is self-contained.
#include <boost/json/block_storage.hpp>
#include <boost/beast/_experimental/unit_test/suite.hpp>
namespace boost {
namespace json {
class block_storage_test : public beast::unit_test::suite
{
public:
void run() override
{
make_storage<block_storage>();
pass();
}
};
BEAST_DEFINE_TESTSUITE(boost,json,block_storage);
} // json
} // boost

31
test/fixed_storage.cpp Normal file
View File

@ -0,0 +1,31 @@
//
// Copyright (c) 2018-2019 Vinnie Falco (vinnie dot falco at gmail dot 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/vinniefalco/json
//
// Test that header file is self-contained.
#include <boost/json/fixed_storage.hpp>
#include <boost/beast/_experimental/unit_test/suite.hpp>
namespace boost {
namespace json {
class fixed_storage_test : public beast::unit_test::suite
{
public:
void run() override
{
make_storage<fixed_storage>(65536);
pass();
}
};
BEAST_DEFINE_TESTSUITE(boost,json,fixed_storage);
} // json
} // boost