Repository: incubator-quickstep Updated Branches: refs/heads/inline-memcpy [created] 3fcbd5d78
Initital update Project: http://git-wip-us.apache.org/repos/asf/incubator-quickstep/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-quickstep/commit/07cff2d6 Tree: http://git-wip-us.apache.org/repos/asf/incubator-quickstep/tree/07cff2d6 Diff: http://git-wip-us.apache.org/repos/asf/incubator-quickstep/diff/07cff2d6 Branch: refs/heads/inline-memcpy Commit: 07cff2d640e3a00fe9a12fb9b05836f3a79dc758 Parents: 17ffbb0 Author: Jianqiao Zhu <jianq...@cs.wisc.edu> Authored: Sat Oct 15 15:46:13 2016 -0500 Committer: Jianqiao Zhu <jianq...@cs.wisc.edu> Committed: Sat Oct 15 15:46:13 2016 -0500 ---------------------------------------------------------------------- .../BasicColumnStoreTupleStorageSubBlock.cpp | 58 +++++++------- storage/CMakeLists.txt | 3 + storage/PackedRowStoreTupleStorageSubBlock.cpp | 37 +++++---- storage/SplitRowStoreTupleStorageSubBlock.cpp | 70 ++++++++--------- utility/CMakeLists.txt | 2 + utility/InlineMemcpy.hpp | 80 ++++++++++++++++++++ 6 files changed, 167 insertions(+), 83 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/07cff2d6/storage/BasicColumnStoreTupleStorageSubBlock.cpp ---------------------------------------------------------------------- diff --git a/storage/BasicColumnStoreTupleStorageSubBlock.cpp b/storage/BasicColumnStoreTupleStorageSubBlock.cpp index 34a1620..a62ab02 100644 --- a/storage/BasicColumnStoreTupleStorageSubBlock.cpp +++ b/storage/BasicColumnStoreTupleStorageSubBlock.cpp @@ -20,7 +20,6 @@ #include "storage/BasicColumnStoreTupleStorageSubBlock.hpp" #include <cstddef> -#include <cstring> #include <unordered_map> #include <utility> #include <vector> @@ -49,6 +48,7 @@ #include "types/operations/comparisons/ComparisonID.hpp" #include "types/operations/comparisons/ComparisonUtil.hpp" #include "utility/BitVector.hpp" +#include "utility/InlineMemcpy.hpp" #include "utility/Macros.hpp" #include "utility/PtrMap.hpp" #include "utility/PtrVector.hpp" @@ -56,7 +56,6 @@ #include "glog/logging.h" -using std::memcpy; using std::memmove; using std::size_t; using std::vector; @@ -298,16 +297,16 @@ tuple_id BasicColumnStoreTupleStorageSubBlock::bulkInsertTuples(ValueAccessor *a if (attr_value == nullptr) { column_null_bitmaps_[attr_id].setBit(header_->num_tuples, true); } else { - memcpy(static_cast<char*>(column_stripes_[attr_id]) - + header_->num_tuples * attr_size, - attr_value, - attr_size); + InlineMemcpy(static_cast<char*>(column_stripes_[attr_id]) + + header_->num_tuples * attr_size, + attr_value, + attr_size); } } else { - memcpy(static_cast<char*>(column_stripes_[attr_id]) - + header_->num_tuples * attr_size, - accessor->template getUntypedValue<false>(accessor_attr_id), - attr_size); + InlineMemcpy(static_cast<char*>(column_stripes_[attr_id]) + + header_->num_tuples * attr_size, + accessor->template getUntypedValue<false>(accessor_attr_id), + attr_size); } ++accessor_attr_id; } @@ -320,10 +319,10 @@ tuple_id BasicColumnStoreTupleStorageSubBlock::bulkInsertTuples(ValueAccessor *a attr_it != relation_.end(); ++attr_it) { const std::size_t attr_size = attr_it->getType().maximumByteLength(); - memcpy(static_cast<char*>(column_stripes_[attr_it->getID()]) - + header_->num_tuples * attr_size, - accessor->template getUntypedValue<false>(accessor_attr_id), - attr_size); + InlineMemcpy(static_cast<char*>(column_stripes_[attr_it->getID()]) + + header_->num_tuples * attr_size, + accessor->template getUntypedValue<false>(accessor_attr_id), + attr_size); ++accessor_attr_id; } ++(header_->num_tuples); @@ -361,13 +360,13 @@ tuple_id BasicColumnStoreTupleStorageSubBlock::bulkInsertTuplesWithRemappedAttri if (attr_value == nullptr) { column_null_bitmaps_[attr_id].setBit(header_->num_tuples, true); } else { - memcpy(static_cast<char*>(column_stripes_[attr_id]) + InlineMemcpy(static_cast<char*>(column_stripes_[attr_id]) + header_->num_tuples * attr_size, attr_value, attr_size); } } else { - memcpy(static_cast<char*>(column_stripes_[attr_id]) + InlineMemcpy(static_cast<char*>(column_stripes_[attr_id]) + header_->num_tuples * attr_size, accessor->template getUntypedValue<false>(*attribute_map_it), attr_size); @@ -383,7 +382,7 @@ tuple_id BasicColumnStoreTupleStorageSubBlock::bulkInsertTuplesWithRemappedAttri attr_it != relation_.end(); ++attr_it) { const std::size_t attr_size = attr_it->getType().maximumByteLength(); - memcpy(static_cast<char*>(column_stripes_[attr_it->getID()]) + InlineMemcpy(static_cast<char*>(column_stripes_[attr_it->getID()]) + header_->num_tuples * attr_size, accessor->template getUntypedValue<false>(*attribute_map_it), attr_size); @@ -793,7 +792,7 @@ bool BasicColumnStoreTupleStorageSubBlock::rebuildInternal() { // Clear out the tail, which will be reorganized. if (ordered_prefix_tuples > 0) { - memcpy(null_bitmap_buffers.back().get(), bitmap_location, bitmap_required_bytes); + InlineMemcpy(null_bitmap_buffers.back().get(), bitmap_location, bitmap_required_bytes); new_null_bitmaps.back().setBitRange(ordered_prefix_tuples, num_tuples - ordered_prefix_tuples, false); @@ -818,11 +817,12 @@ bool BasicColumnStoreTupleStorageSubBlock::rebuildInternal() { for (tuple_id unordered_tuple_num = 0; unordered_tuple_num < num_tuples - ordered_prefix_tuples; ++unordered_tuple_num) { - memcpy(static_cast<char*>(column_stripe_buffers[attr_id].get()) - + unordered_tuple_num * attr_length, - static_cast<char*>(column_stripes_[attr_id]) + - sort_column_values[ordered_prefix_tuples + unordered_tuple_num].getTupleID() * attr_length, - attr_length); + InlineMemcpy(static_cast<char*>(column_stripe_buffers[attr_id].get()) + + unordered_tuple_num * attr_length, + static_cast<char*>(column_stripes_[attr_id]) + + sort_column_values[ordered_prefix_tuples + unordered_tuple_num].getTupleID() + * attr_length, + attr_length); } if (!new_null_bitmaps.elementIsNull(attr_id)) { @@ -844,14 +844,14 @@ bool BasicColumnStoreTupleStorageSubBlock::rebuildInternal() { attr_it != relation_.end(); ++attr_it) { size_t attr_length = attr_it->getType().maximumByteLength(); - memcpy(static_cast<char*>(column_stripes_[attr_it->getID()]) + ordered_prefix_tuples * attr_length, - column_stripe_buffers[attr_it->getID()].get(), - (num_tuples - ordered_prefix_tuples) * attr_length); + InlineMemcpy(static_cast<char*>(column_stripes_[attr_it->getID()]) + ordered_prefix_tuples * attr_length, + column_stripe_buffers[attr_it->getID()].get(), + (num_tuples - ordered_prefix_tuples) * attr_length); if (!null_bitmap_buffers.elementIsNull(attr_it->getID())) { - std::memcpy(bitmap_location, - null_bitmap_buffers[attr_it->getID()].get(), - bitmap_required_bytes); + InlineMemcpy(bitmap_location, + null_bitmap_buffers[attr_it->getID()].get(), + bitmap_required_bytes); bitmap_location += bitmap_required_bytes; } } http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/07cff2d6/storage/CMakeLists.txt ---------------------------------------------------------------------- diff --git a/storage/CMakeLists.txt b/storage/CMakeLists.txt index f05cc46..798c04b 100644 --- a/storage/CMakeLists.txt +++ b/storage/CMakeLists.txt @@ -329,6 +329,7 @@ target_link_libraries(quickstep_storage_BasicColumnStoreTupleStorageSubBlock quickstep_types_operations_comparisons_ComparisonID quickstep_types_operations_comparisons_ComparisonUtil quickstep_utility_BitVector + quickstep_utility_InlineMemcpy quickstep_utility_Macros quickstep_utility_PtrMap quickstep_utility_PtrVector @@ -840,6 +841,7 @@ target_link_libraries(quickstep_storage_PackedRowStoreTupleStorageSubBlock quickstep_types_TypedValue quickstep_types_containers_Tuple quickstep_utility_BitVector + quickstep_utility_InlineMemcpy quickstep_utility_Macros) target_link_libraries(quickstep_storage_PackedRowStoreValueAccessor quickstep_catalog_CatalogRelationSchema @@ -937,6 +939,7 @@ target_link_libraries(quickstep_storage_SplitRowStoreTupleStorageSubBlock quickstep_storage_ValueAccessorUtil quickstep_types_TypedValue quickstep_utility_BitVector + quickstep_utility_InlineMemcpy quickstep_utility_Macros quickstep_utility_ScopedBuffer) target_link_libraries(quickstep_storage_SplitRowStoreValueAccessor http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/07cff2d6/storage/PackedRowStoreTupleStorageSubBlock.cpp ---------------------------------------------------------------------- diff --git a/storage/PackedRowStoreTupleStorageSubBlock.cpp b/storage/PackedRowStoreTupleStorageSubBlock.cpp index 0ad4a4c..4ef3f4f 100644 --- a/storage/PackedRowStoreTupleStorageSubBlock.cpp +++ b/storage/PackedRowStoreTupleStorageSubBlock.cpp @@ -20,7 +20,6 @@ #include "storage/PackedRowStoreTupleStorageSubBlock.hpp" #include <cstddef> -#include <cstring> #include <vector> #include "catalog/CatalogAttribute.hpp" @@ -38,10 +37,10 @@ #include "types/TypedValue.hpp" #include "types/containers/Tuple.hpp" #include "utility/BitVector.hpp" +#include "utility/InlineMemcpy.hpp" #include "utility/Macros.hpp" using std::vector; -using std::memcpy; using std::size_t; namespace quickstep { @@ -164,12 +163,12 @@ tuple_id PackedRowStoreTupleStorageSubBlock::bulkInsertTuples(ValueAccessor *acc header_->num_tuples * num_nullable_attrs + nullable_idx, true); } else { - memcpy(dest_addr, attr_value, attr_size); + InlineMemcpy(dest_addr, attr_value, attr_size); } } else { - memcpy(dest_addr, - accessor->template getUntypedValue<false>(curr_attr), - attr_size); + InlineMemcpy(dest_addr, + accessor->template getUntypedValue<false>(curr_attr), + attr_size); } dest_addr += attr_size; } @@ -184,15 +183,15 @@ tuple_id PackedRowStoreTupleStorageSubBlock::bulkInsertTuples(ValueAccessor *acc const std::size_t attrs_total_size = relation_.getMaximumByteLength(); while (this->hasSpaceToInsert<false>(1) && accessor->next()) { if (fast_copy) { - memcpy(dest_addr, - accessor->template getUntypedValue<false>(0), - attrs_total_size); + InlineMemcpy(dest_addr, + accessor->template getUntypedValue<false>(0), + attrs_total_size); } else { for (std::size_t curr_attr = 0; curr_attr < num_attrs; ++curr_attr) { const std::size_t attr_size = attrs_max_size[curr_attr]; - memcpy(dest_addr, - accessor->template getUntypedValue<false>(curr_attr), - attr_size); + InlineMemcpy(dest_addr, + accessor->template getUntypedValue<false>(curr_attr), + attr_size); dest_addr += attr_size; } } @@ -235,12 +234,12 @@ tuple_id PackedRowStoreTupleStorageSubBlock::bulkInsertTuplesWithRemappedAttribu header_->num_tuples * num_nullable_attrs + nullable_idx, true); } else { - memcpy(dest_addr, attr_value, attr_size); + InlineMemcpy(dest_addr, attr_value, attr_size); } } else { - memcpy(dest_addr, - accessor->template getUntypedValue<false>(attribute_map[curr_attr]), - attr_size); + InlineMemcpy(dest_addr, + accessor->template getUntypedValue<false>(attribute_map[curr_attr]), + attr_size); } dest_addr += attr_size; } @@ -250,9 +249,9 @@ tuple_id PackedRowStoreTupleStorageSubBlock::bulkInsertTuplesWithRemappedAttribu while (this->hasSpaceToInsert<false>(1) && accessor->next()) { for (std::size_t curr_attr = 0; curr_attr < num_attrs; ++curr_attr) { const std::size_t attr_size = attrs_max_size[curr_attr]; - memcpy(dest_addr, - accessor->template getUntypedValue<false>(attribute_map[curr_attr]), - attr_size); + InlineMemcpy(dest_addr, + accessor->template getUntypedValue<false>(attribute_map[curr_attr]), + attr_size); dest_addr += attr_size; } ++(header_->num_tuples); http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/07cff2d6/storage/SplitRowStoreTupleStorageSubBlock.cpp ---------------------------------------------------------------------- diff --git a/storage/SplitRowStoreTupleStorageSubBlock.cpp b/storage/SplitRowStoreTupleStorageSubBlock.cpp index f955c99..3a14a09 100644 --- a/storage/SplitRowStoreTupleStorageSubBlock.cpp +++ b/storage/SplitRowStoreTupleStorageSubBlock.cpp @@ -21,7 +21,6 @@ #include <cstddef> #include <cstdint> -#include <cstring> #include <utility> #include <vector> @@ -34,6 +33,7 @@ #include "storage/ValueAccessorUtil.hpp" #include "types/TypedValue.hpp" #include "utility/BitVector.hpp" +#include "utility/InlineMemcpy.hpp" #include "utility/Macros.hpp" #include "utility/ScopedBuffer.hpp" @@ -287,17 +287,17 @@ tuple_id SplitRowStoreTupleStorageSubBlock::bulkInsertTuples(ValueAccessor *acce if (attr_value == nullptr) { tuple_null_bitmap.setBit(nullable_idx, true); } else { - std::memcpy(fixed_length_attr_storage - + relation_.getFixedLengthAttributeOffset(attr_it->getID()), - attr_value, - attr_it->getType().maximumByteLength()); + InlineMemcpy(fixed_length_attr_storage + + relation_.getFixedLengthAttributeOffset(attr_it->getID()), + attr_value, + attr_it->getType().maximumByteLength()); } } else { const void *attr_value = accessor->template getUntypedValue<false>(accessor_attr_id); - std::memcpy(fixed_length_attr_storage - + relation_.getFixedLengthAttributeOffset(attr_it->getID()), - attr_value, - attr_it->getType().maximumByteLength()); + InlineMemcpy(fixed_length_attr_storage + + relation_.getFixedLengthAttributeOffset(attr_it->getID()), + attr_value, + attr_it->getType().maximumByteLength()); } } occupancy_bitmap_->setBit(pos, true); @@ -368,10 +368,10 @@ tuple_id SplitRowStoreTupleStorageSubBlock::bulkInsertTuples(ValueAccessor *acce attr_it != relation_.end(); ++attr_it, ++accessor_attr_id) { const void *attr_value = accessor->template getUntypedValue<false>(accessor_attr_id); - std::memcpy(fixed_length_attr_storage - + relation_.getFixedLengthAttributeOffset(attr_it->getID()), - attr_value, - attr_it->getType().maximumByteLength()); + InlineMemcpy(fixed_length_attr_storage + + relation_.getFixedLengthAttributeOffset(attr_it->getID()), + attr_value, + attr_it->getType().maximumByteLength()); } occupancy_bitmap_->setBit(pos, true); ++(header_->num_tuples); @@ -472,17 +472,17 @@ tuple_id SplitRowStoreTupleStorageSubBlock::bulkInsertTuplesWithRemappedAttribut if (attr_value == nullptr) { tuple_null_bitmap.setBit(nullable_idx, true); } else { - std::memcpy(fixed_length_attr_storage - + relation_.getFixedLengthAttributeOffset(attr_it->getID()), - attr_value, - attr_it->getType().maximumByteLength()); + InlineMemcpy(fixed_length_attr_storage + + relation_.getFixedLengthAttributeOffset(attr_it->getID()), + attr_value, + attr_it->getType().maximumByteLength()); } } else { const void *attr_value = accessor->template getUntypedValue<false>(*attr_map_it); - std::memcpy(fixed_length_attr_storage - + relation_.getFixedLengthAttributeOffset(attr_it->getID()), - attr_value, - attr_it->getType().maximumByteLength()); + InlineMemcpy(fixed_length_attr_storage + + relation_.getFixedLengthAttributeOffset(attr_it->getID()), + attr_value, + attr_it->getType().maximumByteLength()); } } occupancy_bitmap_->setBit(pos, true); @@ -552,10 +552,10 @@ tuple_id SplitRowStoreTupleStorageSubBlock::bulkInsertTuplesWithRemappedAttribut attr_it != relation_.end(); ++attr_it, ++attr_map_it) { const void *attr_value = accessor->template getUntypedValue<false>(*attr_map_it); - std::memcpy(fixed_length_attr_storage - + relation_.getFixedLengthAttributeOffset(attr_it->getID()), - attr_value, - attr_it->getType().maximumByteLength()); + InlineMemcpy(fixed_length_attr_storage + + relation_.getFixedLengthAttributeOffset(attr_it->getID()), + attr_value, + attr_it->getType().maximumByteLength()); } occupancy_bitmap_->setBit(pos, true); ++(header_->num_tuples); @@ -835,9 +835,9 @@ void SplitRowStoreTupleStorageSubBlock::rebuild() { std::size_t dest = occupancy_bitmap_->firstZero(); std::size_t src = occupancy_bitmap_->lastOne(header_->max_tid + 1); while (dest < static_cast<std::size_t>(header_->num_tuples)) { - std::memcpy(static_cast<char*>(tuple_storage_) + dest * tuple_slot_bytes_, - static_cast<char*>(tuple_storage_) + src * tuple_slot_bytes_, - tuple_slot_bytes_); + InlineMemcpy(static_cast<char*>(tuple_storage_) + dest * tuple_slot_bytes_, + static_cast<char*>(tuple_storage_) + src * tuple_slot_bytes_, + tuple_slot_bytes_); dest = occupancy_bitmap_->firstZero(dest + 1); src = occupancy_bitmap_->lastOne(src); } @@ -873,10 +873,10 @@ void SplitRowStoreTupleStorageSubBlock::rebuild() { const int variable_idx = relation_.getVariableLengthAttributeIndex(attr_it->getID()); if (variable_idx != -1) { // Copy into the temporary buffer. - std::memcpy(static_cast<char*>(packed_buffer.get()) + buffer_pos, - static_cast<char*>(tuple_storage_) - + variable_length_info_array[variable_idx << 1], - variable_length_info_array[(variable_idx << 1) + 1]); + InlineMemcpy(static_cast<char*>(packed_buffer.get()) + buffer_pos, + static_cast<char*>(tuple_storage_) + + variable_length_info_array[variable_idx << 1], + variable_length_info_array[(variable_idx << 1) + 1]); // Temporarily reset the offset entry in the slot to the offset in // the temp buffer (will be corrected in a second pass below). variable_length_info_array[variable_idx << 1] = buffer_pos; @@ -888,9 +888,9 @@ void SplitRowStoreTupleStorageSubBlock::rebuild() { if (buffer_pos != 0) { // Copy temporary packing buffer back into block. const std::uint32_t variable_start = tuple_storage_bytes_ - buffer_pos; - std::memcpy(static_cast<char*>(tuple_storage_) + variable_start, - packed_buffer.get(), - buffer_pos); + InlineMemcpy(static_cast<char*>(tuple_storage_) + variable_start, + packed_buffer.get(), + buffer_pos); // Correct offsets of variable-length attribute storage to point to the // actual location in the block. for (tuple_id tid = 0; tid < header_->num_tuples; ++tid) { http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/07cff2d6/utility/CMakeLists.txt ---------------------------------------------------------------------- diff --git a/utility/CMakeLists.txt b/utility/CMakeLists.txt index ddaae45..8765a57 100644 --- a/utility/CMakeLists.txt +++ b/utility/CMakeLists.txt @@ -174,6 +174,7 @@ add_library(quickstep_utility_ExecutionDAGVisualizer ExecutionDAGVisualizer.hpp) add_library(quickstep_utility_Glob Glob.cpp Glob.hpp) add_library(quickstep_utility_HashPair ../empty_src.cpp HashPair.hpp) +add_library(quickstep_utility_InlineMemcpy ../empty_src.cpp InlineMemcpy.hpp) add_library(quickstep_utility_Macros ../empty_src.cpp Macros.hpp) add_library(quickstep_utility_MemStream ../empty_src.cpp MemStream.hpp) add_library(quickstep_utility_PlanVisualizer PlanVisualizer.cpp PlanVisualizer.hpp) @@ -323,6 +324,7 @@ target_link_libraries(quickstep_utility quickstep_utility_ExecutionDAGVisualizer quickstep_utility_Glob quickstep_utility_HashPair + quickstep_utility_InlineMemcpy quickstep_utility_Macros quickstep_utility_MemStream quickstep_utility_PlanVisualizer http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/07cff2d6/utility/InlineMemcpy.hpp ---------------------------------------------------------------------- diff --git a/utility/InlineMemcpy.hpp b/utility/InlineMemcpy.hpp new file mode 100644 index 0000000..ff7ae83 --- /dev/null +++ b/utility/InlineMemcpy.hpp @@ -0,0 +1,80 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + **/ + +#ifndef QUICKSTEP_UTILITY_INLINE_MEMCPY_HPP_ +#define QUICKSTEP_UTILITY_INLINE_MEMCPY_HPP_ + +#include <cstring> + +namespace quickstep { + +/** \addtogroup Utility + * @{ + */ + +inline void InlineMemcpy(void *dst, const void *src, const std::size_t size) { +#define INLINE_ENTRY_(len) \ + case len: std::memcpy(dst, src, len); break + + switch (size) { + INLINE_ENTRY_(1); + INLINE_ENTRY_(2); + INLINE_ENTRY_(3); + INLINE_ENTRY_(4); + INLINE_ENTRY_(5); + INLINE_ENTRY_(6); + INLINE_ENTRY_(7); + INLINE_ENTRY_(8); + INLINE_ENTRY_(9); + INLINE_ENTRY_(10); + INLINE_ENTRY_(11); + INLINE_ENTRY_(12); + INLINE_ENTRY_(13); + INLINE_ENTRY_(14); + INLINE_ENTRY_(15); + INLINE_ENTRY_(16); + INLINE_ENTRY_(17); + INLINE_ENTRY_(18); + INLINE_ENTRY_(19); + INLINE_ENTRY_(20); + INLINE_ENTRY_(21); + INLINE_ENTRY_(22); + INLINE_ENTRY_(23); + INLINE_ENTRY_(24); + INLINE_ENTRY_(25); + INLINE_ENTRY_(26); + INLINE_ENTRY_(27); + INLINE_ENTRY_(28); + INLINE_ENTRY_(29); + INLINE_ENTRY_(30); + INLINE_ENTRY_(31); + INLINE_ENTRY_(32); + + default: + std::memcpy(dst, src, size); + } + +#undef INLINE_ENTRY_ +} + +/** @} */ + +} // namespace quickstep + +#endif // QUICKSTEP_UTILITY_INLINE_MEMCPY_HPP_