From 9270fe49ab8211b0c4f4e4de8289b8cf06a5ca8a Mon Sep 17 00:00:00 2001 From: Avril Date: Mon, 30 Nov 2020 23:04:50 +0000 Subject: [PATCH] lazy init of spill buffer --- include/fsvec.hpp | 68 ++++++++++++++++++++++++++++++++++------------- 1 file changed, 50 insertions(+), 18 deletions(-) diff --git a/include/fsvec.hpp b/include/fsvec.hpp index 269b461..3fd79dd 100644 --- a/include/fsvec.hpp +++ b/include/fsvec.hpp @@ -25,6 +25,12 @@ struct i_back_inserter virtual inline ~i_back_inserter() =default; }; +struct i_shunt +{ + virtual bool is_full() const =0; + virtual inline ~i_shunt() =default; +}; + struct file_back_buffer { const static constexpr std::size_t DEFAULT_CAP = 1024; @@ -164,49 +170,75 @@ private: file_vector fil; }; -template -struct dynamic_spill_vector : public i_back_inserter +template + requires(std::is_base_of, Shunt >::value) +struct shunt : public i_back_inserter, protected i_shunt { - inline dynamic_spill_vector() : dynamic_spill_vector(FSV_DEFAULT_SPILL_AT){} - inline dynamic_spill_vector(std::size_t cap) : dynamic_spill_vector(cap, cap){} - inline dynamic_spill_vector(std::size_t cap, std::size_t spill) : _spill_at(spill), mem(std::vector()), fil(file_vector(cap)) { + typedef Shunt spill_type; + + inline shunt() : shunt(FSV_DEFAULT_SPILL_AT){} + inline shunt(std::size_t cap) : shunt(cap, cap){} + inline shunt(std::size_t cap, std::size_t spill) : _spill_at(spill), mem(std::vector()), fil(nullptr) { mem.reserve(cap); D_dprintf("alloc cap %lu (sz %lu == 0?), spill %lu", cap, mem.size(), spill_at()); } - inline dynamic_spill_vector(const dynamic_spill_vector& c) = delete; - inline dynamic_spill_vector(dynamic_spill_vector&& m) : + inline shunt(const shunt& c) = delete; + inline shunt(shunt&& m) : _spill_at(m._spill_at), mem(std::move(m.mem)), fil(std::move(m.fil)){} inline void push_back(T&& value) override { - if(size()>=spill_at()) { - D_dprintf("Spilling: sz %lu, spl: %lu", size(), spill_at()); - fil.push_back(std::move(value)); + if(is_full()) { + spl()->push_back(std::move(value)); } else mem.push_back(std::move(value)); } inline void pop_back() override { - if(fil.size()) fil.pop_back(); - else mem.pop_back(); + if(is_full() && spl()->size()) spl()->pop_back(); + else mem.pop_back(); } inline const T& back() const override { - if(fil.size()) return fil.back(); - else return mem.back(); + if(is_full() && spl()->size()) return spl()->back(); + else return mem.back(); } inline T& back() override { - if(fil.size()) return fil.back(); - else return mem.back(); + if(is_full() && spl()->size()) return spl()->back(); + else return mem.back(); } - inline const std::size_t size() const override { return mem.size() + fil.size(); } + inline const std::size_t size() const override { return mem.size() + (fil ? fil->size() : 0); } inline const std::size_t spill_at() const { return _spill_at; } + inline bool is_spilling() const { return is_full(); } +protected: + inline bool is_full() const override { return size()>=spill_at(); } private: + inline const spill_type* spl() const + { + if(is_full()) { + if(!fil) fil = std::make_unique(); + return fil.get(); + } else { + return fil.get(); + } + } + inline spill_type* spl() + { + if(is_full()) { + if(!fil) fil = std::make_unique(); + return fil.get(); + } else { + return fil.get(); + } + } std::size_t _spill_at; std::vector mem; - file_vector fil; + mutable std::unique_ptr fil; }; + +template +using dynamic_spill_vector = shunt >;