diff --git a/include/bitcoin/system/allocator.hpp b/include/bitcoin/system/allocator.hpp index 7bba9fd8cc..1b7f04a4a0 100644 --- a/include/bitcoin/system/allocator.hpp +++ b/include/bitcoin/system/allocator.hpp @@ -281,6 +281,26 @@ inline bool operator==(const allocator& left, using byte_allocator = allocator; +#define CREATE(Type, allocate, ...) \ + allocate.new_object(__VA_ARGS__), allocate.deleter(), allocate +#define POINTER(Type, allocate, ptr) \ + ptr, allocate.deleter(), allocate +#define INPLACE(ptr, Type, allocate, ...) \ + allocate.construct>(ptr, __VA_ARGS__, \ + allocate.deleter(), allocate) + +// TODO: replace above macros with parameter pack expansion. +////template +////auto shared_ptr(Allocator allocator, Args&&... args) NOEXCEPT +////{ +//// return std::make_tuple +//// ( +//// allocator.new_object(std::forward(args)...), +//// allocator.deleter(), +//// allocator +//// ); +////} + } // namespace libbitcoin #endif diff --git a/src/chain/block.cpp b/src/chain/block.cpp index 448af5f01a..33d5d84319 100644 --- a/src/chain/block.cpp +++ b/src/chain/block.cpp @@ -50,7 +50,7 @@ BC_PUSH_WARNING(NO_UNGUARDED_POINTERS) // ---------------------------------------------------------------------------- block::block() NOEXCEPT - : block(to_shared(), to_shared(), + : block(to_shared(), to_shared(), false) { } @@ -67,7 +67,7 @@ block::block(const chain::header& header, } block::block(const chain::header::cptr& header, - const chain::transactions_cptr& txs) NOEXCEPT + const transactions_cptr& txs) NOEXCEPT : block(header ? header : to_shared(), txs ? txs : to_shared(), true) { @@ -104,17 +104,15 @@ block::block(reader&& source, bool witness) NOEXCEPT } block::block(reader& source, bool witness) NOEXCEPT - : header_(source.get_allocator().new_object(source), - source.get_allocator().deleter()), - txs_(source.get_allocator().new_object(), - source.get_allocator().deleter()) + : header_(CREATE(chain::header, source.get_allocator(), source)), + txs_(CREATE(transaction_cptrs, source.get_allocator())) { assign_data(source, witness); } // protected block::block(const chain::header::cptr& header, - const chain::transactions_cptr& txs, bool valid) NOEXCEPT + const transactions_cptr& txs, bool valid) NOEXCEPT : header_(header), txs_(txs), valid_(valid), @@ -148,8 +146,7 @@ void block::assign_data(reader& source, bool witness) NOEXCEPT txs->reserve(count); for (size_t tx = 0; tx < count; ++tx) - txs->emplace_back(allocator.new_object(source, witness), - allocator.deleter()); + txs->emplace_back(CREATE(transaction, allocator, source, witness)); size_ = serialized_size(*txs_); valid_ = source; diff --git a/src/chain/input.cpp b/src/chain/input.cpp index 776f86d514..3ce4f4c45a 100644 --- a/src/chain/input.cpp +++ b/src/chain/input.cpp @@ -176,11 +176,9 @@ input::input(reader&& source) NOEXCEPT // Witness is deserialized and assigned by transaction. input::input(reader& source) NOEXCEPT - : point_(source.get_allocator().new_object(source), - source.get_allocator().deleter()), - script_(source.get_allocator().new_object(source, true), - source.get_allocator().deleter()), - witness_(nullptr), + : point_(CREATE(chain::point, source.get_allocator(), source)), + script_(CREATE(chain::script, source.get_allocator(), source, true)), + witness_(CREATE(chain::witness, source.get_allocator())), sequence_(source.read_4_bytes_little_endian()), valid_(source), size_(serialized_size(*script_)) @@ -303,10 +301,7 @@ size_t input::witnessed_size() const NOEXCEPT void input::set_witness(reader& source) NOEXCEPT { auto& allocator = source.get_allocator(); - - witness_.reset(allocator.new_object(source, true), - allocator.deleter()); - + witness_.reset(CREATE(chain::witness, allocator, source, true)); size_.witnessed = ceilinged_add(size_.nominal, witness_->serialized_size(true)); } diff --git a/src/chain/operation.cpp b/src/chain/operation.cpp index 37ed26226b..6aafff8bf3 100644 --- a/src/chain/operation.cpp +++ b/src/chain/operation.cpp @@ -198,7 +198,7 @@ void operation::assign_data(reader& source) NOEXCEPT // Guard against resetting a previously-invalid stream. if (!source) { - allocator.construct(&data_, nullptr); + INPLACE(&data_, data_chunk, allocator, nullptr); return; } @@ -221,9 +221,7 @@ void operation::assign_data(reader& source) NOEXCEPT source.invalidate(); // An invalid source.read_bytes_raw returns nullptr. - allocator.construct(&data_, source.read_bytes_raw(size), - allocator.deleter()); - + INPLACE(&data_, data_chunk, allocator, source.read_bytes_raw(size)); underflow_ = !source; // This requires that provided stream terminates at the end of the script. @@ -236,7 +234,7 @@ void operation::assign_data(reader& source) NOEXCEPT { code_ = any_invalid; source.set_position(start); - data_ = to_shared(source.read_bytes()); + data_.reset(POINTER(data_chunk, allocator, source.read_bytes_raw())); } // All byte vectors are deserializable, stream indicates own failure. diff --git a/src/chain/output.cpp b/src/chain/output.cpp index acc46612b9..dcbef57b89 100644 --- a/src/chain/output.cpp +++ b/src/chain/output.cpp @@ -92,8 +92,7 @@ output::output(reader&& source) NOEXCEPT output::output(reader& source) NOEXCEPT : value_(source.read_8_bytes_little_endian()), - script_(source.get_allocator().new_object(source, true), - source.get_allocator().deleter()), + script_(CREATE(chain::script, source.get_allocator(), source, true)), valid_(source), size_(serialized_size(*script_, value_)) { diff --git a/src/chain/transaction.cpp b/src/chain/transaction.cpp index 5b0051cc22..c270817f12 100644 --- a/src/chain/transaction.cpp +++ b/src/chain/transaction.cpp @@ -131,10 +131,8 @@ transaction::transaction(reader&& source, bool witness) NOEXCEPT transaction::transaction(reader& source, bool witness) NOEXCEPT : version_(source.read_4_bytes_little_endian()), - inputs_(source.get_allocator().new_object(), - source.get_allocator().deleter()), - outputs_(source.get_allocator().new_object(), - source.get_allocator().deleter()) + inputs_(CREATE(input_cptrs, source.get_allocator())), + outputs_(CREATE(output_cptrs, source.get_allocator())) { assign_data(source, witness); } @@ -184,9 +182,7 @@ void transaction::assign_data(reader& source, bool witness) NOEXCEPT auto count = source.read_size(max_block_size); ins->reserve(count); for (size_t in = 0; in < count; ++in) - ins->emplace_back( - allocator.new_object(source), - allocator.deleter()); + ins->emplace_back(CREATE(input, allocator, source)); // Expensive repeated recomputation, so cache segregated state. // Detect witness as no inputs (marker) and expected flag (bip144). @@ -202,15 +198,13 @@ void transaction::assign_data(reader& source, bool witness) NOEXCEPT count = source.read_size(max_block_size); ins->reserve(count); for (size_t in = 0; in < count; ++in) - ins->emplace_back(allocator.new_object(source), - allocator.deleter()); + ins->emplace_back(CREATE(input, allocator, source)); auto outs = to_non_const_raw_ptr(outputs_); count = source.read_size(max_block_size); outs->reserve(count); for (size_t out = 0; out < count; ++out) - outs->emplace_back(allocator.new_object(source), - allocator.deleter()); + outs->emplace_back(CREATE(output, allocator, source)); // Read or skip witnesses as specified. if (witness) @@ -231,8 +225,7 @@ void transaction::assign_data(reader& source, bool witness) NOEXCEPT count = source.read_size(max_block_size); outs->reserve(count); for (size_t out = 0; out < count; ++out) - outs->emplace_back(allocator.new_object(source), - allocator.deleter()); + outs->emplace_back(CREATE(output, allocator, source)); } locktime_ = source.read_4_bytes_little_endian(); diff --git a/src/chain/witness.cpp b/src/chain/witness.cpp index cfc5e09709..4da79e800c 100644 --- a/src/chain/witness.cpp +++ b/src/chain/witness.cpp @@ -177,8 +177,8 @@ void witness::assign_data(reader& source, bool prefix) NOEXCEPT for (size_t element = 0; element < count; ++element) { const auto size = source.read_size(max_block_weight); - stack_.emplace_back(source.read_bytes_raw(size), - allocator.deleter()); + stack_.emplace_back(POINTER(data_chunk, allocator, + source.read_bytes_raw(size))); size_ = element_size(size_, stack_.back()); } } @@ -187,8 +187,8 @@ void witness::assign_data(reader& source, bool prefix) NOEXCEPT while (!source.is_exhausted()) { const auto size = source.read_size(max_block_weight); - stack_.emplace_back(source.read_bytes_raw(size), - allocator.deleter()); + stack_.emplace_back(POINTER(data_chunk, allocator, + source.read_bytes_raw(size))); size_ = element_size(size_, stack_.back()); } }