treewide: update concepts language from the Concepts TS to C++20

Seastar recently lost support for the experimental Concepts Technical
Specification (TS) and gained support for C++20 concepts. Re-enable
concepts in Scylla by updating our use of concepts to the C++20
standard.

This change:
 - peels off uses of the GCC6_CONCEPT macro
 - removes inclusions of <seastar/gcc6-concepts.hh>
 - replaces function-style concepts (no longer supported) with
   equation-style concepts
 - semicolons added and removed as needed
 - deprecated std::is_pod replaced by recommended replacement
 - updates return type constraints to use concepts instead of
   type names (either std::same_as or std::convertible_to, with
   std::same_as chosen when possible)

No attempt is made to improve the concepts; this is a specification
update only.
Message-Id: <20200531110254.2555854-1-avi@scylladb.com>
This commit is contained in:
Avi Kivity
2020-05-31 14:02:54 +03:00
parent c77bc5bf51
commit a4c44cab88
61 changed files with 397 additions and 619 deletions

View File

@@ -134,10 +134,6 @@ add_executable(scylla
${SEASTAR_SOURCE_FILES}
${SCYLLA_SOURCE_FILES})
# Note that since CLion does not undestand GCC6 concepts, we always disable them (even if users configure otherwise).
# CLion seems to have trouble with `-U` (macro undefinition), so we do it this way instead.
list(REMOVE_ITEM SEASTAR_CFLAGS "-DHAVE_GCC6_CONCEPTS")
# If the Seastar pkg-config information is available, append to the default flags.
#
# For ease of browsing the source code, we always pretend that DPDK is enabled.

View File

@@ -29,7 +29,6 @@
#include <seastar/net//byteorder.hh>
#include <cstdint>
#include <iosfwd>
#include <seastar/util/gcc6-concepts.hh>
#include "data/cell.hh"
#include "data/schema_info.hh"
#include "imr/utils.hh"

View File

@@ -122,26 +122,26 @@ public:
return {_empty_prefix, bound_kind::incl_end};
}
template<template<typename> typename R>
GCC6_CONCEPT( requires Range<R, clustering_key_prefix_view> )
requires Range<R, clustering_key_prefix_view>
static bound_view from_range_start(const R<clustering_key_prefix>& range) {
return range.start()
? bound_view(range.start()->value(), range.start()->is_inclusive() ? bound_kind::incl_start : bound_kind::excl_start)
: bottom();
}
template<template<typename> typename R>
GCC6_CONCEPT( requires Range<R, clustering_key_prefix> )
requires Range<R, clustering_key_prefix>
static bound_view from_range_end(const R<clustering_key_prefix>& range) {
return range.end()
? bound_view(range.end()->value(), range.end()->is_inclusive() ? bound_kind::incl_end : bound_kind::excl_end)
: top();
}
template<template<typename> typename R>
GCC6_CONCEPT( requires Range<R, clustering_key_prefix> )
requires Range<R, clustering_key_prefix>
static std::pair<bound_view, bound_view> from_range(const R<clustering_key_prefix>& range) {
return {from_range_start(range), from_range_end(range)};
}
template<template<typename> typename R>
GCC6_CONCEPT( requires Range<R, clustering_key_prefix_view> )
requires Range<R, clustering_key_prefix_view>
static std::optional<typename R<clustering_key_prefix_view>::bound> to_range_bound(const bound_view& bv) {
if (&bv._prefix.get() == &_empty_prefix) {
return {};

View File

@@ -61,7 +61,7 @@ bool collection_mutation_view::is_empty() const {
}
template <typename F>
GCC6_CONCEPT(requires std::is_invocable_r_v<const data::type_info&, F, collection_mutation_input_stream&>)
requires std::is_invocable_r_v<const data::type_info&, F, collection_mutation_input_stream&>
static bool is_any_live(const atomic_cell_value_view& data, tombstone tomb, gc_clock::time_point now, F&& read_cell_type_info) {
auto in = collection_mutation_input_stream(data);
auto has_tomb = in.read_trivial<bool>();
@@ -108,7 +108,7 @@ bool collection_mutation_view::is_any_live(const abstract_type& type, tombstone
}
template <typename F>
GCC6_CONCEPT(requires std::is_invocable_r_v<const data::type_info&, F, collection_mutation_input_stream&>)
requires std::is_invocable_r_v<const data::type_info&, F, collection_mutation_input_stream&>
static api::timestamp_type last_update(const atomic_cell_value_view& data, F&& read_cell_type_info) {
auto in = collection_mutation_input_stream(data);
api::timestamp_type max = api::missing_timestamp;
@@ -313,7 +313,7 @@ collection_mutation collection_mutation_view_description::serialize(const abstra
}
template <typename C>
GCC6_CONCEPT(requires std::is_base_of_v<abstract_type, std::remove_reference_t<C>>)
requires std::is_base_of_v<abstract_type, std::remove_reference_t<C>>
static collection_mutation_view_description
merge(collection_mutation_view_description a, collection_mutation_view_description b, C&& key_type) {
using element_type = std::pair<bytes_view, atomic_cell_view>;
@@ -375,7 +375,7 @@ collection_mutation merge(const abstract_type& type, collection_mutation_view a,
}
template <typename C>
GCC6_CONCEPT(requires std::is_base_of_v<abstract_type, std::remove_reference_t<C>>)
requires std::is_base_of_v<abstract_type, std::remove_reference_t<C>>
static collection_mutation_view_description
difference(collection_mutation_view_description a, collection_mutation_view_description b, C&& key_type)
{
@@ -421,7 +421,7 @@ collection_mutation difference(const abstract_type& type, collection_mutation_vi
}
template <typename F>
GCC6_CONCEPT(requires std::is_invocable_r_v<std::pair<bytes_view, atomic_cell_view>, F, collection_mutation_input_stream&>)
requires std::is_invocable_r_v<std::pair<bytes_view, atomic_cell_view>, F, collection_mutation_input_stream&>
static collection_mutation_view_description
deserialize_collection_mutation(collection_mutation_input_stream& in, F&& read_kv) {
collection_mutation_view_description ret;

View File

@@ -152,41 +152,39 @@ struct uuid_type_impl final : public concrete_type<utils::UUID> {
template <typename Func> using visit_ret_type = std::invoke_result_t<Func, const ascii_type_impl&>;
GCC6_CONCEPT(
template <typename Func> concept bool CanHandleAllTypes = requires(Func f) {
{ f(*static_cast<const ascii_type_impl*>(nullptr)) } -> visit_ret_type<Func>;
{ f(*static_cast<const boolean_type_impl*>(nullptr)) } -> visit_ret_type<Func>;
{ f(*static_cast<const byte_type_impl*>(nullptr)) } -> visit_ret_type<Func>;
{ f(*static_cast<const bytes_type_impl*>(nullptr)) } -> visit_ret_type<Func>;
{ f(*static_cast<const counter_type_impl*>(nullptr)) } -> visit_ret_type<Func>;
{ f(*static_cast<const date_type_impl*>(nullptr)) } -> visit_ret_type<Func>;
{ f(*static_cast<const decimal_type_impl*>(nullptr)) } -> visit_ret_type<Func>;
{ f(*static_cast<const double_type_impl*>(nullptr)) } -> visit_ret_type<Func>;
{ f(*static_cast<const duration_type_impl*>(nullptr)) } -> visit_ret_type<Func>;
{ f(*static_cast<const empty_type_impl*>(nullptr)) } -> visit_ret_type<Func>;
{ f(*static_cast<const float_type_impl*>(nullptr)) } -> visit_ret_type<Func>;
{ f(*static_cast<const inet_addr_type_impl*>(nullptr)) } -> visit_ret_type<Func>;
{ f(*static_cast<const int32_type_impl*>(nullptr)) } -> visit_ret_type<Func>;
{ f(*static_cast<const list_type_impl*>(nullptr)) } -> visit_ret_type<Func>;
{ f(*static_cast<const long_type_impl*>(nullptr)) } -> visit_ret_type<Func>;
{ f(*static_cast<const map_type_impl*>(nullptr)) } -> visit_ret_type<Func>;
{ f(*static_cast<const reversed_type_impl*>(nullptr)) } -> visit_ret_type<Func>;
{ f(*static_cast<const set_type_impl*>(nullptr)) } -> visit_ret_type<Func>;
{ f(*static_cast<const short_type_impl*>(nullptr)) } -> visit_ret_type<Func>;
{ f(*static_cast<const simple_date_type_impl*>(nullptr)) } -> visit_ret_type<Func>;
{ f(*static_cast<const time_type_impl*>(nullptr)) } -> visit_ret_type<Func>;
{ f(*static_cast<const timestamp_type_impl*>(nullptr)) } -> visit_ret_type<Func>;
{ f(*static_cast<const timeuuid_type_impl*>(nullptr)) } -> visit_ret_type<Func>;
{ f(*static_cast<const tuple_type_impl*>(nullptr)) } -> visit_ret_type<Func>;
{ f(*static_cast<const user_type_impl*>(nullptr)) } -> visit_ret_type<Func>;
{ f(*static_cast<const utf8_type_impl*>(nullptr)) } -> visit_ret_type<Func>;
{ f(*static_cast<const uuid_type_impl*>(nullptr)) } -> visit_ret_type<Func>;
{ f(*static_cast<const varint_type_impl*>(nullptr)) } -> visit_ret_type<Func>;
template <typename Func> concept CanHandleAllTypes = requires(Func f) {
{ f(*static_cast<const ascii_type_impl*>(nullptr)) } -> std::same_as<visit_ret_type<Func>>;
{ f(*static_cast<const boolean_type_impl*>(nullptr)) } -> std::same_as<visit_ret_type<Func>>;
{ f(*static_cast<const byte_type_impl*>(nullptr)) } -> std::same_as<visit_ret_type<Func>>;
{ f(*static_cast<const bytes_type_impl*>(nullptr)) } -> std::same_as<visit_ret_type<Func>>;
{ f(*static_cast<const counter_type_impl*>(nullptr)) } -> std::same_as<visit_ret_type<Func>>;
{ f(*static_cast<const date_type_impl*>(nullptr)) } -> std::same_as<visit_ret_type<Func>>;
{ f(*static_cast<const decimal_type_impl*>(nullptr)) } -> std::same_as<visit_ret_type<Func>>;
{ f(*static_cast<const double_type_impl*>(nullptr)) } -> std::same_as<visit_ret_type<Func>>;
{ f(*static_cast<const duration_type_impl*>(nullptr)) } -> std::same_as<visit_ret_type<Func>>;
{ f(*static_cast<const empty_type_impl*>(nullptr)) } -> std::same_as<visit_ret_type<Func>>;
{ f(*static_cast<const float_type_impl*>(nullptr)) } -> std::same_as<visit_ret_type<Func>>;
{ f(*static_cast<const inet_addr_type_impl*>(nullptr)) } -> std::same_as<visit_ret_type<Func>>;
{ f(*static_cast<const int32_type_impl*>(nullptr)) } -> std::same_as<visit_ret_type<Func>>;
{ f(*static_cast<const list_type_impl*>(nullptr)) } -> std::same_as<visit_ret_type<Func>>;
{ f(*static_cast<const long_type_impl*>(nullptr)) } -> std::same_as<visit_ret_type<Func>>;
{ f(*static_cast<const map_type_impl*>(nullptr)) } -> std::same_as<visit_ret_type<Func>>;
{ f(*static_cast<const reversed_type_impl*>(nullptr)) } -> std::same_as<visit_ret_type<Func>>;
{ f(*static_cast<const set_type_impl*>(nullptr)) } -> std::same_as<visit_ret_type<Func>>;
{ f(*static_cast<const short_type_impl*>(nullptr)) } -> std::same_as<visit_ret_type<Func>>;
{ f(*static_cast<const simple_date_type_impl*>(nullptr)) } -> std::same_as<visit_ret_type<Func>>;
{ f(*static_cast<const time_type_impl*>(nullptr)) } -> std::same_as<visit_ret_type<Func>>;
{ f(*static_cast<const timestamp_type_impl*>(nullptr)) } -> std::same_as<visit_ret_type<Func>>;
{ f(*static_cast<const timeuuid_type_impl*>(nullptr)) } -> std::same_as<visit_ret_type<Func>>;
{ f(*static_cast<const tuple_type_impl*>(nullptr)) } -> std::same_as<visit_ret_type<Func>>;
{ f(*static_cast<const user_type_impl*>(nullptr)) } -> std::same_as<visit_ret_type<Func>>;
{ f(*static_cast<const utf8_type_impl*>(nullptr)) } -> std::same_as<visit_ret_type<Func>>;
{ f(*static_cast<const uuid_type_impl*>(nullptr)) } -> std::same_as<visit_ret_type<Func>>;
{ f(*static_cast<const varint_type_impl*>(nullptr)) } -> std::same_as<visit_ret_type<Func>>;
};
)
template<typename Func>
GCC6_CONCEPT(requires CanHandleAllTypes<Func>)
requires CanHandleAllTypes<Func>
static inline visit_ret_type<Func> visit(const abstract_type& t, Func&& f) {
switch (t.get_kind()) {
case abstract_type::kind::ascii:

View File

@@ -473,8 +473,6 @@ arg_parser.add_argument('--python', action='store', dest='python', default='pyth
help='Python3 path')
arg_parser.add_argument('--split-dwarf', dest='split_dwarf', action='store_true', default=False,
help='use of split dwarf (https://gcc.gnu.org/wiki/DebugFission) to speed up linking')
arg_parser.add_argument('--enable-gcc6-concepts', dest='gcc6_concepts', action='store_true', default=False,
help='enable experimental support for C++ Concepts as implemented in GCC 6')
arg_parser.add_argument('--enable-alloc-failure-injector', dest='alloc_failure_injector', action='store_true', default=False,
help='enable allocation failure injection')
arg_parser.add_argument('--with-antlr3', dest='antlr3_exec', action='store', default=None,
@@ -1250,8 +1248,6 @@ def configure_seastar(build_dir, mode):
if args.dpdk:
seastar_cmake_args += ['-DSeastar_DPDK=ON', '-DSeastar_DPDK_MACHINE=wsm']
if args.gcc6_concepts:
seastar_cmake_args += ['-DSeastar_GCC6_CONCEPTS=ON']
if args.split_dwarf:
seastar_cmake_args += ['-DSeastar_SPLIT_DWARF=ON']
if args.alloc_failure_injector:

View File

@@ -156,10 +156,10 @@ private:
// Shared logic for applying counter_shards and counter_shard_views.
// T is either counter_shard or basic_counter_shard_view<U>.
template<typename T>
GCC6_CONCEPT(requires requires(T shard) {
{ shard.value() } -> int64_t;
{ shard.logical_clock() } -> int64_t;
})
requires requires(T shard) {
{ shard.value() } -> std::same_as<int64_t>;
{ shard.logical_clock() } -> std::same_as<int64_t>;
}
counter_shard& do_apply(T&& other) noexcept {
auto other_clock = other.logical_clock();
if (_logical_clock < other_clock) {

View File

@@ -41,7 +41,7 @@
#pragma once
#include <seastar/util/gcc6-concepts.hh>
#include <concepts>
#include "timestamp.hh"
#include "bytes.hh"
#include "db/consistency_level_type.hh"
@@ -97,11 +97,11 @@ private:
* @param values_ranges a vector of values ranges for each statement in the batch.
*/
template<typename OneMutationDataRange>
GCC6_CONCEPT( requires requires (OneMutationDataRange range) {
requires requires (OneMutationDataRange range) {
std::begin(range);
std::end(range);
} && ( requires (OneMutationDataRange range) { { *range.begin() } -> raw_value_view; } ||
requires (OneMutationDataRange range) { { *range.begin() } -> raw_value; } ) )
} && ( requires (OneMutationDataRange range) { { *range.begin() } -> std::convertible_to<raw_value_view>; } ||
requires (OneMutationDataRange range) { { *range.begin() } -> std::convertible_to<raw_value>; } )
explicit query_options(query_options&& o, std::vector<OneMutationDataRange> values_ranges);
public:
@@ -145,11 +145,11 @@ public:
* @param values_ranges a vector of values ranges for each statement in the batch.
*/
template<typename OneMutationDataRange>
GCC6_CONCEPT( requires requires (OneMutationDataRange range) {
requires requires (OneMutationDataRange range) {
std::begin(range);
std::end(range);
} && ( requires (OneMutationDataRange range) { { *range.begin() } -> raw_value_view; } ||
requires (OneMutationDataRange range) { { *range.begin() } -> raw_value; } ) )
} && ( requires (OneMutationDataRange range) { { *range.begin() } -> std::convertible_to<raw_value_view>; } ||
requires (OneMutationDataRange range) { { *range.begin() } -> std::convertible_to<raw_value>; } )
static query_options make_batch_options(query_options&& o, std::vector<OneMutationDataRange> values_ranges) {
return query_options(std::move(o), std::move(values_ranges));
}
@@ -251,11 +251,11 @@ private:
};
template<typename OneMutationDataRange>
GCC6_CONCEPT( requires requires (OneMutationDataRange range) {
requires requires (OneMutationDataRange range) {
std::begin(range);
std::end(range);
} && ( requires (OneMutationDataRange range) { { *range.begin() } -> raw_value_view; } ||
requires (OneMutationDataRange range) { { *range.begin() } -> raw_value; } ) )
} && ( requires (OneMutationDataRange range) { { *range.begin() } -> std::convertible_to<raw_value_view>; } ||
requires (OneMutationDataRange range) { { *range.begin() } -> std::convertible_to<raw_value>; } )
query_options::query_options(query_options&& o, std::vector<OneMutationDataRange> values_ranges)
: query_options(std::move(o))
{

View File

@@ -50,7 +50,6 @@
#include "result_generator.hh"
#include <seastar/util/gcc6-concepts.hh>
namespace cql3 {
@@ -150,17 +149,13 @@ public:
const std::vector<uint16_t>& partition_key_bind_indices() const;
};
GCC6_CONCEPT(
template<typename Visitor>
concept bool ResultVisitor = requires(Visitor& visitor) {
concept ResultVisitor = requires(Visitor& visitor) {
visitor.start_row();
visitor.accept_value(std::optional<query::result_bytes_view>());
visitor.end_row();
};
)
class result_set {
::shared_ptr<metadata> _metadata;
std::deque<std::vector<bytes_opt>> _rows;
@@ -199,7 +194,7 @@ public:
const std::deque<std::vector<bytes_opt>>& rows() const;
template<typename Visitor>
GCC6_CONCEPT(requires ResultVisitor<Visitor>)
requires ResultVisitor<Visitor>
void visit(Visitor&& visitor) const {
auto column_count = get_metadata().column_count();
for (auto& row : _rows) {
@@ -264,7 +259,7 @@ public:
}
template<typename Visitor>
GCC6_CONCEPT(requires ResultVisitor<Visitor>)
requires ResultVisitor<Visitor>
void visit(Visitor&& visitor) const {
if (_result_set) {
_result_set->visit(std::forward<Visitor>(visitor));

View File

@@ -428,9 +428,7 @@ select_statement::do_execute(service::storage_proxy& proxy,
}
template<typename KeyType>
GCC6_CONCEPT(
requires (std::is_same_v<KeyType, partition_key> || std::is_same_v<KeyType, clustering_key_prefix>)
)
requires (std::is_same_v<KeyType, partition_key> || std::is_same_v<KeyType, clustering_key_prefix>)
static KeyType
generate_base_key_from_index_pk(const partition_key& index_pk, const std::optional<clustering_key>& index_ck, const schema& base_schema, const schema& view_schema) {
const auto& base_columns = std::is_same_v<KeyType, partition_key> ? base_schema.partition_key_columns() : base_schema.clustering_key_columns();
@@ -844,9 +842,7 @@ indexed_table_select_statement::indexed_table_select_statement(schema_ptr schema
}
template<typename KeyType>
GCC6_CONCEPT(
requires (std::is_same_v<KeyType, partition_key> || std::is_same_v<KeyType, clustering_key_prefix>)
)
requires (std::is_same_v<KeyType, partition_key> || std::is_same_v<KeyType, clustering_key_prefix>)
static void append_base_key_to_index_ck(std::vector<bytes_view>& exploded_index_ck, const KeyType& base_key, const column_definition& index_cdef) {
auto key_view = base_key.view();
auto begin = key_view.begin();

View File

@@ -292,12 +292,10 @@ public:
/// \arg data needs to remain valid as long as the writer is in use.
/// \returns imr::WriterAllocator for cell::structure.
template<typename FragmentRange, typename = std::enable_if_t<is_fragment_range_v<std::decay_t<FragmentRange>>>>
GCC6_CONCEPT(
requires std::is_nothrow_move_constructible_v<std::decay_t<FragmentRange>> &&
std::is_nothrow_copy_constructible_v<std::decay_t<FragmentRange>> &&
std::is_nothrow_copy_assignable_v<std::decay_t<FragmentRange>> &&
std::is_nothrow_move_assignable_v<std::decay_t<FragmentRange>>
)
requires std::is_nothrow_move_constructible_v<std::decay_t<FragmentRange>> &&
std::is_nothrow_copy_constructible_v<std::decay_t<FragmentRange>> &&
std::is_nothrow_copy_assignable_v<std::decay_t<FragmentRange>> &&
std::is_nothrow_move_assignable_v<std::decay_t<FragmentRange>>
static auto make_collection(FragmentRange data) noexcept {
return [data = std::move(data)] (auto&& serializer, auto&& allocations) noexcept {
return serializer

View File

@@ -86,12 +86,10 @@ public:
{ }
template<typename Serializer, typename Allocator>
GCC6_CONCEPT(
requires (imr::is_sizer_for_v<cell::variable_value::structure, Serializer>
&& std::is_same_v<Allocator, imr::alloc::object_allocator::sizer>)
|| (imr::is_serializer_for_v<cell::variable_value::structure, Serializer>
&& std::is_same_v<Allocator, imr::alloc::object_allocator::serializer>)
)
requires (imr::is_sizer_for_v<cell::variable_value::structure, Serializer>
&& std::is_same_v<Allocator, imr::alloc::object_allocator::sizer>)
|| (imr::is_serializer_for_v<cell::variable_value::structure, Serializer>
&& std::is_same_v<Allocator, imr::alloc::object_allocator::serializer>)
auto operator()(Serializer serializer, Allocator allocations) {
auto after_size = serializer.serialize(_value_size);
if (_force_internal || _value_size <= cell::maximum_internal_storage_length) {
@@ -134,14 +132,14 @@ public:
inline value_writer<empty_fragment_range> cell::variable_value::write(size_t value_size, bool force_internal) noexcept
{
GCC6_CONCEPT(static_assert(imr::WriterAllocator<value_writer<empty_fragment_range>, structure>));
static_assert(imr::WriterAllocator<value_writer<empty_fragment_range>, structure>);
return value_writer<empty_fragment_range>(empty_fragment_range(), value_size, force_internal);
}
template<typename FragmentRange>
inline value_writer<std::decay_t<FragmentRange>> cell::variable_value::write(FragmentRange&& value, bool force_internal) noexcept
{
GCC6_CONCEPT(static_assert(imr::WriterAllocator<value_writer<std::decay_t<FragmentRange>>, structure>));
static_assert(imr::WriterAllocator<value_writer<std::decay_t<FragmentRange>>, structure>);
return value_writer<std::decay_t<FragmentRange>>(std::forward<FragmentRange>(value), value.size_bytes(), force_internal);
}

View File

@@ -109,7 +109,7 @@ public:
return _c.process(reinterpret_cast<const uint8_t*>(data), size);
}
template<typename FragmentedBuffer>
GCC6_CONCEPT(requires FragmentRange<FragmentedBuffer>)
requires FragmentRange<FragmentedBuffer>
void process_fragmented(const FragmentedBuffer& buffer) {
return _c.process_fragmented(buffer);
}

View File

@@ -29,7 +29,6 @@
#include "mutation_fragment.hh"
#include "tracing/trace_state.hh"
#include <seastar/util/gcc6-concepts.hh>
#include <seastar/core/thread.hh>
#include <seastar/core/file.hh>
#include "db/timeout_clock.hh"
@@ -41,31 +40,27 @@ using seastar::future;
class mutation_source;
class reader_permit;
GCC6_CONCEPT(
template<typename Consumer>
concept bool FlatMutationReaderConsumer() {
return requires(Consumer c, mutation_fragment mf) {
{ c(std::move(mf)) } -> stop_iteration;
};
}
)
GCC6_CONCEPT(
template<typename T>
concept bool FlattenedConsumer() {
return StreamedMutationConsumer<T>() && requires(T obj, const dht::decorated_key& dk) {
obj.consume_new_partition(dk);
obj.consume_end_of_partition();
};
}
template<typename T>
concept bool FlattenedConsumerFilter = requires(T filter, const dht::decorated_key& dk, const mutation_fragment& mf) {
{ filter(dk) } -> bool;
{ filter(mf) } -> bool;
{ filter.on_end_of_stream() } -> void;
template<typename Consumer>
concept FlatMutationReaderConsumer =
requires(Consumer c, mutation_fragment mf) {
{ c(std::move(mf)) } -> std::same_as<stop_iteration>;
};
template<typename T>
concept FlattenedConsumer =
StreamedMutationConsumer<T> && requires(T obj, const dht::decorated_key& dk) {
{ obj.consume_new_partition(dk) };
{ obj.consume_end_of_partition() };
};
template<typename T>
concept FlattenedConsumerFilter =
requires(T filter, const dht::decorated_key& dk, const mutation_fragment& mf) {
{ filter(dk) } -> std::same_as<bool>;
{ filter(mf) } -> std::same_as<bool>;
{ filter.on_end_of_stream() } -> std::same_as<void>;
};
)
/*
* Allows iteration on mutations using mutation_fragments.
@@ -149,9 +144,7 @@ public:
}
template<typename Consumer>
GCC6_CONCEPT(
requires FlatMutationReaderConsumer<Consumer>()
)
requires FlatMutationReaderConsumer<Consumer>
// Stops when consumer returns stop_iteration::yes or end of stream is reached.
// Next call will start from the next mutation_fragment in the stream.
future<> consume_pausable(Consumer consumer, db::timeout_clock::time_point timeout) {
@@ -169,9 +162,7 @@ public:
}
template<typename Consumer, typename Filter>
GCC6_CONCEPT(
requires FlatMutationReaderConsumer<Consumer>() && FlattenedConsumerFilter<Filter>
)
requires FlatMutationReaderConsumer<Consumer> && FlattenedConsumerFilter<Filter>
// A variant of consume_pausable() that expects to be run in
// a seastar::thread.
// Partitions for which filter(decorated_key) returns false are skipped
@@ -246,9 +237,7 @@ public:
};
public:
template<typename Consumer>
GCC6_CONCEPT(
requires FlattenedConsumer<Consumer>()
)
requires FlattenedConsumer<Consumer>
// Stops when consumer returns stop_iteration::yes from consume_end_of_partition or end of stream is reached.
// Next call will receive fragments from the next partition.
// When consumer returns stop_iteration::yes from methods other than consume_end_of_partition then the read
@@ -270,9 +259,7 @@ public:
}
template<typename Consumer, typename Filter>
GCC6_CONCEPT(
requires FlattenedConsumer<Consumer>() && FlattenedConsumerFilter<Filter>
)
requires FlattenedConsumer<Consumer> && FlattenedConsumerFilter<Filter>
// A variant of consumee() that expects to be run in a seastar::thread.
// Partitions for which filter(decorated_key) returns false are skipped
// entirely and never reach the consumer.
@@ -333,17 +320,13 @@ public:
}
template <typename Consumer>
GCC6_CONCEPT(
requires FlatMutationReaderConsumer<Consumer>()
)
requires FlatMutationReaderConsumer<Consumer>
auto consume_pausable(Consumer consumer, db::timeout_clock::time_point timeout) {
return _impl->consume_pausable(std::move(consumer), timeout);
}
template <typename Consumer>
GCC6_CONCEPT(
requires FlattenedConsumer<Consumer>()
)
requires FlattenedConsumer<Consumer>
auto consume(Consumer consumer, db::timeout_clock::time_point timeout) {
return _impl->consume(std::move(consumer), timeout);
}
@@ -394,17 +377,13 @@ public:
};
template<typename Consumer, typename Filter>
GCC6_CONCEPT(
requires FlattenedConsumer<Consumer>() && FlattenedConsumerFilter<Filter>
)
requires FlattenedConsumer<Consumer> && FlattenedConsumerFilter<Filter>
auto consume_in_thread(Consumer consumer, Filter filter, db::timeout_clock::time_point timeout) {
return _impl->consume_in_thread(std::move(consumer), std::move(filter), timeout);
}
template<typename Consumer>
GCC6_CONCEPT(
requires FlattenedConsumer<Consumer>()
)
requires FlattenedConsumer<Consumer>
auto consume_in_thread(Consumer consumer, db::timeout_clock::time_point timeout) {
return consume_in_thread(std::move(consumer), no_filter{}, timeout);
}
@@ -528,11 +507,11 @@ flat_mutation_reader make_flat_mutation_reader(Args &&... args) {
// The consumer will stop iff StopCondition returns true, in particular
// reaching the end of stream alone won't stop the reader.
template<typename StopCondition, typename ConsumeMutationFragment, typename ConsumeEndOfStream>
GCC6_CONCEPT(requires requires(StopCondition stop, ConsumeMutationFragment consume_mf, ConsumeEndOfStream consume_eos, mutation_fragment mf) {
{ stop() } -> bool;
{ consume_mf(std::move(mf)) } -> void;
{ consume_eos() } -> future<>;
})
requires requires(StopCondition stop, ConsumeMutationFragment consume_mf, ConsumeEndOfStream consume_eos, mutation_fragment mf) {
{ stop() } -> std::same_as<bool>;
{ consume_mf(std::move(mf)) } -> std::same_as<void>;
{ consume_eos() } -> std::same_as<future<>>;
}
future<> consume_mutation_fragments_until(
flat_mutation_reader& r,
StopCondition&& stop,
@@ -555,9 +534,7 @@ future<> consume_mutation_fragments_until(
// Creates a stream which is like r but with transformation applied to the elements.
template<typename T>
GCC6_CONCEPT(
requires StreamedMutationTranformer<T>()
)
requires StreamedMutationTranformer<T>
flat_mutation_reader transform(flat_mutation_reader r, T t) {
class transforming_reader : public flat_mutation_reader::impl {
flat_mutation_reader _reader;

View File

@@ -24,10 +24,10 @@
#include <chrono>
#include <map>
#include <optional>
#include <concepts>
#include <seastar/core/byteorder.hh>
#include <seastar/core/sstring.hh>
#include "seastarx.hh"
#include <seastar/util/gcc6-concepts.hh>
//
// This hashing differs from std::hash<> in that it decouples knowledge about
@@ -42,14 +42,11 @@
// appending_hash<T> is machine-independent.
//
GCC6_CONCEPT(
template<typename H>
concept bool Hasher() {
return requires(H& h, const char* ptr, size_t size) {
{ h.update(ptr, size) } -> void;
};
}
)
template<typename H>
concept Hasher =
requires(H& h, const char* ptr, size_t size) {
{ h.update(ptr, size) } -> std::same_as<void>;
};
class hasher {
public:
@@ -57,13 +54,13 @@ public:
virtual void update(const char* ptr, size_t size) = 0;
};
GCC6_CONCEPT(static_assert(Hasher<hasher>());)
static_assert(Hasher<hasher>);
template<typename T, typename Enable = void>
struct appending_hash;
template<typename H, typename T, typename... Args>
GCC6_CONCEPT(requires Hasher<H>())
requires Hasher<H>
inline
void feed_hash(H& h, const T& value, Args&&... args) {
appending_hash<T>()(h, value, std::forward<Args>(args)...);
@@ -72,7 +69,7 @@ void feed_hash(H& h, const T& value, Args&&... args) {
template<typename T>
struct appending_hash<T, std::enable_if_t<std::is_arithmetic<T>::value>> {
template<typename H>
GCC6_CONCEPT(requires Hasher<H>())
requires Hasher<H>
void operator()(H& h, T value) const {
auto value_le = cpu_to_le(value);
h.update(reinterpret_cast<const char*>(&value_le), sizeof(T));
@@ -82,7 +79,7 @@ struct appending_hash<T, std::enable_if_t<std::is_arithmetic<T>::value>> {
template<>
struct appending_hash<bool> {
template<typename H>
GCC6_CONCEPT(requires Hasher<H>())
requires Hasher<H>
void operator()(H& h, bool value) const {
feed_hash(h, static_cast<uint8_t>(value));
}
@@ -91,7 +88,7 @@ struct appending_hash<bool> {
template<typename T>
struct appending_hash<T, std::enable_if_t<std::is_enum<T>::value>> {
template<typename H>
GCC6_CONCEPT(requires Hasher<H>())
requires Hasher<H>
void operator()(H& h, const T& value) const {
feed_hash(h, static_cast<std::underlying_type_t<T>>(value));
}
@@ -100,7 +97,7 @@ struct appending_hash<T, std::enable_if_t<std::is_enum<T>::value>> {
template<typename T>
struct appending_hash<std::optional<T>> {
template<typename H>
GCC6_CONCEPT(requires Hasher<H>())
requires Hasher<H>
void operator()(H& h, const std::optional<T>& value) const {
if (value) {
feed_hash(h, true);
@@ -114,7 +111,7 @@ struct appending_hash<std::optional<T>> {
template<size_t N>
struct appending_hash<char[N]> {
template<typename H>
GCC6_CONCEPT(requires Hasher<H>())
requires Hasher<H>
void operator()(H& h, const char (&value) [N]) const {
feed_hash(h, N);
h.update(value, N);
@@ -124,7 +121,7 @@ struct appending_hash<char[N]> {
template<typename T>
struct appending_hash<std::vector<T>> {
template<typename H>
GCC6_CONCEPT(requires Hasher<H>())
requires Hasher<H>
void operator()(H& h, const std::vector<T>& value) const {
feed_hash(h, value.size());
for (auto&& v : value) {
@@ -136,7 +133,7 @@ struct appending_hash<std::vector<T>> {
template<typename K, typename V>
struct appending_hash<std::map<K, V>> {
template<typename H>
GCC6_CONCEPT(requires Hasher<H>())
requires Hasher<H>
void operator()(H& h, const std::map<K, V>& value) const {
feed_hash(h, value.size());
for (auto&& e : value) {
@@ -149,7 +146,7 @@ struct appending_hash<std::map<K, V>> {
template<>
struct appending_hash<sstring> {
template<typename H>
GCC6_CONCEPT(requires Hasher<H>())
requires Hasher<H>
void operator()(H& h, const sstring& v) const {
feed_hash(h, v.size());
h.update(reinterpret_cast<const char*>(v.cbegin()), v.size() * sizeof(sstring::value_type));
@@ -159,7 +156,7 @@ struct appending_hash<sstring> {
template<>
struct appending_hash<std::string> {
template<typename H>
GCC6_CONCEPT(requires Hasher<H>())
requires Hasher<H>
void operator()(H& h, const std::string& v) const {
feed_hash(h, v.size());
h.update(reinterpret_cast<const char*>(v.data()), v.size() * sizeof(std::string::value_type));
@@ -169,7 +166,7 @@ struct appending_hash<std::string> {
template<typename T, typename R>
struct appending_hash<std::chrono::duration<T, R>> {
template<typename H>
GCC6_CONCEPT(requires Hasher<H>())
requires Hasher<H>
void operator()(H& h, std::chrono::duration<T, R> v) const {
feed_hash(h, v.count());
}
@@ -178,7 +175,7 @@ struct appending_hash<std::chrono::duration<T, R>> {
template<typename Clock, typename Duration>
struct appending_hash<std::chrono::time_point<Clock, Duration>> {
template<typename H>
GCC6_CONCEPT(requires Hasher<H>())
requires Hasher<H>
void operator()(H& h, std::chrono::time_point<Clock, Duration> v) const {
feed_hash(h, v.time_since_epoch().count());
}

View File

@@ -449,7 +449,7 @@ def add_param_writer_basic_type(name, base_state, typ, var_type="", var_index=No
if allow_fragmented:
writer += Template(reindent(4, """
template<typename FragmentedBuffer>
GCC6_CONCEPT(requires FragmentRange<FragmentedBuffer>)
requires FragmentRange<FragmentedBuffer>
after_${base_state}__$name<Output> write_fragmented_$name$var_type(FragmentedBuffer&& fragments) && {
$set_varient_index
serialize_fragmented(_out, std::forward<FragmentedBuffer>(fragments));

View File

@@ -64,15 +64,13 @@ public:
}
};
GCC6_CONCEPT(
template<typename T>
concept bool ContextFactory = requires(const T factory, const uint8_t* ptr) {
concept ContextFactory = requires(const T factory, const uint8_t* ptr) {
{ factory.create(ptr) } noexcept;
};
static_assert(ContextFactory<no_context_factory_t>,
"no_context_factory_t has to meet ContextFactory constraints");
)
/// LSA migrator for IMR objects
///
@@ -81,7 +79,7 @@ static_assert(ContextFactory<no_context_factory_t>,
/// of type `Structure`. The deserialisation context needed to invoke the mover
/// is going to be created by the provided context factory `CtxFactory`.
template<typename Structure, typename CtxFactory>
GCC6_CONCEPT(requires ContextFactory<CtxFactory>)
requires ContextFactory<CtxFactory>
class lsa_migrate_fn final : public migrate_fn_type, CtxFactory {
public:
using structure = Structure;

View File

@@ -23,8 +23,7 @@
#include <array>
#include <type_traits>
#include <seastar/util/gcc6-concepts.hh>
#include <concepts>
#include "utils/meta.hh"
@@ -54,9 +53,9 @@ public:
}
template<typename Context = no_context_t>
GCC6_CONCEPT(requires requires(const Context& ctx) {
requires requires(const Context& ctx) {
{ ctx.template context_for<Tag>() } noexcept;
})
}
auto get(const Context& ctx = no_context) noexcept {
return Type::make_view(_ptr, ctx.template context_for<Tag>(_ptr));
}
@@ -75,9 +74,9 @@ public:
}
public:
template<typename Context>
GCC6_CONCEPT(requires requires(const Context& ctx) {
{ ctx.template is_present<Tag>() } noexcept -> bool;
})
requires requires(const Context& ctx) {
{ ctx.template is_present<Tag>() } noexcept -> std::same_as<bool>;
}
static size_t serialized_object_size(const uint8_t* in, const Context& context) noexcept {
return context.template is_present<Tag>()
? Type::serialized_object_size(in, context)
@@ -237,9 +236,9 @@ public:
public:
template<typename Context>
GCC6_CONCEPT(requires requires(const Context& ctx) {
{ ctx.template active_alternative_of<Tag>() } noexcept -> alternative_index;
})
requires requires(const Context& ctx) {
{ ctx.template active_alternative_of<Tag>() } noexcept -> std::same_as<alternative_index>;
}
static size_t serialized_object_size(const uint8_t* in, const Context& context) noexcept {
return choose_alternative(context.template active_alternative_of<Tag>(), [&] (auto object) noexcept {
using alternative = std::remove_pointer_t<decltype(object)>;

View File

@@ -21,6 +21,7 @@
#pragma once
#include <concepts>
#include "imr/alloc.hh"
#include "imr/compound.hh"
#include "imr/fundamental.hh"
@@ -59,11 +60,9 @@ using default_sizer_t = decltype(Structure::get_sizer());
template<typename Structure>
using default_serializer_t = decltype(Structure::get_serializer(nullptr));
GCC6_CONCEPT(
/// A simple writer that accepts only sizer or serializer as an argument.
template<typename Writer, typename Structure>
concept bool WriterSimple = requires(Writer writer, default_sizer_t<Structure> sizer,
concept WriterSimple = requires(Writer writer, default_sizer_t<Structure> sizer,
default_serializer_t<Structure> serializer)
{
writer(sizer);
@@ -72,7 +71,7 @@ concept bool WriterSimple = requires(Writer writer, default_sizer_t<Structure> s
/// A writer that accepts both sizer or serializer and a memory allocator.
template<typename Writer, typename Structure>
concept bool WriterAllocator = requires(Writer writer, default_sizer_t<Structure> sizer,
concept WriterAllocator = requires(Writer writer, default_sizer_t<Structure> sizer,
default_serializer_t<Structure> serializer,
imr::alloc::object_allocator::sizer alloc_sizer,
imr::alloc::object_allocator::serializer alloc_serializer)
@@ -81,6 +80,4 @@ concept bool WriterAllocator = requires(Writer writer, default_sizer_t<Structure
writer(serializer, alloc_serializer);
};
)
}

View File

@@ -25,7 +25,6 @@
#include <seastar/core/align.hh>
#include <seastar/core/bitops.hh>
#include <seastar/util/gcc6-concepts.hh>
#include "bytes.hh"
#include "utils/meta.hh"
@@ -37,7 +36,7 @@ namespace imr {
namespace internal {
template<typename T, typename CharT>
GCC6_CONCEPT(requires std::is_pod<T>::value && sizeof(CharT) == 1)
requires std::is_standard_layout_v<T> && std::is_trivial_v<T> && (sizeof(CharT) == 1)
inline T read_pod(const CharT* in) noexcept {
T obj;
std::copy_n(in, sizeof(T), reinterpret_cast<CharT*>(&obj));
@@ -45,7 +44,7 @@ inline T read_pod(const CharT* in) noexcept {
}
template<typename T, typename CharT>
GCC6_CONCEPT(requires std::is_pod<T>::value && sizeof(CharT) == 1)
requires std::is_standard_layout_v<T> && std::is_trivial_v<T> && (sizeof(CharT) == 1)
inline void write_pod(T obj, CharT* out) noexcept {
std::copy_n(reinterpret_cast<const CharT*>(&obj), sizeof(T), out);
}
@@ -157,7 +156,7 @@ public:
///
/// Represents a fixed-size POD value.
template<typename Type>
GCC6_CONCEPT(requires std::is_pod<Type>::value)
requires std::is_standard_layout_v<Type> && std::is_trivial_v<Type>
struct pod {
using underlying = Type;
enum : size_t {
@@ -237,18 +236,18 @@ struct buffer {
using basic_view = std::conditional_t<is_mutable == ::mutable_view::no, view, mutable_view>;
template<typename Context>
GCC6_CONCEPT(requires requires(const Context& ctx) {
{ ctx.template size_of<Tag>() } noexcept -> size_t;
})
requires requires(const Context& ctx) {
{ ctx.template size_of<Tag>() } noexcept -> std::same_as<size_t>;
}
static view make_view(const uint8_t* in, const Context& context) noexcept {
auto ptr = reinterpret_cast<bytes_view::const_pointer>(in);
return bytes_view(ptr, context.template size_of<Tag>());
}
template<typename Context>
GCC6_CONCEPT(requires requires(const Context& ctx) {
{ ctx.template size_of<Tag>() } noexcept -> size_t;
})
requires requires(const Context& ctx) {
{ ctx.template size_of<Tag>() } noexcept -> std::same_as<size_t>;
}
static mutable_view make_view(uint8_t* in, const Context& context) noexcept {
auto ptr = reinterpret_cast<bytes_mutable_view::pointer>(in);
return bytes_mutable_view(ptr, context.template size_of<Tag>());
@@ -256,9 +255,9 @@ struct buffer {
public:
template<typename Context>
GCC6_CONCEPT(requires requires(const Context& ctx) {
{ ctx.template size_of<Tag>() } noexcept -> size_t;
})
requires requires(const Context& ctx) {
{ ctx.template size_of<Tag>() } noexcept -> std::same_as<size_t>;
}
static size_t serialized_object_size(const uint8_t*, const Context& context) noexcept {
return context.template size_of<Tag>();
}
@@ -268,9 +267,9 @@ public:
}
template<typename Serializer>
GCC6_CONCEPT(requires requires (Serializer ser, uint8_t* ptr) {
requires requires (Serializer ser, uint8_t* ptr) {
{ ser(ptr) } noexcept;
})
}
static size_t size_when_serialized(size_t size, Serializer&&) noexcept {
return size;
}
@@ -297,9 +296,9 @@ public:
}
template<typename Serializer>
GCC6_CONCEPT(requires requires (Serializer ser, uint8_t* ptr) {
requires requires (Serializer ser, uint8_t* ptr) {
{ ser(ptr) } noexcept;
})
}
static size_t serialize(uint8_t* out, size_t size, Serializer&& serializer) noexcept {
std::forward<Serializer>(serializer)(out);
return size;

View File

@@ -148,9 +148,9 @@ public:
/// \note This function could be deprecated once the IMR starts supporting
/// copying IMR objects.
template<typename RawWriter>
GCC6_CONCEPT(requires requires (RawWriter wr, uint8_t* ptr) {
requires requires (RawWriter wr, uint8_t* ptr) {
{ wr(ptr) } noexcept;
})
}
static object make_raw(size_t len, RawWriter&& wr, allocation_strategy::migrate_fn migrate = &imr::alloc::default_lsa_migrate_fn<structure>::migrate_fn) {
object obj;
auto ptr = static_cast<uint8_t*>(current_allocator().alloc(migrate, sizeof(void*) + len, 1));
@@ -163,7 +163,7 @@ public:
/// Create an IMR objects
template<typename Writer, typename MigrateFn>
GCC6_CONCEPT(requires WriterAllocator<Writer, Structure>)
requires WriterAllocator<Writer, Structure>
static object make(Writer&& object_writer,
MigrateFn* migrate = &imr::alloc::default_lsa_migrate_fn<structure>::migrate_fn) {
static_assert(std::is_same_v<typename MigrateFn::structure, structure>);
@@ -171,7 +171,7 @@ public:
}
private:
template<typename Writer>
GCC6_CONCEPT(requires WriterAllocator<Writer, Structure>)
requires WriterAllocator<Writer, Structure>
static object do_make(Writer&& object_writer, allocation_strategy::migrate_fn migrate) {
struct alloc_deleter {
size_t _size;

32
lua.cc
View File

@@ -220,19 +220,17 @@ struct lua_table {
template <typename Func>
using lua_visit_ret_type = std::invoke_result_t<Func, const double&>;
GCC6_CONCEPT(
template <typename Func>
concept bool CanHandleRawLuaTypes = requires(Func f) {
{ f(*static_cast<const long long*>(nullptr)) } -> lua_visit_ret_type<Func>;
{ f(*static_cast<const double*>(nullptr)) } -> lua_visit_ret_type<Func>;
{ f(*static_cast<const big_decimal*>(nullptr)) } -> lua_visit_ret_type<Func>;
{ f(*static_cast<const std::string_view*>(nullptr)) } -> lua_visit_ret_type<Func>;
{ f(*static_cast<const lua_table*>(nullptr)) } -> lua_visit_ret_type<Func>;
concept CanHandleRawLuaTypes = requires(Func f) {
{ f(*static_cast<const long long*>(nullptr)) } -> std::same_as<lua_visit_ret_type<Func>>;
{ f(*static_cast<const double*>(nullptr)) } -> std::same_as<lua_visit_ret_type<Func>>;
{ f(*static_cast<const big_decimal*>(nullptr)) } -> std::same_as<lua_visit_ret_type<Func>>;
{ f(*static_cast<const std::string_view*>(nullptr)) } -> std::same_as<lua_visit_ret_type<Func>>;
{ f(*static_cast<const lua_table*>(nullptr)) } -> std::same_as<lua_visit_ret_type<Func>>;
};
)
template <typename Func>
GCC6_CONCEPT(requires CanHandleRawLuaTypes<Func>)
requires CanHandleRawLuaTypes<Func>
static auto visit_lua_raw_value(lua_State* l, int index, Func&& f) {
switch (lua_type(l, index)) {
case LUA_TNONE:
@@ -275,19 +273,17 @@ static auto visit_decimal(const big_decimal &v, Func&& f) {
return f(r.convert_to<double>());
}
GCC6_CONCEPT(
template <typename Func>
concept bool CanHandleLuaTypes = requires(Func f) {
{ f(*static_cast<const double*>(nullptr)) } -> lua_visit_ret_type<Func>;
{ f(*static_cast<const utils::multiprecision_int*>(nullptr)) } -> lua_visit_ret_type<Func>;
{ f(*static_cast<const big_decimal*>(nullptr)) } -> lua_visit_ret_type<Func>;
{ f(*static_cast<const std::string_view*>(nullptr)) } -> lua_visit_ret_type<Func>;
{ f(*static_cast<const lua_table*>(nullptr)) } -> lua_visit_ret_type<Func>;
concept CanHandleLuaTypes = requires(Func f) {
{ f(*static_cast<const double*>(nullptr)) } -> std::same_as<lua_visit_ret_type<Func>>;
{ f(*static_cast<const utils::multiprecision_int*>(nullptr)) } -> std::same_as<lua_visit_ret_type<Func>>;
{ f(*static_cast<const big_decimal*>(nullptr)) } -> std::same_as<lua_visit_ret_type<Func>>;
{ f(*static_cast<const std::string_view*>(nullptr)) } -> std::same_as<lua_visit_ret_type<Func>>;
{ f(*static_cast<const lua_table*>(nullptr)) } -> std::same_as<lua_visit_ret_type<Func>>;
};
)
template <typename Func>
GCC6_CONCEPT(requires CanHandleLuaTypes<Func>)
requires CanHandleLuaTypes<Func>
static auto visit_lua_value(lua_State* l, int index, Func&& f) {
struct visitor {
lua_State* l;

View File

@@ -41,19 +41,17 @@ enum class compact_for_sstables {
yes,
};
GCC6_CONCEPT(
template<typename T>
concept bool CompactedFragmentsConsumer = requires(T obj, tombstone t, const dht::decorated_key& dk, static_row sr,
clustering_row cr, range_tombstone rt, tombstone current_tombstone, row_tombstone current_row_tombstone, bool is_alive) {
obj.consume_new_partition(dk);
obj.consume(t);
{ obj.consume(std::move(sr), current_tombstone, is_alive) } -> stop_iteration;
{ obj.consume(std::move(cr), current_row_tombstone, is_alive) } -> stop_iteration;
{ obj.consume(std::move(rt)) } -> stop_iteration;
{ obj.consume_end_of_partition() } -> stop_iteration;
obj.consume_end_of_stream();
};
)
template<typename T>
concept CompactedFragmentsConsumer = requires(T obj, tombstone t, const dht::decorated_key& dk, static_row sr,
clustering_row cr, range_tombstone rt, tombstone current_tombstone, row_tombstone current_row_tombstone, bool is_alive) {
obj.consume_new_partition(dk);
obj.consume(t);
{ obj.consume(std::move(sr), current_tombstone, is_alive) } -> std::same_as<stop_iteration>;
{ obj.consume(std::move(cr), current_row_tombstone, is_alive) } -> std::same_as<stop_iteration>;
{ obj.consume(std::move(rt)) } -> std::same_as<stop_iteration>;
{ obj.consume_end_of_partition() } -> std::same_as<stop_iteration>;
obj.consume_end_of_stream();
};
struct detached_compaction_state {
::partition_start partition_start;
@@ -265,9 +263,7 @@ public:
}
template <typename Consumer, typename GCConsumer>
GCC6_CONCEPT(
requires CompactedFragmentsConsumer<Consumer> && CompactedFragmentsConsumer<GCConsumer>
)
requires CompactedFragmentsConsumer<Consumer> && CompactedFragmentsConsumer<GCConsumer>
void consume(tombstone t, Consumer& consumer, GCConsumer& gc_consumer) {
_range_tombstones.set_partition_tombstone(t);
if (!only_live()) {
@@ -280,9 +276,7 @@ public:
}
template <typename Consumer, typename GCConsumer>
GCC6_CONCEPT(
requires CompactedFragmentsConsumer<Consumer> && CompactedFragmentsConsumer<GCConsumer>
)
requires CompactedFragmentsConsumer<Consumer> && CompactedFragmentsConsumer<GCConsumer>
stop_iteration consume(static_row&& sr, Consumer& consumer, GCConsumer& gc_consumer) {
_last_static_row = static_row(_schema, sr);
auto current_tombstone = _range_tombstones.get_partition_tombstone();
@@ -307,9 +301,7 @@ public:
}
template <typename Consumer, typename GCConsumer>
GCC6_CONCEPT(
requires CompactedFragmentsConsumer<Consumer> && CompactedFragmentsConsumer<GCConsumer>
)
requires CompactedFragmentsConsumer<Consumer> && CompactedFragmentsConsumer<GCConsumer>
stop_iteration consume(clustering_row&& cr, Consumer& consumer, GCConsumer& gc_consumer) {
auto current_tombstone = _range_tombstones.tombstone_for_row(cr.key());
auto t = cr.tomb();
@@ -365,9 +357,7 @@ public:
}
template <typename Consumer, typename GCConsumer>
GCC6_CONCEPT(
requires CompactedFragmentsConsumer<Consumer> && CompactedFragmentsConsumer<GCConsumer>
)
requires CompactedFragmentsConsumer<Consumer> && CompactedFragmentsConsumer<GCConsumer>
stop_iteration consume(range_tombstone&& rt, Consumer& consumer, GCConsumer& gc_consumer) {
_range_tombstones.apply(rt);
// FIXME: drop tombstone if it is fully covered by other range tombstones
@@ -384,9 +374,7 @@ public:
}
template <typename Consumer, typename GCConsumer>
GCC6_CONCEPT(
requires CompactedFragmentsConsumer<Consumer> && CompactedFragmentsConsumer<GCConsumer>
)
requires CompactedFragmentsConsumer<Consumer> && CompactedFragmentsConsumer<GCConsumer>
stop_iteration consume_end_of_partition(Consumer& consumer, GCConsumer& gc_consumer) {
if (!_empty_partition_in_gc_consumer) {
gc_consumer.consume_end_of_partition();
@@ -411,9 +399,7 @@ public:
}
template <typename Consumer, typename GCConsumer>
GCC6_CONCEPT(
requires CompactedFragmentsConsumer<Consumer> && CompactedFragmentsConsumer<GCConsumer>
)
requires CompactedFragmentsConsumer<Consumer> && CompactedFragmentsConsumer<GCConsumer>
auto consume_end_of_stream(Consumer& consumer, GCConsumer& gc_consumer) {
if (_dk) {
_last_dk = *_dk;
@@ -437,9 +423,7 @@ public:
/// partition-header and static row if there are clustering rows or range
/// tombstones left in the partition.
template <typename Consumer>
GCC6_CONCEPT(
requires CompactedFragmentsConsumer<Consumer>
)
requires CompactedFragmentsConsumer<Consumer>
void start_new_page(uint32_t row_limit,
uint32_t partition_limit,
gc_clock::time_point query_time,
@@ -480,9 +464,7 @@ public:
};
template<emit_only_live_rows OnlyLive, compact_for_sstables SSTableCompaction, typename Consumer, typename GCConsumer>
GCC6_CONCEPT(
requires CompactedFragmentsConsumer<Consumer> && CompactedFragmentsConsumer<GCConsumer>
)
requires CompactedFragmentsConsumer<Consumer> && CompactedFragmentsConsumer<GCConsumer>
class compact_mutation {
lw_shared_ptr<compact_mutation_state<OnlyLive, SSTableCompaction>> _state;
Consumer _consumer;
@@ -541,9 +523,7 @@ public:
};
template<emit_only_live_rows only_live, typename Consumer>
GCC6_CONCEPT(
requires CompactedFragmentsConsumer<Consumer>
)
requires CompactedFragmentsConsumer<Consumer>
struct compact_for_query : compact_mutation<only_live, compact_for_sstables::no, Consumer, noop_compacted_fragments_consumer> {
using compact_mutation<only_live, compact_for_sstables::no, Consumer, noop_compacted_fragments_consumer>::compact_mutation;
};
@@ -554,9 +534,7 @@ using compact_for_mutation_query_state = compact_for_query_state<emit_only_live_
using compact_for_data_query_state = compact_for_query_state<emit_only_live_rows::yes>;
template<typename Consumer, typename GCConsumer = noop_compacted_fragments_consumer>
GCC6_CONCEPT(
requires CompactedFragmentsConsumer<Consumer> && CompactedFragmentsConsumer<GCConsumer>
)
requires CompactedFragmentsConsumer<Consumer> && CompactedFragmentsConsumer<GCConsumer>
struct compact_for_compaction : compact_mutation<emit_only_live_rows::no, compact_for_sstables::yes, Consumer, GCConsumer> {
using compact_mutation<emit_only_live_rows::no, compact_for_sstables::yes, Consumer, GCConsumer>::compact_mutation;
};

View File

@@ -25,7 +25,6 @@
#include "position_in_partition.hh"
#include <optional>
#include <seastar/util/gcc6-concepts.hh>
#include <seastar/util/optimized_optional.hh>
#include "seastar/core/future-util.hh"
@@ -246,59 +245,44 @@ public:
friend std::ostream& operator<<(std::ostream& is, const partition_end& row);
};
GCC6_CONCEPT(
template<typename T, typename ReturnType>
concept bool MutationFragmentConsumer() {
return requires(T t, static_row sr, clustering_row cr, range_tombstone rt, partition_start ph, partition_end pe) {
{ t.consume(std::move(sr)) } -> ReturnType;
{ t.consume(std::move(cr)) } -> ReturnType;
{ t.consume(std::move(rt)) } -> ReturnType;
{ t.consume(std::move(ph)) } -> ReturnType;
{ t.consume(std::move(pe)) } -> ReturnType;
concept MutationFragmentConsumer =
requires(T t, static_row sr, clustering_row cr, range_tombstone rt, partition_start ph, partition_end pe) {
{ t.consume(std::move(sr)) } -> std::same_as<ReturnType>;
{ t.consume(std::move(cr)) } -> std::same_as<ReturnType>;
{ t.consume(std::move(rt)) } -> std::same_as<ReturnType>;
{ t.consume(std::move(ph)) } -> std::same_as<ReturnType>;
{ t.consume(std::move(pe)) } -> std::same_as<ReturnType>;
};
}
)
GCC6_CONCEPT(
template<typename T, typename ReturnType>
concept bool FragmentConsumerReturning() {
return requires(T t, static_row sr, clustering_row cr, range_tombstone rt, tombstone tomb) {
{ t.consume(std::move(sr)) } -> ReturnType;
{ t.consume(std::move(cr)) } -> ReturnType;
{ t.consume(std::move(rt)) } -> ReturnType;
concept FragmentConsumerReturning =
requires(T t, static_row sr, clustering_row cr, range_tombstone rt, tombstone tomb) {
{ t.consume(std::move(sr)) } -> std::same_as<ReturnType>;
{ t.consume(std::move(cr)) } -> std::same_as<ReturnType>;
{ t.consume(std::move(rt)) } -> std::same_as<ReturnType>;
};
}
)
GCC6_CONCEPT(
template<typename T>
concept bool FragmentConsumer() {
return FragmentConsumerReturning<T, stop_iteration >() || FragmentConsumerReturning<T, future<stop_iteration>>();
}
)
concept FragmentConsumer =
FragmentConsumerReturning<T, stop_iteration> || FragmentConsumerReturning<T, future<stop_iteration>>;
GCC6_CONCEPT(
template<typename T>
concept bool StreamedMutationConsumer() {
return FragmentConsumer<T>() && requires(T t, static_row sr, clustering_row cr, range_tombstone rt, tombstone tomb) {
concept StreamedMutationConsumer =
FragmentConsumer<T> && requires(T t, static_row sr, clustering_row cr, range_tombstone rt, tombstone tomb) {
t.consume(tomb);
t.consume_end_of_stream();
};
}
)
GCC6_CONCEPT(
template<typename T, typename ReturnType>
concept bool MutationFragmentVisitor() {
return requires(T t, const static_row& sr, const clustering_row& cr, const range_tombstone& rt, const partition_start& ph, const partition_end& eop) {
{ t(sr) } -> ReturnType;
{ t(cr) } -> ReturnType;
{ t(rt) } -> ReturnType;
{ t(ph) } -> ReturnType;
{ t(eop) } -> ReturnType;
concept MutationFragmentVisitor =
requires(T t, const static_row& sr, const clustering_row& cr, const range_tombstone& rt, const partition_start& ph, const partition_end& eop) {
{ t(sr) } -> std::same_as<ReturnType>;
{ t(cr) } -> std::same_as<ReturnType>;
{ t(rt) } -> std::same_as<ReturnType>;
{ t(ph) } -> std::same_as<ReturnType>;
{ t(eop) } -> std::same_as<ReturnType>;
};
}
)
class mutation_fragment {
public:
@@ -446,9 +430,7 @@ public:
void apply(const schema& s, mutation_fragment&& mf);
template<typename Consumer>
GCC6_CONCEPT(
requires MutationFragmentConsumer<Consumer, decltype(std::declval<Consumer>().consume(std::declval<range_tombstone>()))>()
)
requires MutationFragmentConsumer<Consumer, decltype(std::declval<Consumer>().consume(std::declval<range_tombstone>()))>
decltype(auto) consume(Consumer& consumer) && {
switch (_kind) {
case kind::static_row:
@@ -466,9 +448,7 @@ public:
}
template<typename Visitor>
GCC6_CONCEPT(
requires MutationFragmentVisitor<Visitor, decltype(std::declval<Visitor>()(std::declval<static_row&>()))>()
)
requires MutationFragmentVisitor<Visitor, decltype(std::declval<Visitor>()(std::declval<static_row&>()))>
decltype(auto) visit(Visitor&& visitor) const {
switch (_kind) {
case kind::static_row:
@@ -630,14 +610,11 @@ public:
friend std::ostream& operator<<(std::ostream& out, const range_tombstone_stream&);
};
GCC6_CONCEPT(
// F gets a stream element as an argument and returns the new value which replaces that element
// in the transformed stream.
template<typename F>
concept bool StreamedMutationTranformer() {
return requires(F f, mutation_fragment mf, schema_ptr s) {
{ f(std::move(mf)) } -> mutation_fragment;
{ f(s) } -> schema_ptr;
};
}
)
// F gets a stream element as an argument and returns the new value which replaces that element
// in the transformed stream.
template<typename F>
concept StreamedMutationTranformer =
requires(F f, mutation_fragment mf, schema_ptr s) {
{ f(std::move(mf)) } -> std::same_as<mutation_fragment>;
{ f(s) } -> std::same_as<schema_ptr>;
};

View File

@@ -47,7 +47,7 @@
using namespace db;
GCC6_CONCEPT(static_assert(MutationViewVisitor<mutation_partition_view_virtual_visitor>);)
static_assert(MutationViewVisitor<mutation_partition_view_virtual_visitor>);
mutation_partition_view_virtual_visitor::~mutation_partition_view_virtual_visitor() = default;
@@ -208,7 +208,7 @@ row_marker read_row_marker(boost::variant<ser::live_marker_view, ser::expiring_m
}
template<typename Visitor>
GCC6_CONCEPT(requires MutationViewVisitor<Visitor>)
requires MutationViewVisitor<Visitor>
void mutation_partition_view::do_accept(const column_mapping& cm, Visitor& visitor) const {
auto in = _in;
auto mpv = ser::deserialize(in, boost::type<ser::mutation_partition_view>());

View File

@@ -32,9 +32,8 @@ class mutation_partition_view;
class partition_builder;
class converting_mutation_partition_applier;
GCC6_CONCEPT(
template<typename T>
concept bool MutationViewVisitor = requires (T& visitor, tombstone t, atomic_cell ac,
concept MutationViewVisitor = requires (T& visitor, tombstone t, atomic_cell ac,
collection_mutation_view cmv, range_tombstone rt,
position_in_partition_view pipv, row_tombstone row_tomb,
row_marker rm) {
@@ -47,7 +46,6 @@ concept bool MutationViewVisitor = requires (T& visitor, tombstone t, atomic_cel
visitor.accept_row_cell(column_id(), std::move(ac));
visitor.accept_row_cell(column_id(), cmv);
};
)
class mutation_partition_view_virtual_visitor {
public:
@@ -70,7 +68,7 @@ private:
{ }
template<typename Visitor>
GCC6_CONCEPT(requires MutationViewVisitor<Visitor>)
requires MutationViewVisitor<Visitor>
void do_accept(const column_mapping&, Visitor& visitor) const;
public:
static mutation_partition_view from_stream(utils::input_stream v) {

View File

@@ -36,22 +36,20 @@ static constexpr size_t merger_small_vector_size = 4;
template<typename T>
using merger_vector = utils::small_vector<T, merger_small_vector_size>;
GCC6_CONCEPT(
template<typename Producer>
concept bool FragmentProducer = requires(Producer p, dht::partition_range part_range, position_range pos_range,
db::timeout_clock::time_point timeout) {
// The returned fragments are expected to have the same
// position_in_partition. Iterators and references are expected
// to be valid until the next call to operator()().
{ p(timeout) } -> future<boost::iterator_range<merger_vector<mutation_fragment>::iterator>>;
// These have the same semantics as their
// flat_mutation_reader counterparts.
{ p.next_partition() };
{ p.fast_forward_to(part_range, timeout) } -> future<>;
{ p.fast_forward_to(pos_range, timeout) } -> future<>;
{ p.buffer_size() } -> size_t;
};
)
template<typename Producer>
concept FragmentProducer = requires(Producer p, dht::partition_range part_range, position_range pos_range,
db::timeout_clock::time_point timeout) {
// The returned fragments are expected to have the same
// position_in_partition. Iterators and references are expected
// to be valid until the next call to operator()().
{ p(timeout) } -> std::same_as<future<boost::iterator_range<merger_vector<mutation_fragment>::iterator>>>;
// These have the same semantics as their
// flat_mutation_reader counterparts.
{ p.next_partition() };
{ p.fast_forward_to(part_range, timeout) } -> std::same_as<future<>>;
{ p.fast_forward_to(pos_range, timeout) } -> std::same_as<future<>>;
{ p.buffer_size() } -> std::same_as<size_t>;
};
/**
* Merge mutation-fragments produced by producer.
@@ -68,9 +66,7 @@ GCC6_CONCEPT(
* fast_forward_to() and next_partition(), as appropriate.
*/
template<class Producer>
GCC6_CONCEPT(
requires FragmentProducer<Producer>
)
requires FragmentProducer<Producer>
class mutation_fragment_merger {
using iterator = merger_vector<mutation_fragment>::iterator;
@@ -692,12 +688,10 @@ class restricting_mutation_reader : public flat_mutation_reader::impl {
static const ssize_t new_reader_base_cost{16 * 1024};
template<typename Function>
GCC6_CONCEPT(
requires std::is_move_constructible<Function>::value
&& requires(Function fn, flat_mutation_reader& reader) {
fn(reader);
}
)
requires std::is_move_constructible<Function>::value
&& requires(Function fn, flat_mutation_reader& reader) {
fn(reader);
}
decltype(auto) with_reader(Function fn, db::timeout_clock::time_point timeout) {
if (auto* state = std::get_if<admitted_state>(&_state)) {
return fn(state->reader);

View File

@@ -83,11 +83,9 @@ flat_mutation_reader make_combined_reader(schema_ptr schema,
mutation_reader::forwarding fwd_mr = mutation_reader::forwarding::yes);
template <typename MutationFilter>
GCC6_CONCEPT(
requires requires(MutationFilter mf, const dht::decorated_key& dk) {
{ mf(dk) } -> bool;
}
)
requires requires(MutationFilter mf, const dht::decorated_key& dk) {
{ mf(dk) } -> std::same_as<bool>;
}
class filtering_reader : public flat_mutation_reader::impl {
flat_mutation_reader _rd;
MutationFilter _filter;

View File

@@ -27,9 +27,7 @@ namespace mutation_writer {
using reader_consumer = noncopyable_function<future<> (flat_mutation_reader)>;
template <typename Writer>
GCC6_CONCEPT(
requires MutationFragmentConsumer<Writer, future<>>()
)
requires MutationFragmentConsumer<Writer, future<>>
future<> feed_writer(flat_mutation_reader&& rd, Writer&& wr) {
return do_with(std::move(rd), std::move(wr), [] (flat_mutation_reader& rd, Writer& wr) {
return rd.fill_buffer(db::no_timeout).then([&rd, &wr] {

View File

@@ -84,34 +84,26 @@ size_t partition_version::size_in_allocator(const schema& s, allocation_strategy
namespace {
GCC6_CONCEPT(
// A functor which transforms objects from Domain into objects from CoDomain
template<typename U, typename Domain, typename CoDomain>
concept bool Mapper() {
return requires(U obj, const Domain& src) {
{ obj(src) } -> const CoDomain&;
concept Mapper =
requires(U obj, const Domain& src) {
{ obj(src) } -> std::convertible_to<const CoDomain&>;
};
}
// A functor which merges two objects from Domain into one. The result is stored in the first argument.
template<typename U, typename Domain>
concept bool Reducer() {
return requires(U obj, Domain& dst, const Domain& src) {
{ obj(dst, src) } -> void;
concept Reducer =
requires(U obj, Domain& dst, const Domain& src) {
{ obj(dst, src) } -> std::same_as<void>;
};
}
)
// Calculates the value of particular part of mutation_partition represented by
// the version chain starting from v.
// |map| extracts the part from each version.
// |reduce| Combines parts from the two versions.
template <typename Result, typename Map, typename Initial, typename Reduce>
GCC6_CONCEPT(
requires Mapper<Map, mutation_partition, Result>() && Reducer<Reduce, Result>()
)
requires Mapper<Map, mutation_partition, Result> && Reducer<Reduce, Result>
inline Result squashed(const partition_version_ref& v, Map&& map, Initial&& initial, Reduce&& reduce) {
const partition_version* this_v = &*v;
partition_version* it = v->last();
@@ -124,9 +116,7 @@ inline Result squashed(const partition_version_ref& v, Map&& map, Initial&& init
}
template <typename Result, typename Map, typename Reduce>
GCC6_CONCEPT(
requires Mapper<Map, mutation_partition, Result>() && Reducer<Reduce, Result>()
)
requires Mapper<Map, mutation_partition, Result> && Reducer<Reduce, Result>
inline Result squashed(const partition_version_ref& v, Map&& map, Reduce&& reduce) {
return squashed<Result>(v, map,
[] (auto&& o) -> decltype(auto) { return std::forward<decltype(o)>(o); },

View File

@@ -74,9 +74,7 @@ public:
/// or std::nullopt if the last row wasn't a clustering row, and whatever the
/// consumer's `consume_end_of_stream()` method returns.
template <emit_only_live_rows OnlyLive, typename Consumer>
GCC6_CONCEPT(
requires CompactedFragmentsConsumer<Consumer>
)
requires CompactedFragmentsConsumer<Consumer>
auto consume_page(flat_mutation_reader& reader,
lw_shared_ptr<compact_for_query_state<OnlyLive>> compaction_state,
const query::partition_slice& slice,
@@ -175,9 +173,7 @@ public:
}
template <typename Consumer>
GCC6_CONCEPT(
requires CompactedFragmentsConsumer<Consumer>
)
requires CompactedFragmentsConsumer<Consumer>
auto consume_page(Consumer&& consumer,
uint32_t row_limit,
uint32_t partition_limit,

View File

@@ -136,9 +136,8 @@ struct result_visitor {
void accept_partition_end(const result_row_view& static_row) {}
};
GCC6_CONCEPT(
template<typename Visitor>
concept bool ResultVisitor = requires(Visitor visitor, const partition_key& pkey,
concept ResultVisitor = requires(Visitor visitor, const partition_key& pkey,
uint32_t row_count, const clustering_key& ckey,
const result_row_view& static_row, const result_row_view& row)
{
@@ -148,7 +147,6 @@ concept bool ResultVisitor = requires(Visitor visitor, const partition_key& pkey
visitor.accept_new_row(static_row, row);
visitor.accept_partition_end(static_row);
};
)
class result_view {
ser::query_result_view _v;
@@ -170,7 +168,7 @@ public:
}
template <typename Visitor>
GCC6_CONCEPT(requires ResultVisitor<Visitor>)
requires ResultVisitor<Visitor>
void consume(const partition_slice& slice, Visitor&& visitor) const {
for (auto&& p : _v.partitions()) {
auto rows = p.rows();

View File

@@ -28,7 +28,6 @@
#include <boost/range/algorithm/copy.hpp>
#include <boost/range/adaptor/sliced.hpp>
#include <boost/range/adaptor/transformed.hpp>
#include <seastar/util/gcc6-concepts.hh>
template<typename T>
class range_bound {
@@ -698,10 +697,8 @@ std::ostream& operator<<(std::ostream& out, const nonwrapping_range<U>& r) {
template<typename T>
using range = wrapping_range<T>;
GCC6_CONCEPT(
template<template<typename> typename T, typename U>
concept bool Range = std::is_same<T<U>, wrapping_range<U>>::value || std::is_same<T<U>, nonwrapping_range<U>>::value;
)
concept Range = std::is_same<T<U>, wrapping_range<U>>::value || std::is_same<T<U>, nonwrapping_range<U>>::value;
// Allow using range<T> in a hash table. The hash function 31 * left +
// right is the same one used by Cassandra's AbstractBounds.hashCode().

View File

@@ -69,6 +69,4 @@ public:
}
};
GCC6_CONCEPT(
static_assert(StreamedMutationTranformer<schema_upgrader>());
)
static_assert(StreamedMutationTranformer<schema_upgrader>);

View File

@@ -442,7 +442,7 @@ public:
return bytes_view(reinterpret_cast<const int8_t*>(_stream.begin()), _stream.size());
} else {
using iterator_type = typename Stream::iterator_type ;
GCC6_CONCEPT(static_assert(FragmentRange<buffer_view<iterator_type>>));
static_assert(FragmentRange<buffer_view<iterator_type>>);
return seastar::with_serialized_stream(_stream, seastar::make_visitor(
[&] (typename seastar::memory_input_stream<iterator_type >::simple stream) {
return buffer_view<iterator_type>(bytes_view(reinterpret_cast<const int8_t*>(stream.begin()),
@@ -507,7 +507,7 @@ struct serializer<bytes> {
}
}
template<typename Output, typename FragmentedBuffer>
GCC6_CONCEPT(requires FragmentRange<FragmentedBuffer>)
requires FragmentRange<FragmentedBuffer>
static void write_fragmented(Output& out, FragmentedBuffer&& fragments) {
safe_serialize_as_uint32(out, uint32_t(fragments.size_bytes()));
using boost::range::for_each;
@@ -535,7 +535,7 @@ void serialize(Output& out, const bytes_ostream& v) {
serializer<bytes>::write(out, v);
}
template<typename Output, typename FragmentedBuffer>
GCC6_CONCEPT(requires FragmentRange<FragmentedBuffer>)
requires FragmentRange<FragmentedBuffer>
void serialize_fragmented(Output& out, FragmentedBuffer&& v) {
serializer<bytes>::write_fragmented(out, std::forward<FragmentedBuffer>(v));
}

View File

@@ -55,10 +55,8 @@
namespace service {
GCC6_CONCEPT(
template<typename M>
concept bool MergeableMutation = std::is_same<M, canonical_mutation>::value || std::is_same<M, frozen_mutation>::value;
)
template<typename M>
concept MergeableMutation = std::is_same<M, canonical_mutation>::value || std::is_same<M, frozen_mutation>::value;
class migration_manager : public seastar::async_sharded_service<migration_manager> {
private:
@@ -100,7 +98,7 @@ public:
future<> merge_schema_from(netw::msg_addr src, const std::vector<frozen_mutation>& mutations);
template<typename M>
GCC6_CONCEPT(requires MergeableMutation<M>)
requires MergeableMutation<M>
future<> merge_schema_in_background(netw::msg_addr src, const std::vector<M>& mutations) {
return with_gate(_background_tasks, [this, src, &mutations] {
return merge_schema_from(src, mutations);

View File

@@ -150,7 +150,7 @@ protected:
do_fetch_page(uint32_t page_size, gc_clock::time_point now, db::timeout_clock::time_point timeout);
template<typename Visitor>
GCC6_CONCEPT(requires query::ResultVisitor<Visitor>)
requires query::ResultVisitor<Visitor>
void handle_result(Visitor&& visitor,
const foreign_ptr<lw_shared_ptr<query::result>>& results,
uint32_t page_size, gc_clock::time_point now);

View File

@@ -305,7 +305,7 @@ public:
};
template<typename Visitor>
GCC6_CONCEPT(requires query::ResultVisitor<Visitor>)
requires query::ResultVisitor<Visitor>
void query_pager::handle_result(
Visitor&& visitor,
const foreign_ptr<lw_shared_ptr<query::result>>& results,

View File

@@ -22,24 +22,21 @@
#pragma once
#include <zlib.h>
#include <seastar/util/gcc6-concepts.hh>
#include "libdeflate/libdeflate.h"
#include "utils/gz/crc_combine.hh"
GCC6_CONCEPT(
template<typename Checksum>
concept bool ChecksumUtils = requires(const char* input, size_t size, uint32_t checksum) {
{ Checksum::init_checksum() } -> uint32_t;
{ Checksum::checksum(input, size) } -> uint32_t;
{ Checksum::checksum(checksum, input, size) } -> uint32_t;
{ Checksum::checksum_combine(checksum, checksum, size) } -> uint32_t;
concept ChecksumUtils = requires(const char* input, size_t size, uint32_t checksum) {
{ Checksum::init_checksum() } -> std::same_as<uint32_t>;
{ Checksum::checksum(input, size) } -> std::same_as<uint32_t>;
{ Checksum::checksum(checksum, input, size) } -> std::same_as<uint32_t>;
{ Checksum::checksum_combine(checksum, checksum, size) } -> std::same_as<uint32_t>;
// Tells whether checksum_combine() should be preferred over checksum().
// For same checksummers it's faster to re-feed the buffer to checksum() than to
// combine the checksum of the buffer.
{ Checksum::prefer_combine() } -> bool;
{ Checksum::prefer_combine() } -> std::same_as<bool>;
};
)
struct adler32_utils {
inline static uint32_t init_checksum() {

View File

@@ -504,9 +504,7 @@ private:
virtual flat_mutation_reader make_sstable_reader() const = 0;
template <typename GCConsumer>
GCC6_CONCEPT(
requires CompactedFragmentsConsumer<GCConsumer>
)
requires CompactedFragmentsConsumer<GCConsumer>
future<> setup(GCConsumer gc_consumer) {
auto ssts = make_lw_shared<sstables::sstable_set>(_cf.get_compaction_strategy().make_sstable_set(_schema));
sstring formatted_msg = "[";
@@ -661,9 +659,7 @@ public:
}
template <typename GCConsumer = noop_compacted_fragments_consumer>
GCC6_CONCEPT(
requires CompactedFragmentsConsumer<GCConsumer>
)
requires CompactedFragmentsConsumer<GCConsumer>
static future<compaction_info> run(std::unique_ptr<compaction> c, GCConsumer gc_consumer = GCConsumer());
friend class compacting_sstable_writer;
@@ -1304,9 +1300,7 @@ public:
};
template <typename GCConsumer>
GCC6_CONCEPT(
requires CompactedFragmentsConsumer<GCConsumer>
)
requires CompactedFragmentsConsumer<GCConsumer>
future<compaction_info> compaction::run(std::unique_ptr<compaction> c, GCConsumer gc_consumer) {
return seastar::async([c = std::move(c), gc_consumer = std::move(gc_consumer)] () mutable {
auto consumer = c->setup(std::move(gc_consumer));

View File

@@ -344,9 +344,7 @@ compression::locate(uint64_t position, const compression::segmented_offsets::acc
}
template <typename ChecksumType>
GCC6_CONCEPT(
requires ChecksumUtils<ChecksumType>
)
requires ChecksumUtils<ChecksumType>
class compressed_file_data_source_impl : public data_source_impl {
std::optional<input_stream<char>> _input_stream;
sstables::compression* _compression_metadata;
@@ -453,9 +451,7 @@ public:
};
template <typename ChecksumType>
GCC6_CONCEPT(
requires ChecksumUtils<ChecksumType>
)
requires ChecksumUtils<ChecksumType>
class compressed_file_data_source : public data_source {
public:
compressed_file_data_source(file f, sstables::compression* cm,
@@ -466,9 +462,7 @@ public:
};
template <typename ChecksumType>
GCC6_CONCEPT(
requires ChecksumUtils<ChecksumType>
)
requires ChecksumUtils<ChecksumType>
inline input_stream<char> make_compressed_file_input_stream(
file f, sstables::compression *cm, uint64_t offset, size_t len,
file_input_stream_options options)
@@ -489,9 +483,7 @@ enum class compressed_checksum_mode {
// where the buffer flushed will be compressed and its checksum computed, then
// the result passed to a regular output stream.
template <typename ChecksumType, compressed_checksum_mode mode>
GCC6_CONCEPT(
requires ChecksumUtils<ChecksumType>
)
requires ChecksumUtils<ChecksumType>
class compressed_file_data_sink_impl : public data_sink_impl {
output_stream<char> _out;
sstables::compression* _compression_metadata;
@@ -555,9 +547,7 @@ public:
};
template <typename ChecksumType, compressed_checksum_mode mode>
GCC6_CONCEPT(
requires ChecksumUtils<ChecksumType>
)
requires ChecksumUtils<ChecksumType>
class compressed_file_data_sink : public data_sink {
public:
compressed_file_data_sink(file f, sstables::compression* cm, sstables::local_compression lc, file_output_stream_options options)
@@ -566,9 +556,7 @@ public:
};
template <typename ChecksumType, compressed_checksum_mode mode>
GCC6_CONCEPT(
requires ChecksumUtils<ChecksumType>
)
requires ChecksumUtils<ChecksumType>
inline output_stream<char> make_compressed_file_output_stream(file f, file_output_stream_options options,
sstables::compression* cm,
const compression_parameters& cp) {

View File

@@ -26,7 +26,6 @@
#include <seastar/core/future.hh>
#include <seastar/util/optimized_optional.hh>
#include <seastar/util/gcc6-concepts.hh>
#include "shared_sstable.hh"
#include "row.hh"
@@ -64,9 +63,7 @@ data_consume_rows(const schema&, shared_sstable, typename DataConsumeRowsContext
// Moreover, the sstable object used for the sstable::data_consume_rows()
// call which created this data_consume_context, must also be kept alive.
template <typename DataConsumeRowsContext>
GCC6_CONCEPT(
requires ConsumeRowsContext<DataConsumeRowsContext>()
)
requires ConsumeRowsContext<DataConsumeRowsContext>
class data_consume_context {
shared_sstable _sst;
std::unique_ptr<DataConsumeRowsContext> _ctx;

View File

@@ -191,7 +191,7 @@ public:
};
template <typename W>
GCC6_CONCEPT(requires Writer<W>())
requires Writer<W>
static void write(W& out, const clustering_block& block) {
write_vint(out, block.header);
for (const auto& [value, type]: block.values) {
@@ -200,7 +200,7 @@ static void write(W& out, const clustering_block& block) {
}
template <typename W>
GCC6_CONCEPT(requires Writer<W>())
requires Writer<W>
void write_clustering_prefix(W& out, const schema& s,
const clustering_key_prefix& prefix, ephemerally_full_prefix is_ephemerally_full) {
clustering_blocks_input_range range{s, prefix, is_ephemerally_full};
@@ -301,7 +301,7 @@ public:
};
template <typename W>
GCC6_CONCEPT(requires Writer<W>())
requires Writer<W>
void write_missing_columns(W& out, const indexed_columns& columns, const row& row) {
for (const auto value: missing_columns_input_range{columns, row}) {
write_vint(out, value);
@@ -309,7 +309,7 @@ void write_missing_columns(W& out, const indexed_columns& columns, const row& ro
}
template <typename T, typename W>
GCC6_CONCEPT(requires Writer<W>())
requires Writer<W>
void write_unsigned_delta_vint(W& out, T value, T base) {
using unsigned_type = std::make_unsigned_t<T>;
unsigned_type unsigned_delta = static_cast<unsigned_type>(value) - static_cast<unsigned_type>(base);
@@ -321,25 +321,25 @@ void write_unsigned_delta_vint(W& out, T value, T base) {
}
template <typename W>
GCC6_CONCEPT(requires Writer<W>())
requires Writer<W>
void write_delta_timestamp(W& out, api::timestamp_type timestamp, const encoding_stats& enc_stats) {
write_unsigned_delta_vint(out, timestamp, enc_stats.min_timestamp);
}
template <typename W>
GCC6_CONCEPT(requires Writer<W>())
requires Writer<W>
void write_delta_ttl(W& out, gc_clock::duration ttl, const encoding_stats& enc_stats) {
write_unsigned_delta_vint(out, ttl.count(), enc_stats.min_ttl.count());
}
template <typename W>
GCC6_CONCEPT(requires Writer<W>())
requires Writer<W>
void write_delta_local_deletion_time(W& out, int64_t local_deletion_time, const encoding_stats& enc_stats) {
write_unsigned_delta_vint(out, local_deletion_time, enc_stats.min_local_deletion_time.time_since_epoch().count());
}
template <typename W>
GCC6_CONCEPT(requires Writer<W>())
requires Writer<W>
void write_delta_local_deletion_time(W& out, gc_clock::time_point ldt, const encoding_stats& enc_stats) {
write_unsigned_delta_vint(out, ldt.time_since_epoch().count(), enc_stats.min_local_deletion_time.time_since_epoch().count());
}
@@ -519,13 +519,11 @@ static bound_kind_m get_kind(const rt_marker& marker) {
return marker.kind;
}
GCC6_CONCEPT(
template<typename T>
concept bool Clustered = requires(T t) {
{ t.key() } -> const clustering_key_prefix&;
{ get_kind(t) } -> bound_kind_m;
concept Clustered = requires(T t) {
{ t.key() } -> std::convertible_to<const clustering_key_prefix&>;
{ get_kind(t) } -> std::same_as<bound_kind_m>;
};
)
// Used for writing SSTables in 'mc' format.
class writer : public sstable_writer::writer_impl {
@@ -706,9 +704,7 @@ private:
void write_clustered(const rt_marker& marker, uint64_t prev_row_size);
template <typename T>
GCC6_CONCEPT(
requires Clustered<T>
)
requires Clustered<T>
void write_clustered(const T& clustered) {
clustering_info info {clustered.key(), get_kind(clustered)};
maybe_set_pi_first_clustering(info);
@@ -1279,7 +1275,7 @@ stop_iteration writer::consume(clustering_row&& cr) {
// Write clustering prefix along with its bound kind and, if not full, its size
template <typename W>
GCC6_CONCEPT(requires Writer<W>())
requires Writer<W>
static void write_clustering_prefix(W& writer, bound_kind_m kind,
const schema& s, const clustering_key_prefix& clustering) {
assert(kind != bound_kind_m::static_clustering);

View File

@@ -28,7 +28,6 @@
#include "unimplemented.hh"
#include "dht/i_partitioner.hh"
#include <seastar/core/byteorder.hh>
#include <seastar/util/gcc6-concepts.hh>
#include "index_reader.hh"
#include "counters.hh"
#include "utils/data_input.hh"
@@ -76,22 +75,19 @@ position_in_partition_view get_slice_upper_bound(const schema& s, const query::p
return position_in_partition_view::for_range_end(ranges.back());
}
GCC6_CONCEPT(
template<typename T>
concept bool RowConsumer() {
return requires(T t,
concept RowConsumer =
requires(T t,
const partition_key& pk,
position_range cr,
db::timeout_clock::time_point timeout) {
{ t.io_priority() } -> const io_priority_class&;
{ t.is_mutation_end() } -> bool;
{ t.setup_for_partition(pk) } -> void;
{ t.push_ready_fragments() } -> void;
{ t.maybe_skip() } -> std::optional<position_in_partition_view>;
{ t.fast_forward_to(std::move(cr), timeout) } -> std::optional<position_in_partition_view>;
{ t.io_priority() } -> std::convertible_to<const io_priority_class&>;
{ t.is_mutation_end() } -> std::same_as<bool>;
{ t.setup_for_partition(pk) } -> std::same_as<void>;
{ t.push_ready_fragments() } -> std::same_as<void>;
{ t.maybe_skip() } -> std::same_as<std::optional<position_in_partition_view>>;
{ t.fast_forward_to(std::move(cr), timeout) } -> std::same_as<std::optional<position_in_partition_view>>;
};
}
)
/*
* Helper method to set or reset the range tombstone start bound according to the
@@ -127,9 +123,7 @@ void set_range_tombstone_start_from_end_open_marker(Consumer& c, const schema& s
}
template <typename DataConsumeRowsContext = data_consume_rows_context, typename Consumer = mp_row_consumer_k_l>
GCC6_CONCEPT(
requires RowConsumer<Consumer>()
)
requires RowConsumer<Consumer>
class sstable_mutation_reader : public mp_row_consumer_reader {
Consumer _consumer;
bool _will_likely_slice = false;

View File

@@ -85,26 +85,21 @@ struct foreign_sstable_open_info;
struct sstable_open_info;
class sstables_manager;
GCC6_CONCEPT(
template<typename T>
concept bool ConsumeRowsContext() {
return requires(T c, indexable_element el, size_t s) {
{ c.consume_input() } -> future<>;
{ c.reset(el) } -> void;
{ c.fast_forward_to(s, s) } -> future<>;
{ c.position() } -> uint64_t;
{ c.skip_to(s) } -> future<>;
{ c.reader_position() } -> const sstables::reader_position_tracker&;
{ c.eof() } -> bool;
{ c.close() } -> future<>;
concept ConsumeRowsContext =
requires(T c, indexable_element el, size_t s) {
{ c.consume_input() } -> std::same_as<future<>>;
{ c.reset(el) } -> std::same_as<void>;
{ c.fast_forward_to(s, s) } -> std::same_as<future<>>;
{ c.position() } -> std::same_as<uint64_t>;
{ c.skip_to(s) } -> std::same_as<future<>>;
{ c.reader_position() } -> std::same_as<const sstables::reader_position_tracker&>;
{ c.eof() } -> std::same_as<bool>;
{ c.close() } -> std::same_as<future<>>;
};
}
)
template <typename DataConsumeRowsContext>
GCC6_CONCEPT(
requires ConsumeRowsContext<DataConsumeRowsContext>()
)
requires ConsumeRowsContext<DataConsumeRowsContext>
class data_consume_context;
class index_reader;

View File

@@ -21,7 +21,6 @@
#pragma once
#include <seastar/util/gcc6-concepts.hh>
#include "disk_types.hh"
#include <seastar/core/enum.hh>
#include "bytes.hh"
@@ -49,14 +48,11 @@ static inline bytes_view to_bytes_view(const temporary_buffer<char>& b) {
namespace sstables {
GCC6_CONCEPT(
template<typename T>
concept bool Writer() {
return requires(T& wr, const char* data, size_t size) {
{ wr.write(data, size) } -> void;
concept Writer =
requires(T& wr, const char* data, size_t size) {
{ wr.write(data, size) } -> std::same_as<void>;
};
}
)
struct commitlog_interval {
db::replay_position start;
@@ -249,7 +245,7 @@ template <typename T>
uint64_t serialized_size(sstable_version_types v, const T& object);
template <class T, typename W>
GCC6_CONCEPT(requires Writer<W>())
requires Writer<W>
typename std::enable_if_t<!std::is_integral<T>::value && !std::is_enum<T>::value, void>
write(sstable_version_types v, W& out, const T& t);

View File

@@ -127,9 +127,7 @@ serialized_size(sstable_version_types v, const T& object) {
}
template <typename ChecksumType>
GCC6_CONCEPT(
requires ChecksumUtils<ChecksumType>
)
requires ChecksumUtils<ChecksumType>
class checksummed_file_data_sink_impl : public data_sink_impl {
data_sink _out;
struct checksum& _c;
@@ -167,9 +165,7 @@ public:
};
template <typename ChecksumType>
GCC6_CONCEPT(
requires ChecksumUtils<ChecksumType>
)
requires ChecksumUtils<ChecksumType>
class checksummed_file_data_sink : public data_sink {
public:
checksummed_file_data_sink(file f, struct checksum& cinfo, uint32_t& full_file_checksum, file_output_stream_options options)
@@ -177,9 +173,7 @@ public:
};
template <typename ChecksumType>
GCC6_CONCEPT(
requires ChecksumUtils<ChecksumType>
)
requires ChecksumUtils<ChecksumType>
inline
output_stream<char> make_checksummed_file_output_stream(file f, struct checksum& cinfo, uint32_t& full_file_checksum, file_output_stream_options options) {
auto buffer_size = options.buffer_size;
@@ -187,9 +181,7 @@ output_stream<char> make_checksummed_file_output_stream(file f, struct checksum&
}
template <typename ChecksumType>
GCC6_CONCEPT(
requires ChecksumUtils<ChecksumType>
)
requires ChecksumUtils<ChecksumType>
class checksummed_file_writer : public file_writer {
checksum _c;
uint32_t _full_checksum;
@@ -217,7 +209,7 @@ using adler32_checksummed_file_writer = checksummed_file_writer<adler32_utils>;
using crc32_checksummed_file_writer = checksummed_file_writer<crc32_utils>;
template <typename T, typename W>
GCC6_CONCEPT(requires Writer<W>())
requires Writer<W>
inline void write_vint_impl(W& out, T value) {
using vint_type = std::conditional_t<std::is_unsigned_v<T>, unsigned_vint, signed_vint>;
std::array<bytes::value_type, max_vint_length> encoding_buffer;
@@ -226,24 +218,24 @@ inline void write_vint_impl(W& out, T value) {
}
template <typename W>
GCC6_CONCEPT(requires Writer<W>())
requires Writer<W>
void write_unsigned_vint(W& out, uint64_t value) {
return write_vint_impl(out, value);
}
template <typename W>
GCC6_CONCEPT(requires Writer<W>())
requires Writer<W>
void write_signed_vint(W& out, int64_t value) {
return write_vint_impl(out, value);
}
template <typename T, typename W>
GCC6_CONCEPT(requires Writer<W>())
requires Writer<W>
typename std::enable_if_t<!std::is_integral_v<T>>
write_vint(W& out, T t) = delete;
template <typename T, typename W>
GCC6_CONCEPT(requires Writer<W>())
requires Writer<W>
inline void write_vint(W& out, T value) {
static_assert(std::is_integral_v<T>, "Non-integral values can't be written using write_vint");
return std::is_unsigned_v<T> ? write_unsigned_vint(out, value) : write_signed_vint(out, value);
@@ -251,7 +243,7 @@ inline void write_vint(W& out, T value) {
template <typename T, typename W>
GCC6_CONCEPT(requires Writer<W>())
requires Writer<W>
inline typename std::enable_if_t<std::is_integral<T>::value, void>
write(sstable_version_types v, W& out, T i) {
auto *nr = reinterpret_cast<const net::packed<T> *>(&i);
@@ -261,7 +253,7 @@ write(sstable_version_types v, W& out, T i) {
}
template <typename T, typename W>
GCC6_CONCEPT(requires Writer<W>())
requires Writer<W>
inline typename std::enable_if_t<std::is_enum<T>::value, void>
write(sstable_version_types v, W& out, T i) {
write(v, out, static_cast<typename std::underlying_type<T>::type>(i));
@@ -269,7 +261,7 @@ write(sstable_version_types v, W& out, T i) {
template <typename W>
GCC6_CONCEPT(requires Writer<W>())
requires Writer<W>
inline void write(sstable_version_types v, W& out, bool i) {
write(v, out, static_cast<uint8_t>(i));
}
@@ -283,13 +275,13 @@ inline void write(sstable_version_types v, file_writer& out, double d) {
template <typename W>
GCC6_CONCEPT(requires Writer<W>())
requires Writer<W>
inline void write(sstable_version_types v, W& out, const bytes& s) {
out.write(s);
}
template <typename W>
GCC6_CONCEPT(requires Writer<W>())
requires Writer<W>
inline void write(sstable_version_types v, W& out, bytes_view s) {
out.write(reinterpret_cast<const char*>(s.data()), s.size());
}
@@ -302,20 +294,20 @@ inline void write(sstable_version_types v, file_writer& out, bytes_ostream s) {
template<typename W, typename First, typename Second, typename... Rest>
GCC6_CONCEPT(requires Writer<W>())
requires Writer<W>
inline void write(sstable_version_types v, W& out, const First& first, const Second& second, Rest&&... rest) {
write(v, out, first);
write(v, out, second, std::forward<Rest>(rest)...);
}
template <class T, typename W>
GCC6_CONCEPT(requires Writer<W>())
requires Writer<W>
inline void write(sstable_version_types v, W& out, const vint<T>& t) {
write_vint(out, t.value);
}
template <class T, typename W>
GCC6_CONCEPT(requires Writer<W>())
requires Writer<W>
typename std::enable_if_t<!std::is_integral<T>::value && !std::is_enum<T>::value, void>
write(sstable_version_types v, W& out, const T& t) {
// describe_type() is not const correct, so cheat here:
@@ -534,7 +526,7 @@ void write_column_name(sstable_version_types v, Writer& out, const schema& s, co
}
template <typename W>
GCC6_CONCEPT(requires Writer<W>())
requires Writer<W>
void write_cell_value(W& out, const abstract_type& type, bytes_view value) {
if (!value.empty()) {
if (type.value_length_if_fixed()) {
@@ -547,7 +539,7 @@ void write_cell_value(W& out, const abstract_type& type, bytes_view value) {
}
template <typename W>
GCC6_CONCEPT(requires Writer<W>())
requires Writer<W>
void write_cell_value(W& out, const abstract_type& type, atomic_cell_value_view value) {
if (!value.empty()) {
if (!type.value_length_if_fixed()) {
@@ -559,7 +551,7 @@ void write_cell_value(W& out, const abstract_type& type, atomic_cell_value_view
}
template <typename WriteLengthFunc, typename W>
GCC6_CONCEPT(requires Writer<W>())
requires Writer<W>
void write_counter_value(counter_cell_view ccv, W& out, sstable_version_types v, WriteLengthFunc&& write_len_func) {
auto shard_count = ccv.shard_count();
static constexpr auto header_entry_size = sizeof(int16_t);

View File

@@ -22,7 +22,6 @@
#pragma once
#include <seastar/util/gcc6-concepts.hh>
#include "cql3/statements/prepared_statement.hh"
#include "service/migration_manager.hh"
@@ -89,7 +88,7 @@ public:
* @param opt_maker_args opt_maker arguments
*/
template <typename OptMaker, typename... Args>
GCC6_CONCEPT( requires seastar::CanInvoke<OptMaker, Args...> )
requires seastar::CanInvoke<OptMaker, Args...>
future<> insert(service::query_state& qs, OptMaker opt_maker, Args... opt_maker_args) {
return insert(qs, noncopyable_function<cql3::query_options ()>([opt_maker = std::move(opt_maker), args = std::make_tuple(std::move(opt_maker_args)...)] () mutable {
return apply(opt_maker, std::move(args));

View File

@@ -245,7 +245,7 @@ inline auto replacer_fn_no_op() {
}
template<typename AsyncAction>
GCC6_CONCEPT( requires requires (AsyncAction aa, sstables::sstable::version_types& c) { { aa(c) } -> future<>; } )
requires requires (AsyncAction aa, sstables::sstable::version_types& c) { { aa(c) } -> std::same_as<future<>>; }
inline
future<> for_each_sstable_version(AsyncAction action) {
return seastar::do_for_each(all_sstable_versions, std::move(action));

View File

@@ -188,14 +188,12 @@ std::string bytes_to_string(query::result_bytes_view v) {
}
namespace thrift {
GCC6_CONCEPT(
template<typename T>
concept bool Aggregator =
concept Aggregator =
requires() { typename T::type; }
&& requires(T aggregator, typename T::type* aggregation, const bytes& name, const query::result_atomic_cell_view& cell) {
{ aggregator.on_column(aggregation, name, cell) } -> void;
{ aggregator.on_column(aggregation, name, cell) } -> std::same_as<void>;
};
)
}
enum class query_order { no, yes };
@@ -1607,7 +1605,7 @@ private:
};
template<typename Aggregator, query_order QueryOrder>
GCC6_CONCEPT( requires thrift::Aggregator<Aggregator> )
requires thrift::Aggregator<Aggregator>
class column_visitor : public Aggregator {
const schema& _s;
const query::partition_slice& _slice;

View File

@@ -724,7 +724,7 @@ bool abstract_type::is_string() const {
}
template<typename Predicate>
GCC6_CONCEPT(requires CanHandleAllTypes<Predicate>)
requires CanHandleAllTypes<Predicate>
static bool find(const abstract_type& t, const Predicate& f) {
struct visitor {
const Predicate& f;

View File

@@ -217,7 +217,7 @@ public:
#endif
template<typename FragmentedBuffer>
GCC6_CONCEPT(requires FragmentRange<FragmentedBuffer>)
requires FragmentRange<FragmentedBuffer>
void process_fragmented(const FragmentedBuffer& buffer) {
using boost::range::for_each;
for_each(buffer, [this] (bytes_view bv) {

View File

@@ -26,13 +26,11 @@
#include <boost/program_options/errors.hpp>
#include <iostream>
#include <seastar/util/gcc6-concepts.hh>
#include <sstream>
#include <type_traits>
GCC6_CONCEPT(
template<typename T>
concept bool HasMapInterface = requires(T t) {
concept HasMapInterface = requires(T t) {
typename std::remove_reference<T>::type::mapped_type;
typename std::remove_reference<T>::type::key_type;
typename std::remove_reference<T>::type::value_type;
@@ -42,7 +40,6 @@ concept bool HasMapInterface = requires(T t) {
t.cbegin();
t.cend();
};
)
/// A Boost program option holding an enum value.
///
@@ -74,7 +71,7 @@ concept bool HasMapInterface = requires(T t) {
/// ("vec", po::value<vector<enum_option<Type>>>()->multitoken(), "Type vector");
/// }
template<typename Mapper>
GCC6_CONCEPT(requires HasMapInterface<decltype(Mapper::map())>)
requires HasMapInterface<decltype(Mapper::map())>
class enum_option {
using map_t = typename std::remove_reference<decltype(Mapper::map())>::type;
typename map_t::mapped_type _value;

View File

@@ -21,17 +21,15 @@
#pragma once
#include <concepts>
#include <boost/range/algorithm/copy.hpp>
#include <boost/range/algorithm/for_each.hpp>
#include <seastar/util/gcc6-concepts.hh>
#include "bytes.hh"
enum class mutable_view { no, yes, };
GCC6_CONCEPT(
/// Fragmented buffer
///
/// Concept `FragmentedBuffer` is satisfied by any class that is a range of
@@ -39,18 +37,16 @@ GCC6_CONCEPT(
/// size of the buffer. The interfaces accepting `FragmentedBuffer` will attempt
/// to avoid unnecessary linearisation.
template<typename T>
concept bool FragmentRange = requires (T range) {
concept FragmentRange = requires (T range) {
typename T::fragment_type;
requires std::is_same_v<typename T::fragment_type, bytes_view>
|| std::is_same_v<typename T::fragment_type, bytes_mutable_view>;
{ *range.begin() } -> typename T::fragment_type;
{ *range.end() } -> typename T::fragment_type;
{ range.size_bytes() } -> size_t;
{ range.empty() } -> bool; // returns true iff size_bytes() == 0.
{ *range.begin() } -> std::convertible_to<const typename T::fragment_type&>;
{ *range.end() } -> std::convertible_to<const typename T::fragment_type&>;
{ range.size_bytes() } -> std::convertible_to<size_t>;
{ range.empty() } -> std::same_as<bool>; // returns true iff size_bytes() == 0.
};
)
template<typename T, typename = void>
struct is_fragment_range : std::false_type { };
@@ -68,9 +64,7 @@ static constexpr bool is_fragment_range_v = is_fragment_range<T>::value;
/// adaptors below, i.e. it allows treating all fragment ranges
/// uniformly as views.
template <typename T>
GCC6_CONCEPT(
requires FragmentRange<T>
)
requires FragmentRange<T>
class fragment_range_view {
const T* _range;
public:
@@ -127,16 +121,12 @@ struct empty_fragment_range {
bool empty() const { return true; }
};
GCC6_CONCEPT(
static_assert(FragmentRange<empty_fragment_range>);
static_assert(FragmentRange<single_fragment_range<mutable_view::no>>);
static_assert(FragmentRange<single_fragment_range<mutable_view::yes>>);
)
template<typename FragmentedBuffer>
GCC6_CONCEPT(requires FragmentRange<FragmentedBuffer>)
requires FragmentRange<FragmentedBuffer>
bytes linearized(const FragmentedBuffer& buffer)
{
bytes b(bytes::initialized_later(), buffer.size_bytes());
@@ -149,9 +139,9 @@ bytes linearized(const FragmentedBuffer& buffer)
}
template<typename FragmentedBuffer, typename Function>
GCC6_CONCEPT(requires FragmentRange<FragmentedBuffer> && requires (Function fn, bytes_view bv) {
requires FragmentRange<FragmentedBuffer> && requires (Function fn, bytes_view bv) {
fn(bv);
})
}
decltype(auto) with_linearized(const FragmentedBuffer& buffer, Function&& fn)
{
bytes b;

View File

@@ -239,7 +239,7 @@ public:
return !(*this == other);
}
};
GCC6_CONCEPT(static_assert(FragmentRange<fragmented_temporary_buffer::view>));
static_assert(FragmentRange<fragmented_temporary_buffer::view>);
inline fragmented_temporary_buffer::operator view() const noexcept
{
@@ -251,12 +251,10 @@ inline fragmented_temporary_buffer::operator view() const noexcept
namespace fragmented_temporary_buffer_concepts {
GCC6_CONCEPT(
template<typename T>
concept bool ExceptionThrower = requires(T obj, size_t n) {
concept ExceptionThrower = requires(T obj, size_t n) {
obj.throw_out_of_range(n, n);
};
)
}
@@ -279,7 +277,7 @@ private:
}
template<typename ExceptionThrower>
GCC6_CONCEPT(requires fragmented_temporary_buffer_concepts::ExceptionThrower<ExceptionThrower>)
requires fragmented_temporary_buffer_concepts::ExceptionThrower<ExceptionThrower>
void check_out_of_range(ExceptionThrower& exceptions, size_t n) {
if (__builtin_expect(bytes_left() < n, false)) {
exceptions.throw_out_of_range(n, bytes_left());
@@ -328,7 +326,7 @@ public:
throw std::out_of_range(format("attempted to read {:d} bytes from a {:d} byte buffer", attempted_read, actual_left));
}
};
GCC6_CONCEPT(static_assert(fragmented_temporary_buffer_concepts::ExceptionThrower<default_exception_thrower>));
static_assert(fragmented_temporary_buffer_concepts::ExceptionThrower<default_exception_thrower>);
istream(const vector_type& fragments, size_t total_size) noexcept
: _current(fragments.begin())
@@ -350,7 +348,7 @@ public:
}
template<typename T, typename ExceptionThrower = default_exception_thrower>
GCC6_CONCEPT(requires fragmented_temporary_buffer_concepts::ExceptionThrower<ExceptionThrower>)
requires fragmented_temporary_buffer_concepts::ExceptionThrower<ExceptionThrower>
T read(ExceptionThrower&& exceptions = default_exception_thrower()) {
auto new_end = _current_position + sizeof(T);
if (__builtin_expect(new_end > _current_end, false)) {
@@ -363,7 +361,7 @@ public:
}
template<typename Output, typename ExceptionThrower = default_exception_thrower>
GCC6_CONCEPT(requires fragmented_temporary_buffer_concepts::ExceptionThrower<ExceptionThrower>)
requires fragmented_temporary_buffer_concepts::ExceptionThrower<ExceptionThrower>
Output read_to(size_t n, Output out, ExceptionThrower&& exceptions = default_exception_thrower()) {
auto new_end = _current_position + n;
if (__builtin_expect(new_end <= _current_end, true)) {
@@ -386,7 +384,7 @@ public:
}
template<typename ExceptionThrower = default_exception_thrower>
GCC6_CONCEPT(requires fragmented_temporary_buffer_concepts::ExceptionThrower<ExceptionThrower>)
requires fragmented_temporary_buffer_concepts::ExceptionThrower<ExceptionThrower>
view read_view(size_t n, ExceptionThrower&& exceptions = default_exception_thrower()) {
auto new_end = _current_position + n;
if (__builtin_expect(new_end <= _current_end, true)) {
@@ -407,7 +405,7 @@ public:
}
template<typename ExceptionThrower = default_exception_thrower>
GCC6_CONCEPT(requires fragmented_temporary_buffer_concepts::ExceptionThrower<ExceptionThrower>)
requires fragmented_temporary_buffer_concepts::ExceptionThrower<ExceptionThrower>
bytes_view read_bytes_view(size_t n, bytes_ostream& linearization_buffer, ExceptionThrower&& exceptions = default_exception_thrower()) {
auto new_end = _current_position + n;
if (__builtin_expect(new_end <= _current_end, true)) {

View File

@@ -32,9 +32,7 @@ namespace utils {
// Facilitates transparently reading from a fragmented range.
template<typename T, typename Exception = std::runtime_error>
GCC6_CONCEPT(
requires FragmentRange<T>
)
requires FragmentRange<T>
class linearizing_input_stream {
using iterator = typename T::iterator;
using fragment_type = typename T::fragment_type;
@@ -111,9 +109,7 @@ public:
}
template <typename Type>
GCC6_CONCEPT(
requires std::is_trivial_v<Type>
)
requires std::is_trivial_v<Type>
Type read_trivial() {
auto [bv, linearized] = do_read(sizeof(Type));
auto ret = net::ntoh(*reinterpret_cast<const net::packed<Type>*>(bv.begin()));

View File

@@ -27,7 +27,6 @@
#include <seastar/core/shared_ptr.hh>
#include <seastar/core/future.hh>
#include <seastar/core/bitops.hh>
#include <seastar/util/gcc6-concepts.hh>
#include <boost/intrusive/unordered_set.hpp>
#include <boost/iterator/transform_iterator.hpp>
#include <boost/lambda/bind.hpp>
@@ -54,12 +53,12 @@ template<typename Key,
typename EqualPred = std::equal_to<Key>,
typename Stats = do_nothing_loading_shared_values_stats,
size_t InitialBucketsCount = 16>
GCC6_CONCEPT( requires requires () {
requires requires () {
Stats::inc_hits();
Stats::inc_misses();
Stats::inc_blocks();
Stats::inc_evictions();
})
}
class loading_shared_values {
public:
using key_type = Key;

View File

@@ -26,7 +26,6 @@
#include <boost/range/algorithm/max_element.hpp>
#include <limits>
#include <seastar/core/bitops.hh>
#include <seastar/util/gcc6-concepts.hh>
#include "seastarx.hh"
namespace bi = boost::intrusive;
@@ -132,11 +131,9 @@ struct log_heap_element_traits<T, opts, false> {
* precision decreasing as values get larger.
*/
template<typename T, const log_heap_options& opts>
GCC6_CONCEPT(
requires requires() {
typename log_heap_element_traits<T, opts>;
}
)
requires requires() {
typename log_heap_element_traits<T, opts>;
}
class log_heap final {
// Ensure that (value << sub_bucket_index) in bucket_of() doesn't overflow
static_assert(pow2_rank_constexpr(opts.max_size - opts.min_size + 1) + opts.sub_bucket_shift < std::numeric_limits<size_t>::digits, "overflow");

View File

@@ -22,7 +22,6 @@
#pragma once
#include <seastar/core/memory.hh>
#include <seastar/util/gcc6-concepts.hh>
#include "bytes.hh"
#include "bytes_ostream.hh"
@@ -120,9 +119,9 @@ public:
/// size of the buffer (less than or equal the previously specified maximum
/// length).
template<typename Function>
GCC6_CONCEPT(requires requires(Function fn, bytes_mutable_view view) {
{ fn(view) } -> size_t;
})
requires requires(Function fn, bytes_mutable_view view) {
{ fn(view) } -> std::convertible_to<size_t>;
}
bytes_ostream make_buffer(size_t maximum_length, Function&& fn) {
bytes_ostream output;
bytes_mutable_view view = [&] {
@@ -142,9 +141,9 @@ public:
}
template<typename Function>
GCC6_CONCEPT(requires requires(Function fn, bytes_mutable_view view) {
{ fn(view) } -> size_t;
})
requires requires(Function fn, bytes_mutable_view view) {
{ fn(view) } -> std::same_as<size_t>;
}
fragmented_temporary_buffer make_fragmented_temporary_buffer(size_t maximum_length, size_t maximum_fragment_size, Function&& fn) {
std::vector<temporary_buffer<char>> fragments;
bytes_mutable_view view = [&] {

View File

@@ -40,7 +40,6 @@
#include <stdint.h>
#include <seastar/util/gcc6-concepts.hh>
#include <seastar/core/sstring.hh>
#include <seastar/net/byteorder.hh>
#include "bytes.hh"
@@ -60,9 +59,9 @@ static constexpr size_t serialize_int64_size = 8;
namespace internal_impl {
template <typename ExplicitIntegerType, typename CharOutputIterator, typename IntegerType>
GCC6_CONCEPT(requires std::is_integral<ExplicitIntegerType>::value && std::is_integral<IntegerType>::value && requires (CharOutputIterator it) {
requires std::is_integral<ExplicitIntegerType>::value && std::is_integral<IntegerType>::value && requires (CharOutputIterator it) {
*it++ = 'a';
})
}
inline
void serialize_int(CharOutputIterator& out, IntegerType val) {
ExplicitIntegerType nval = net::hton(ExplicitIntegerType(val));
@@ -109,9 +108,9 @@ void serialize_bool(CharOutputIterator& out, bool val) {
// For now we'll just assume those aren't in the string...
// TODO: fix the compatibility with Java even in this case.
template <typename CharOutputIterator>
GCC6_CONCEPT(requires requires (CharOutputIterator it) {
requires requires (CharOutputIterator it) {
*it++ = 'a';
})
}
inline
void serialize_string(CharOutputIterator& out, const sstring& s) {
// Java specifies that nulls in the string need to be replaced by the
@@ -132,9 +131,9 @@ void serialize_string(CharOutputIterator& out, const sstring& s) {
}
template <typename CharOutputIterator>
GCC6_CONCEPT(requires requires (CharOutputIterator it) {
requires requires (CharOutputIterator it) {
*it++ = 'a';
})
}
inline
void serialize_string(CharOutputIterator& out, const char* s) {
// TODO: like above, need to change UTF-8 when above 16-bit.

View File

@@ -21,22 +21,20 @@
#pragma once
#include <seastar/util/gcc6-concepts.hh>
#include <type_traits>
#include <concepts>
GCC6_CONCEPT(
template<typename T>
concept bool HasTriCompare =
concept HasTriCompare =
requires(const T& t) {
{ t.compare(t) } -> int;
{ t.compare(t) } -> std::same_as<int>;
} && std::is_same<std::result_of_t<decltype(&T::compare)(T, T)>, int>::value; //FIXME: #1449
)
template<typename T>
class with_relational_operators {
private:
template<typename U>
GCC6_CONCEPT( requires HasTriCompare<U> )
requires HasTriCompare<U>
int do_compare(const U& t) const {
return static_cast<const U*>(this)->compare(t);
}