From 0b9a59f2707ddadc113effa0bedfd36c1a8f78a0 Mon Sep 17 00:00:00 2001 From: Rene Rivera Date: Fri, 7 Oct 2016 23:07:33 -0500 Subject: [PATCH 01/10] Add, and update, documentation build targets. --- doc/jamfile.v2 | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/doc/jamfile.v2 b/doc/jamfile.v2 index bdc1659b..ca6e53bb 100644 --- a/doc/jamfile.v2 +++ b/doc/jamfile.v2 @@ -208,5 +208,12 @@ install png_install : [ glob $(here)/*.png ] : $(here)/../../../doc/ht install pdfinstall : standalone : PDF . circular_buffer.pdf ; - - +############################################################################### +alias boostdoc + : standalone/docbook + : + : + : ; +explicit boostdoc ; +alias boostrelease ; +explicit boostrelease ; From 50dbb456ce94e5814b91b936289fde8cc4e3c80c Mon Sep 17 00:00:00 2001 From: Yuval Lifshitz Date: Tue, 18 Dec 2018 14:54:10 +0200 Subject: [PATCH 02/10] add serialization to circular buffer --- example/circular_buffer_bound_example.cpp | 1 + example/circular_buffer_serialization.cpp | 141 ++++++++++++++++++ example/jamfile.v2 | 2 + include/boost/circular_buffer.hpp | 1 + .../boost/circular_buffer/serialization.hpp | 75 ++++++++++ test/Jamfile.v2 | 4 + test/serialization_test.cpp | 65 ++++++++ 7 files changed, 289 insertions(+) create mode 100644 example/circular_buffer_serialization.cpp create mode 100644 include/boost/circular_buffer/serialization.hpp create mode 100644 test/serialization_test.cpp diff --git a/example/circular_buffer_bound_example.cpp b/example/circular_buffer_bound_example.cpp index f55daa3d..731aadb4 100644 --- a/example/circular_buffer_bound_example.cpp +++ b/example/circular_buffer_bound_example.cpp @@ -11,6 +11,7 @@ This example shows how the `circular_buffer` can be utilized as an underlying container of the bounded buffer. */ +#include #include #include #include diff --git a/example/circular_buffer_serialization.cpp b/example/circular_buffer_serialization.cpp new file mode 100644 index 00000000..4d813507 --- /dev/null +++ b/example/circular_buffer_serialization.cpp @@ -0,0 +1,141 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int main(int argc, char** argv) +{ + int buffer_size = 100000; + + if (argc == 2) { + buffer_size = std::atoi(argv[1]); + if (buffer_size <= 0) { + std::cout << "invalid buffer size" << std::endl; + return 1; + } + } + + // Seed with a real random value, if available + std::random_device r; + + // Choose a randomly whether to push or pop + std::default_random_engine e(r()); + std::uniform_int_distribution uniform_dist(1, 10); + + { + boost::circular_buffer cb1(buffer_size); + for (auto i = 0; i < buffer_size; ++i) { + auto draw = uniform_dist(e); + if (draw < 8 || cb1.empty()) + cb1.push_back(i); + else + cb1.pop_front(); + } + + { + // in-memory storage + std::stringstream ss; + + boost::archive::text_oarchive oa(ss); + std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::now(); + boost::serialization::serialize(oa, cb1, 0); + std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now(); + std::cout << "in-memory serialization for buffer: " << buffer_size << " took: " << + std::chrono::duration_cast (end - begin).count() << " usec" << std::endl; + + boost::circular_buffer cb2(0); + boost::archive::text_iarchive ia(ss); + begin = std::chrono::steady_clock::now(); + boost::serialization::serialize(ia, cb2, 0); + end = std::chrono::steady_clock::now(); + std::cout << "in-memory deserialization for buffer: " << buffer_size << " took: " << + std::chrono::duration_cast (end - begin).count() << " usec" << std::endl; + + if (cb1 != cb2) { + std::cout << "circular buffer did not recover correctly" << std::endl; + } + } + + { + const std::string filename = "cb.tmp"; + // file storage + { + std::ofstream ofs(filename); + + boost::archive::text_oarchive oa(ofs); + std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::now(); + boost::serialization::serialize(oa, cb1, 0); + std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now(); + std::cout << "file serialization for buffer: " << buffer_size << " took: " << + std::chrono::duration_cast (end - begin).count() << " usec" << std::endl; + } + { + std::ifstream ifs(filename); + + boost::circular_buffer cb2(0); + boost::archive::text_iarchive ia(ifs); + std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::now(); + boost::serialization::serialize(ia, cb2, 0); + std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now(); + std::cout << "file deserialization for buffer: " << buffer_size << " took: " << + std::chrono::duration_cast (end - begin).count() << " usec" << std::endl; + + if (cb1 != cb2) { + std::cout << "circular buffer did not recover correctly" << std::endl; + } + } + std::remove(filename.c_str()); + } + } + + { + // space optimized + boost::circular_buffer_space_optimized cb1(buffer_size); + for (auto i = 0; i < buffer_size; ++i) { + auto draw = uniform_dist(e); + if (draw < 8 || cb1.empty()) { + cb1.push_back(i); + } else { + cb1.pop_front(); + } + } + + { + const std::string filename = "space_opt_cb.tmp"; + { + std::ofstream ofs(filename); + + boost::archive::text_oarchive oa(ofs); + std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::now(); + boost::serialization::serialize(oa, cb1, 0); + std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now(); + std::cout << "in-memory serialization for space optimized buffer: " << buffer_size << " took: " << + std::chrono::duration_cast (end - begin).count() << " usec" << std::endl; + } + + { + std::ifstream ifs(filename); + + boost::circular_buffer_space_optimized cb2(0); + boost::archive::text_iarchive ia(ifs); + std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::now(); + boost::serialization::serialize(ia, cb2, 0); + std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now(); + std::cout << "in-memory deserialization for space optimized buffer: " << buffer_size << " took: " << + std::chrono::duration_cast (end - begin).count() << " usec" << std::endl; + + if (cb1 != cb2) { + std::cout << "space optimized circular buffer did not recover correctly" << std::endl; + } + } + } + } + + return 0; +} + diff --git a/example/jamfile.v2 b/example/jamfile.v2 index 36db161b..6c8de839 100644 --- a/example/jamfile.v2 +++ b/example/jamfile.v2 @@ -12,6 +12,7 @@ project : requirements /boost/system//boost_system /boost/thread//boost_thread + /boost/serialization #BOOST_ALL_NO_LIB=1 multi @@ -39,4 +40,5 @@ run bounded_buffer_comparison.cpp ; run circular_buffer_iter_example.cpp ; run circular_buffer_sum_example.cpp ; run circular_buffer_bound_example.cpp ../../thread/build//boost_thread ../../timer/build//boost_timer ; +run circular_buffer_serialization.cpp ; diff --git a/include/boost/circular_buffer.hpp b/include/boost/circular_buffer.hpp index f0530805..4619b872 100644 --- a/include/boost/circular_buffer.hpp +++ b/include/boost/circular_buffer.hpp @@ -54,6 +54,7 @@ #include #include #include +#include #undef BOOST_CB_ASSERT_TEMPLATED_ITERATOR_CONSTRUCTORS #undef BOOST_CB_IS_CONVERTIBLE diff --git a/include/boost/circular_buffer/serialization.hpp b/include/boost/circular_buffer/serialization.hpp new file mode 100644 index 00000000..8659f36c --- /dev/null +++ b/include/boost/circular_buffer/serialization.hpp @@ -0,0 +1,75 @@ +// boost::circular_buffer serialization + +#include +#include +#include + +namespace boost { namespace serialization { +template +void save(Archive& ar, const circular_buffer& b, const unsigned int /* version */) +{ + ar << b.capacity(); + ar << b.size(); + const typename circular_buffer::const_array_range one = b.array_one(); + const typename circular_buffer::const_array_range two = b.array_two(); + ar.save_binary(one.first, one.second*sizeof(T)); + ar.save_binary(two.first, two.second*sizeof(T)); +} + +template +void load(Archive& ar, circular_buffer& b, const unsigned int /* version */) +{ + b.clear(); + typename circular_buffer::capacity_type capacity; + typename circular_buffer::size_type size; + ar >> capacity; + ar >> size; + b.set_capacity(capacity); + const scoped_array::value_type> buff(new T[size]); + ar.load_binary(buff.get(), size*sizeof(T)); + b.insert(b.begin(), buff.get(), buff.get()+size); +} + +template +inline void serialize(Archive & ar, circular_buffer& b, const unsigned int version) +{ + split_free(ar, b, version); +} + +template +void save(Archive& ar, const circular_buffer_space_optimized& b, const unsigned int /* version */) +{ + ar << b.capacity().capacity(); + ar << b.capacity().min_capacity(); + ar << b.size(); + const typename circular_buffer_space_optimized::const_array_range one = b.array_one(); + const typename circular_buffer_space_optimized::const_array_range two = b.array_two(); + ar.save_binary(one.first, one.second*sizeof(T)); + ar.save_binary(two.first, two.second*sizeof(T)); +} + +template +void load(Archive& ar, circular_buffer_space_optimized& b, const unsigned int /* version */) +{ + b.clear(); + typename circular_buffer_space_optimized::size_type capacity; + typename circular_buffer_space_optimized::size_type min_capacity; + typename circular_buffer_space_optimized::size_type size; + ar >> capacity; + ar >> min_capacity; + ar >> size; + const typename circular_buffer_space_optimized::capacity_type capacity_control(capacity, min_capacity); + b.set_capacity(capacity_control); + const scoped_array::value_type> buff(new T[size]); + ar.load_binary(buff.get(), size*sizeof(T)); + b.insert(b.begin(), buff.get(), buff.get()+size); +} + +template +inline void serialize(Archive & ar, circular_buffer_space_optimized& b, const unsigned int version) +{ + split_free(ar, b, version); +} + +} } // end namespace boost::serialization + diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 7e1ae584..f8ef194c 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -13,6 +13,9 @@ import testing ; project : requirements + /boost/test//boost_unit_test_framework + /boost/serialization + static msvc:all msvc:on msvc:_SCL_SECURE_NO_WARNINGS @@ -29,4 +32,5 @@ test-suite "circular_buffer" [ run soft_iterator_invalidation.cpp : : : single : ] [ run constant_erase_test.cpp : : : single : ] [ compile bounded_buffer_comparison.cpp : multi : ] + [ run serialization_test.cpp : : : single : ] ; diff --git a/test/serialization_test.cpp b/test/serialization_test.cpp new file mode 100644 index 00000000..54dddca4 --- /dev/null +++ b/test/serialization_test.cpp @@ -0,0 +1,65 @@ +// Test of the circular buffer container serialization + +#include +#include +#include +#include +#include +#include + +using namespace boost::unit_test; + +const auto buffer_size = 100000; + +void basic_test() { + boost::circular_buffer cb1(buffer_size); + for (auto i = 0; i < buffer_size; ++i) { + cb1.push_back(i); + } + + { + // in-memory storage + std::stringstream ss; + + boost::archive::text_oarchive oa(ss); + boost::serialization::serialize(oa, cb1, 0); + + boost::circular_buffer cb2(0); + boost::archive::text_iarchive ia(ss); + boost::serialization::serialize(ia, cb2, 0); + BOOST_CHECK(cb1 == cb2); + } +} + +void spaced_optimized_test() { + boost::circular_buffer_space_optimized cb1(buffer_size); + for (auto i = 0; i < buffer_size; ++i) { + cb1.push_back(i); + } + + { + // in-memory storage + std::stringstream ss; + + boost::archive::text_oarchive oa(ss); + boost::serialization::serialize(oa, cb1, 0); + + boost::circular_buffer_space_optimized cb2(0); + boost::archive::text_iarchive ia(ss); + boost::serialization::serialize(ia, cb2, 0); + BOOST_CHECK(cb1 == cb2); + } +} + + +// test main +test_suite* init_unit_test_suite(int /*argc*/, char* /*argv*/[]) { + + test_suite* tests = BOOST_TEST_SUITE("Unit tests for circular_buffer serialization."); + + tests->add(BOOST_TEST_CASE(&basic_test)); + tests->add(BOOST_TEST_CASE(&spaced_optimized_test)); + + return tests; +} + From 32a145f025014bbff95f29d8eaec17219c998bdc Mon Sep 17 00:00:00 2001 From: Yuval Lifshitz Date: Thu, 20 Dec 2018 15:32:42 +0200 Subject: [PATCH 03/10] make test c++0x compatible --- test/serialization_test.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/serialization_test.cpp b/test/serialization_test.cpp index 54dddca4..628850fe 100644 --- a/test/serialization_test.cpp +++ b/test/serialization_test.cpp @@ -9,11 +9,11 @@ using namespace boost::unit_test; -const auto buffer_size = 100000; +const int buffer_size = 100000; void basic_test() { boost::circular_buffer cb1(buffer_size); - for (auto i = 0; i < buffer_size; ++i) { + for (int i = 0; i < buffer_size; ++i) { cb1.push_back(i); } @@ -33,7 +33,7 @@ void basic_test() { void spaced_optimized_test() { boost::circular_buffer_space_optimized cb1(buffer_size); - for (auto i = 0; i < buffer_size; ++i) { + for (int i = 0; i < buffer_size; ++i) { cb1.push_back(i); } @@ -51,7 +51,6 @@ void spaced_optimized_test() { } } - // test main test_suite* init_unit_test_suite(int /*argc*/, char* /*argv*/[]) { @@ -63,3 +62,4 @@ test_suite* init_unit_test_suite(int /*argc*/, char* /*argv*/[]) { return tests; } + From 1e9312356323ebbf7835164b9342ef81e85371cd Mon Sep 17 00:00:00 2001 From: Yuval Lifshitz Date: Mon, 31 Dec 2018 15:01:10 +0200 Subject: [PATCH 04/10] fix jamfile indentation --- example/jamfile.v2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/example/jamfile.v2 b/example/jamfile.v2 index 6c8de839..7ac4116e 100644 --- a/example/jamfile.v2 +++ b/example/jamfile.v2 @@ -12,7 +12,7 @@ project : requirements /boost/system//boost_system /boost/thread//boost_thread - /boost/serialization + /boost/thread/serialization #BOOST_ALL_NO_LIB=1 multi From 6cf3af50593203661d8a4bb9a1854ad2563ad4b8 Mon Sep 17 00:00:00 2001 From: Yuval Lifshitz Date: Sun, 20 Jan 2019 13:57:04 +0200 Subject: [PATCH 05/10] fix library name in jamfile Signed-off-by: Yuval Lifshitz --- example/jamfile.v2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/example/jamfile.v2 b/example/jamfile.v2 index 7ac4116e..607812cf 100644 --- a/example/jamfile.v2 +++ b/example/jamfile.v2 @@ -12,7 +12,7 @@ project : requirements /boost/system//boost_system /boost/thread//boost_thread - /boost/thread/serialization + /boost//serialization #BOOST_ALL_NO_LIB=1 multi From d9bdfd7423ece3079b12aa321e1ee3a713054a87 Mon Sep 17 00:00:00 2001 From: Yuval Lifshitz Date: Tue, 26 Feb 2019 11:56:24 +0200 Subject: [PATCH 06/10] add license phrases Signed-off-by: Yuval Lifshitz --- example/circular_buffer_serialization.cpp | 4 ++++ include/boost/circular_buffer/serialization.hpp | 6 +++++- test/serialization_test.cpp | 4 ++++ 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/example/circular_buffer_serialization.cpp b/example/circular_buffer_serialization.cpp index 4d813507..16bd401f 100644 --- a/example/circular_buffer_serialization.cpp +++ b/example/circular_buffer_serialization.cpp @@ -1,3 +1,7 @@ +// Distributed under the Boost Software License, Version 1.0. +// (See the accompanying file LICENSE_1_0.txt +// or a copy at .) + #include #include #include diff --git a/include/boost/circular_buffer/serialization.hpp b/include/boost/circular_buffer/serialization.hpp index 8659f36c..2f21065a 100644 --- a/include/boost/circular_buffer/serialization.hpp +++ b/include/boost/circular_buffer/serialization.hpp @@ -1,4 +1,8 @@ -// boost::circular_buffer serialization +// Implementation of circular_buffer serialization + +// Use, modification, and distribution is subject to 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) #include #include diff --git a/test/serialization_test.cpp b/test/serialization_test.cpp index 628850fe..f9d2baa1 100644 --- a/test/serialization_test.cpp +++ b/test/serialization_test.cpp @@ -1,5 +1,9 @@ // Test of the circular buffer container serialization +// Use, modification, and distribution is subject to 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) + #include #include #include From 7b9ef135153abd17da4d511edb30eaabc9872156 Mon Sep 17 00:00:00 2001 From: Yuval Lifshitz Date: Sun, 3 Mar 2019 12:28:08 +0200 Subject: [PATCH 07/10] de/serialize array1/array2 separatly Signed-off-by: Yuval Lifshitz --- .../boost/circular_buffer/serialization.hpp | 56 +++++++++++++------ test/serialization_test.cpp | 46 ++++++++------- 2 files changed, 66 insertions(+), 36 deletions(-) diff --git a/include/boost/circular_buffer/serialization.hpp b/include/boost/circular_buffer/serialization.hpp index 2f21065a..f8e0de22 100644 --- a/include/boost/circular_buffer/serialization.hpp +++ b/include/boost/circular_buffer/serialization.hpp @@ -13,11 +13,16 @@ template void save(Archive& ar, const circular_buffer& b, const unsigned int /* version */) { ar << b.capacity(); - ar << b.size(); const typename circular_buffer::const_array_range one = b.array_one(); const typename circular_buffer::const_array_range two = b.array_two(); - ar.save_binary(one.first, one.second*sizeof(T)); - ar.save_binary(two.first, two.second*sizeof(T)); + ar << one.second; + ar << two.second; + if (one.second) { + ar.save_binary(one.first, one.second*sizeof(T)); + } + if (two.second) { + ar.save_binary(two.first, two.second*sizeof(T)); + } } template @@ -25,13 +30,20 @@ void load(Archive& ar, circular_buffer& b, const unsigned int /* version */) { b.clear(); typename circular_buffer::capacity_type capacity; - typename circular_buffer::size_type size; ar >> capacity; - ar >> size; b.set_capacity(capacity); - const scoped_array::value_type> buff(new T[size]); - ar.load_binary(buff.get(), size*sizeof(T)); - b.insert(b.begin(), buff.get(), buff.get()+size); + typename circular_buffer::size_type size1; + typename circular_buffer::size_type size2; + ar >> size1; + ar >> size2; + const scoped_array::value_type> buff(new T[size1+size2]); + if (size1) { + ar.load_binary(buff.get(), size1*sizeof(T)); + } + if (size2) { + ar.load_binary(&buff[size1], size2*sizeof(T)); + } + b.insert(b.begin(), buff.get(), buff.get()+size1+size2); } template @@ -45,11 +57,16 @@ void save(Archive& ar, const circular_buffer_space_optimized& b, const unsign { ar << b.capacity().capacity(); ar << b.capacity().min_capacity(); - ar << b.size(); const typename circular_buffer_space_optimized::const_array_range one = b.array_one(); const typename circular_buffer_space_optimized::const_array_range two = b.array_two(); - ar.save_binary(one.first, one.second*sizeof(T)); - ar.save_binary(two.first, two.second*sizeof(T)); + ar << one.second; + ar << two.second; + if (one.second) { + ar.save_binary(one.first, one.second*sizeof(T)); + } + if (two.second) { + ar.save_binary(two.first, two.second*sizeof(T)); + } } template @@ -58,15 +75,22 @@ void load(Archive& ar, circular_buffer_space_optimized& b, const unsigned int b.clear(); typename circular_buffer_space_optimized::size_type capacity; typename circular_buffer_space_optimized::size_type min_capacity; - typename circular_buffer_space_optimized::size_type size; ar >> capacity; ar >> min_capacity; - ar >> size; const typename circular_buffer_space_optimized::capacity_type capacity_control(capacity, min_capacity); b.set_capacity(capacity_control); - const scoped_array::value_type> buff(new T[size]); - ar.load_binary(buff.get(), size*sizeof(T)); - b.insert(b.begin(), buff.get(), buff.get()+size); + typename circular_buffer::size_type size1; + typename circular_buffer::size_type size2; + ar >> size1; + ar >> size2; + const scoped_array::value_type> buff(new T[size1+size2]); + if (size1) { + ar.load_binary(buff.get(), size1*sizeof(T)); + } + if (size2) { + ar.load_binary(&buff[size1], size2*sizeof(T)); + } + b.insert(b.begin(), buff.get(), buff.get()+size1+size2); } template diff --git a/test/serialization_test.cpp b/test/serialization_test.cpp index f9d2baa1..cf1dea90 100644 --- a/test/serialization_test.cpp +++ b/test/serialization_test.cpp @@ -15,8 +15,9 @@ using namespace boost::unit_test; const int buffer_size = 100000; +template void basic_test() { - boost::circular_buffer cb1(buffer_size); + buffer_type cb1(buffer_size); for (int i = 0; i < buffer_size; ++i) { cb1.push_back(i); } @@ -28,31 +29,35 @@ void basic_test() { boost::archive::text_oarchive oa(ss); boost::serialization::serialize(oa, cb1, 0); - boost::circular_buffer cb2(0); + buffer_type cb2(0); boost::archive::text_iarchive ia(ss); boost::serialization::serialize(ia, cb2, 0); BOOST_CHECK(cb1 == cb2); } } -void spaced_optimized_test() { - boost::circular_buffer_space_optimized cb1(buffer_size); - for (int i = 0; i < buffer_size; ++i) { - cb1.push_back(i); - } +template +void fragmented_buffer_test() { - { - // in-memory storage - std::stringstream ss; + buffer_type cb1(buffer_size); + for (auto i = 0; i < buffer_size/4; ++i) + cb1.push_back(i+1); + for (auto i = 0; i < buffer_size/4; ++i) + cb1.push_front((i+1)*100); - boost::archive::text_oarchive oa(ss); - boost::serialization::serialize(oa, cb1, 0); + // making sure we are testing a fragmented buffer + BOOST_CHECK(!cb1.is_linearized()); - boost::circular_buffer_space_optimized cb2(0); - boost::archive::text_iarchive ia(ss); - boost::serialization::serialize(ia, cb2, 0); - BOOST_CHECK(cb1 == cb2); - } + std::stringstream ss; + + boost::archive::text_oarchive oa(ss); + boost::serialization::serialize(oa, cb1, 0); + + buffer_type cb2(0); + boost::archive::text_iarchive ia(ss); + boost::serialization::serialize(ia, cb2, 0); + + BOOST_CHECK(cb1 == cb2); } // test main @@ -60,10 +65,11 @@ test_suite* init_unit_test_suite(int /*argc*/, char* /*argv*/[]) { test_suite* tests = BOOST_TEST_SUITE("Unit tests for circular_buffer serialization."); - tests->add(BOOST_TEST_CASE(&basic_test)); - tests->add(BOOST_TEST_CASE(&spaced_optimized_test)); + tests->add(BOOST_TEST_CASE(&basic_test>)); + tests->add(BOOST_TEST_CASE(&basic_test>)); + tests->add(BOOST_TEST_CASE(&fragmented_buffer_test>)); + tests->add(BOOST_TEST_CASE(&fragmented_buffer_test>)); return tests; } - From 49b5d7f230d4d913a19f7f06ae7cced112a8462b Mon Sep 17 00:00:00 2001 From: Yuval Lifshitz Date: Sun, 3 Mar 2019 19:02:49 +0200 Subject: [PATCH 08/10] allow disabling of serilalization Signed-off-by: Yuval Lifshitz --- include/boost/circular_buffer.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/boost/circular_buffer.hpp b/include/boost/circular_buffer.hpp index 4619b872..48bbf4a9 100644 --- a/include/boost/circular_buffer.hpp +++ b/include/boost/circular_buffer.hpp @@ -54,7 +54,9 @@ #include #include #include +#if !defined(BOOST_CIRCULAR_BUFFER_DISABLE_SERIALIZATION) #include +#endif #undef BOOST_CB_ASSERT_TEMPLATED_ITERATOR_CONSTRUCTORS #undef BOOST_CB_IS_CONVERTIBLE From 12edc8dd7c7d2fc22b8d8f73d64a7b24ba514537 Mon Sep 17 00:00:00 2001 From: Yuval Lifshitz Date: Mon, 4 Mar 2019 10:57:39 +0200 Subject: [PATCH 09/10] use binary optimization only for binary archives Signed-off-by: Yuval Lifshitz --- example/circular_buffer_serialization.cpp | 31 ++++++++- .../boost/circular_buffer/serialization.hpp | 64 ++++++++++++++++++- test/serialization_test.cpp | 51 ++++++++++++--- 3 files changed, 132 insertions(+), 14 deletions(-) diff --git a/example/circular_buffer_serialization.cpp b/example/circular_buffer_serialization.cpp index 16bd401f..0552d89e 100644 --- a/example/circular_buffer_serialization.cpp +++ b/example/circular_buffer_serialization.cpp @@ -11,6 +11,8 @@ #include #include #include +#include +#include int main(int argc, char** argv) { @@ -42,7 +44,7 @@ int main(int argc, char** argv) } { - // in-memory storage + // in-memory storage text std::stringstream ss; boost::archive::text_oarchive oa(ss); @@ -65,9 +67,33 @@ int main(int argc, char** argv) } } + { + // in-memory storage binary + std::stringstream ss; + + boost::archive::binary_oarchive oa(ss); + std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::now(); + boost::serialization::serialize(oa, cb1, 0); + std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now(); + std::cout << "in-memory binary serialization for buffer: " << buffer_size << " took: " << + std::chrono::duration_cast (end - begin).count() << " usec" << std::endl; + + boost::circular_buffer cb2(0); + boost::archive::binary_iarchive ia(ss); + begin = std::chrono::steady_clock::now(); + boost::serialization::serialize(ia, cb2, 0); + end = std::chrono::steady_clock::now(); + std::cout << "in-memory binary deserialization for buffer: " << buffer_size << " took: " << + std::chrono::duration_cast (end - begin).count() << " usec" << std::endl; + + if (cb1 != cb2) { + std::cout << "circular buffer did not recover correctly" << std::endl; + } + } + { const std::string filename = "cb.tmp"; - // file storage + // file storage text { std::ofstream ofs(filename); @@ -137,6 +163,7 @@ int main(int argc, char** argv) std::cout << "space optimized circular buffer did not recover correctly" << std::endl; } } + std::remove(filename.c_str()); } } diff --git a/include/boost/circular_buffer/serialization.hpp b/include/boost/circular_buffer/serialization.hpp index f8e0de22..03115961 100644 --- a/include/boost/circular_buffer/serialization.hpp +++ b/include/boost/circular_buffer/serialization.hpp @@ -7,14 +7,26 @@ #include #include #include +#include +#include namespace boost { namespace serialization { template void save(Archive& ar, const circular_buffer& b, const unsigned int /* version */) { ar << b.capacity(); - const typename circular_buffer::const_array_range one = b.array_one(); - const typename circular_buffer::const_array_range two = b.array_two(); + ar << b.size(); + for (const auto& e : b) { + ar << e; + } +} + +template +void save(archive::binary_oarchive& ar, const circular_buffer& b, const unsigned int /* version */) +{ + ar << b.capacity(); + const typename circular_buffer::const_array_range& one = b.array_one(); + const typename circular_buffer::const_array_range& two = b.array_two(); ar << one.second; ar << two.second; if (one.second) { @@ -27,6 +39,23 @@ void save(Archive& ar, const circular_buffer& b, const unsigned int /* versio template void load(Archive& ar, circular_buffer& b, const unsigned int /* version */) +{ + b.clear(); + typename circular_buffer::capacity_type capacity; + ar >> capacity; + b.set_capacity(capacity); + typename circular_buffer::size_type size; + ar >> size; + while (size > 0) { + T e; + ar >> e; + b.push_back(e); + --size; + } +} + +template +void load(archive::binary_iarchive& ar, circular_buffer& b, const unsigned int /* version */) { b.clear(); typename circular_buffer::capacity_type capacity; @@ -54,6 +83,17 @@ inline void serialize(Archive & ar, circular_buffer& b, const unsigned int ve template void save(Archive& ar, const circular_buffer_space_optimized& b, const unsigned int /* version */) +{ + ar << b.capacity().capacity(); + ar << b.capacity().min_capacity(); + ar << b.size(); + for (const auto& e : b) { + ar << e; + } +} + +template +void save(archive::binary_oarchive& ar, const circular_buffer_space_optimized& b, const unsigned int /* version */) { ar << b.capacity().capacity(); ar << b.capacity().min_capacity(); @@ -71,6 +111,26 @@ void save(Archive& ar, const circular_buffer_space_optimized& b, const unsign template void load(Archive& ar, circular_buffer_space_optimized& b, const unsigned int /* version */) +{ + b.clear(); + typename circular_buffer_space_optimized::size_type capacity; + typename circular_buffer_space_optimized::size_type min_capacity; + ar >> capacity; + ar >> min_capacity; + const typename circular_buffer_space_optimized::capacity_type capacity_control(capacity, min_capacity); + b.set_capacity(capacity_control); + typename circular_buffer::size_type size; + ar >> size; + while (size > 0) { + T e; + ar >> e; + b.push_back(e); + --size; + } +} + +template +void load(archive::binary_iarchive& ar, circular_buffer_space_optimized& b, const unsigned int /* version */) { b.clear(); typename circular_buffer_space_optimized::size_type capacity; diff --git a/test/serialization_test.cpp b/test/serialization_test.cpp index cf1dea90..29819573 100644 --- a/test/serialization_test.cpp +++ b/test/serialization_test.cpp @@ -7,6 +7,8 @@ #include #include #include +#include +#include #include #include #include @@ -15,7 +17,7 @@ using namespace boost::unit_test; const int buffer_size = 100000; -template +template void basic_test() { buffer_type cb1(buffer_size); for (int i = 0; i < buffer_size; ++i) { @@ -26,17 +28,17 @@ void basic_test() { // in-memory storage std::stringstream ss; - boost::archive::text_oarchive oa(ss); + oarchive_type oa(ss); boost::serialization::serialize(oa, cb1, 0); buffer_type cb2(0); - boost::archive::text_iarchive ia(ss); + iarchive_type ia(ss); boost::serialization::serialize(ia, cb2, 0); BOOST_CHECK(cb1 == cb2); } } -template +template void fragmented_buffer_test() { buffer_type cb1(buffer_size); @@ -50,25 +52,54 @@ void fragmented_buffer_test() { std::stringstream ss; - boost::archive::text_oarchive oa(ss); + oarchive_type oa(ss); boost::serialization::serialize(oa, cb1, 0); buffer_type cb2(0); - boost::archive::text_iarchive ia(ss); + iarchive_type ia(ss); boost::serialization::serialize(ia, cb2, 0); BOOST_CHECK(cb1 == cb2); } +void basic_test_text() { + basic_test, boost::archive::text_oarchive, boost::archive::text_iarchive>(); +} +void basic_test_optimized_text() { + basic_test, boost::archive::text_oarchive, boost::archive::text_iarchive>(); +} +void fragmented_test_text() { + fragmented_buffer_test, boost::archive::text_oarchive, boost::archive::text_iarchive>(); +} +void fragmented_test_optimized_text() { + fragmented_buffer_test, boost::archive::text_oarchive, boost::archive::text_iarchive>(); +} +void basic_test_binary() { + basic_test, boost::archive::binary_oarchive, boost::archive::binary_iarchive>(); +} +void basic_test_optimized_binary() { + basic_test, boost::archive::binary_oarchive, boost::archive::binary_iarchive>(); +} +void fragmented_test_binary() { + fragmented_buffer_test, boost::archive::binary_oarchive, boost::archive::binary_iarchive>(); +} +void fragmented_test_optimized_binary() { + fragmented_buffer_test, boost::archive::binary_oarchive, boost::archive::binary_iarchive>(); +} + // test main test_suite* init_unit_test_suite(int /*argc*/, char* /*argv*/[]) { test_suite* tests = BOOST_TEST_SUITE("Unit tests for circular_buffer serialization."); - tests->add(BOOST_TEST_CASE(&basic_test>)); - tests->add(BOOST_TEST_CASE(&basic_test>)); - tests->add(BOOST_TEST_CASE(&fragmented_buffer_test>)); - tests->add(BOOST_TEST_CASE(&fragmented_buffer_test>)); + tests->add(BOOST_TEST_CASE(&basic_test_text)); + tests->add(BOOST_TEST_CASE(&basic_test_optimized_text)); + tests->add(BOOST_TEST_CASE(&fragmented_test_text)); + tests->add(BOOST_TEST_CASE(&fragmented_test_optimized_text)); + tests->add(BOOST_TEST_CASE(&basic_test_binary)); + tests->add(BOOST_TEST_CASE(&basic_test_optimized_binary)); + tests->add(BOOST_TEST_CASE(&fragmented_test_binary)); + tests->add(BOOST_TEST_CASE(&fragmented_test_optimized_binary)); return tests; } From fce55feb3e650a341cd32aa9cb39e4ddeaeda926 Mon Sep 17 00:00:00 2001 From: Yuval Lifshitz Date: Mon, 4 Mar 2019 12:07:13 +0200 Subject: [PATCH 10/10] library should be c++03 compliant Signed-off-by: Yuval Lifshitz --- include/boost/circular_buffer/serialization.hpp | 12 ++++++++---- test/serialization_test.cpp | 4 ++-- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/include/boost/circular_buffer/serialization.hpp b/include/boost/circular_buffer/serialization.hpp index 03115961..170fc647 100644 --- a/include/boost/circular_buffer/serialization.hpp +++ b/include/boost/circular_buffer/serialization.hpp @@ -16,8 +16,10 @@ void save(Archive& ar, const circular_buffer& b, const unsigned int /* versio { ar << b.capacity(); ar << b.size(); - for (const auto& e : b) { - ar << e; + const typename circular_buffer::const_iterator it_end = b.end(); + typename circular_buffer::const_iterator it = b.begin(); + for (; it != it_end; ++it) { + ar << *it; } } @@ -87,8 +89,10 @@ void save(Archive& ar, const circular_buffer_space_optimized& b, const unsign ar << b.capacity().capacity(); ar << b.capacity().min_capacity(); ar << b.size(); - for (const auto& e : b) { - ar << e; + const typename circular_buffer_space_optimized::const_iterator it_end = b.end(); + typename circular_buffer_space_optimized::const_iterator it = b.begin(); + for (; it != it_end; ++it) { + ar << *it; } } diff --git a/test/serialization_test.cpp b/test/serialization_test.cpp index 29819573..d8960108 100644 --- a/test/serialization_test.cpp +++ b/test/serialization_test.cpp @@ -42,9 +42,9 @@ template void fragmented_buffer_test() { buffer_type cb1(buffer_size); - for (auto i = 0; i < buffer_size/4; ++i) + for (int i = 0; i < buffer_size/4; ++i) cb1.push_back(i+1); - for (auto i = 0; i < buffer_size/4; ++i) + for (int i = 0; i < buffer_size/4; ++i) cb1.push_front((i+1)*100); // making sure we are testing a fragmented buffer