From ec197d4bcef3da3965d2fbf515b105383965993a Mon Sep 17 00:00:00 2001 From: Vinnie Falco Date: Fri, 27 Sep 2019 15:06:30 -0700 Subject: [PATCH] Support pilfer construction --- bench/bench.cpp | 44 +++++++++++++++++------------- include/boost/json/array.hpp | 4 +++ include/boost/json/impl/array.ipp | 15 ++++++++-- include/boost/json/impl/object.ipp | 8 ++++++ include/boost/json/impl/value.ipp | 42 ++++++++++++++++++++++++++++ include/boost/json/object.hpp | 4 +++ include/boost/json/value.hpp | 5 ++++ 7 files changed, 101 insertions(+), 21 deletions(-) diff --git a/bench/bench.cpp b/bench/bench.cpp index aa920e43..060cfd43 100644 --- a/bench/bench.cpp +++ b/bench/bench.cpp @@ -50,7 +50,14 @@ public: class boost_impl : public any_impl { + json::parser* p_; + public: + boost_impl() + : p_(new json::parser) + { + } + boost::string_view name() const noexcept override { @@ -61,9 +68,8 @@ public: parse( boost::string_view s) override { - json::parser p; boost::system::error_code ec; - p.write({s.data(), s.size()}, ec); + p_->write({s.data(), s.size()}, ec); } }; @@ -337,23 +343,20 @@ benchParse( boost::string_view doc, any_impl& impl) { - for(int i = 0; i < 10; ++i) - { - using clock_type = std::chrono::steady_clock; - auto const when = clock_type::now(); - dout << impl.name(); - impl.parse(doc); - auto const elapsed = - std::chrono::duration_cast< - std::chrono::milliseconds>( - clock_type::now() - when); - dout << - " parse " << - doc.size() << " bytes" - " in " << elapsed.count() << "ms" << - "\n"; - dout.flush(); - } + using clock_type = std::chrono::steady_clock; + auto const when = clock_type::now(); + dout << impl.name(); + impl.parse(doc); + auto const elapsed = + std::chrono::duration_cast< + std::chrono::milliseconds>( + clock_type::now() - when); + dout << + " parse " << + doc.size() << " bytes" + " in " << elapsed.count() << "ms" << + "\n"; + dout.flush(); } int @@ -368,15 +371,18 @@ main(int argc, char** argv) f.max_depth(i); auto const doc = f.make_document(); #if 0 + for(int j = 0; j < 10; ++j) { rapidjson_impl impl; benchParse(doc, impl); } + for(int j = 0; j < 10; ++j) { nlohmann_impl impl; benchParse(doc, impl); } #endif + for(int j = 0; j < 10; ++j) { boost_impl impl; benchParse(doc, impl); diff --git a/include/boost/json/array.hpp b/include/boost/json/array.hpp index abbfc906..5cdf729a 100644 --- a/include/boost/json/array.hpp +++ b/include/boost/json/array.hpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -105,6 +106,9 @@ public: BOOST_JSON_DECL array(array&& other) noexcept; + BOOST_JSON_DECL + array(pilfered other) noexcept; + BOOST_JSON_DECL array( array&& other, diff --git a/include/boost/json/impl/array.ipp b/include/boost/json/impl/array.ipp index a485149c..436aa8ae 100644 --- a/include/boost/json/impl/array.ipp +++ b/include/boost/json/impl/array.ipp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -220,6 +221,14 @@ array(array&& other) noexcept { } +array:: +array(pilfered other) noexcept + : tab_(boost::exchange( + other.get().tab_, nullptr)) + , sp_(other.get().sp_) +{ +} + array:: array( array&& other, @@ -497,10 +506,12 @@ reserve(size_type new_capacity) } for(size_type i = 0; i < tab_->size; ++i) - ::new(&tab->begin()[i]) value_type( - std::move(tab_->begin()[i])); + relocate( + &tab->begin()[i], + tab_->begin()[i]); tab->size = tab_->size; std::swap(tab, tab_); + tab->size = 0; // VFALCO Hack table::destroy(tab, sp_); } diff --git a/include/boost/json/impl/object.ipp b/include/boost/json/impl/object.ipp index f9bfd01b..25163e7e 100644 --- a/include/boost/json/impl/object.ipp +++ b/include/boost/json/impl/object.ipp @@ -327,6 +327,14 @@ object(object&& other) noexcept { } +object:: +object(pilfered other) noexcept + : sp_(std::move(other.get().sp_)) + , tab_(boost::exchange( + other.get().tab_, nullptr)) +{ +} + object:: object( object&& other, diff --git a/include/boost/json/impl/value.ipp b/include/boost/json/impl/value.ipp index fd75de75..41117a69 100644 --- a/include/boost/json/impl/value.ipp +++ b/include/boost/json/impl/value.ipp @@ -82,6 +82,48 @@ value(value&& other) noexcept other.kind_ = json::kind::null; } +value:: +value(pilfered p) noexcept +{ + auto& other = p.get(); + switch(other.kind_) + { + case json::kind::object: + ::new(&obj_) object( + pilfer(other.obj_)); + break; + + case json::kind::array: + ::new(&arr_) array( + std::move(other.arr_)); + break; + + case json::kind::string: + ::new(&str_) string( + std::move(other.str_)); + break; + + case json::kind::number: + ::new(&nat_.sp_) storage_ptr( + std::move(other.nat_.sp_)); + ::new(&nat_.num_) number( + std::move(other.nat_.num_)); + break; + + case json::kind::boolean: + ::new(&nat_.sp_) storage_ptr( + std::move(other.nat_.sp_)); + nat_.bool_ = other.nat_.bool_; + break; + + case json::kind::null: + ::new(&nat_.sp_) storage_ptr( + std::move(other.nat_.sp_)); + break; + } + kind_ = other.kind_; +} + value:: value( value&& other, diff --git a/include/boost/json/object.hpp b/include/boost/json/object.hpp index 177abceb..f79a71e5 100644 --- a/include/boost/json/object.hpp +++ b/include/boost/json/object.hpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -139,6 +140,9 @@ public: BOOST_JSON_DECL object(object&& other) noexcept; + BOOST_JSON_DECL + object(pilfered other) noexcept; + BOOST_JSON_DECL object( object&& other, diff --git a/include/boost/json/value.hpp b/include/boost/json/value.hpp index 6997bcc0..19946791 100644 --- a/include/boost/json/value.hpp +++ b/include/boost/json/value.hpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -133,6 +134,10 @@ public: BOOST_JSON_DECL value(value&& other) noexcept; + /// Pilfer constructor + BOOST_JSON_DECL + value(pilfered other) noexcept; + /// Move construct a value, using the specified storage BOOST_JSON_DECL value(