aboutsummaryrefslogtreecommitdiffstats
path: root/vespalib
diff options
context:
space:
mode:
Diffstat (limited to 'vespalib')
-rw-r--r--vespalib/src/tests/traits/traits_test.cpp10
-rw-r--r--vespalib/src/vespa/vespalib/util/threadstackexecutorbase.cpp2
-rw-r--r--vespalib/src/vespa/vespalib/util/traits.h6
-rw-r--r--vespalib/src/vespa/vespalib/util/typify.h52
4 files changed, 50 insertions, 20 deletions
diff --git a/vespalib/src/tests/traits/traits_test.cpp b/vespalib/src/tests/traits/traits_test.cpp
index 0a29721df1d..7751327df75 100644
--- a/vespalib/src/tests/traits/traits_test.cpp
+++ b/vespalib/src/tests/traits/traits_test.cpp
@@ -42,4 +42,14 @@ TEST("require that can_skip_destruction works") {
EXPECT_EQUAL(can_skip_destruction<Child2>::value, true);
}
+struct NoType {};
+struct TypeType { using type = NoType; };
+struct NoTypeType { static constexpr int type = 3; };
+
+TEST("require that type type member can be detected") {
+ EXPECT_FALSE(has_type_type_v<NoType>);
+ EXPECT_TRUE(has_type_type_v<TypeType>);
+ EXPECT_FALSE(has_type_type_v<NoTypeType>);
+}
+
TEST_MAIN() { TEST_RUN_ALL(); }
diff --git a/vespalib/src/vespa/vespalib/util/threadstackexecutorbase.cpp b/vespalib/src/vespa/vespalib/util/threadstackexecutorbase.cpp
index efb1dbf4054..ad5d78d5ab6 100644
--- a/vespalib/src/vespa/vespalib/util/threadstackexecutorbase.cpp
+++ b/vespalib/src/vespa/vespalib/util/threadstackexecutorbase.cpp
@@ -87,6 +87,7 @@ ThreadStackExecutorBase::obtainTask(Worker &worker)
if (!worker.idle) {
assert(_taskCount != 0);
--_taskCount;
+ wakeup(monitor);
_barrier.completeEvent(worker.task.token);
worker.idle = true;
}
@@ -96,7 +97,6 @@ ThreadStackExecutorBase::obtainTask(Worker &worker)
worker.task = std::move(_tasks.front());
worker.idle = false;
_tasks.pop();
- wakeup(monitor);
return true;
}
if (_closed) {
diff --git a/vespalib/src/vespa/vespalib/util/traits.h b/vespalib/src/vespa/vespalib/util/traits.h
index eb0385abc72..7f8945954a8 100644
--- a/vespalib/src/vespa/vespalib/util/traits.h
+++ b/vespalib/src/vespa/vespalib/util/traits.h
@@ -39,4 +39,10 @@ struct can_skip_destruction : std::is_trivially_destructible<T> {};
//-----------------------------------------------------------------------------
+template <typename, typename = std::void_t<>> struct has_type_type : std::false_type {};
+template <typename T> struct has_type_type<T, std::void_t<typename T::type>> : std::true_type {};
+template <typename T> constexpr bool has_type_type_v = has_type_type<T>::value;
+
+//-----------------------------------------------------------------------------
+
} // namespace vespalib
diff --git a/vespalib/src/vespa/vespalib/util/typify.h b/vespalib/src/vespa/vespalib/util/typify.h
index a2a24baca41..0d84d1756a5 100644
--- a/vespalib/src/vespa/vespalib/util/typify.h
+++ b/vespalib/src/vespa/vespalib/util/typify.h
@@ -2,6 +2,7 @@
#pragma once
+#include "traits.h"
#include <stddef.h>
#include <utility>
@@ -10,27 +11,40 @@ namespace vespalib {
//-----------------------------------------------------------------------------
/**
- * Typification result for values resolving into actual types.
+ * Typification result for values resolving into actual types. Using
+ * this exact template is not required, but the result type must have
+ * the name 'type' for the auto-unwrapping performed by typify_invoke
+ * to work.
**/
template <typename T> struct TypifyResultType {
- static constexpr bool is_type = true;
using type = T;
};
/**
- * Typification result for values resolving into compile-time values
- * which are also types as long as they are kept inside their result
- * wrappers.
+ * Typification result for values resolving into non-types. Using this
+ * exact template is not required, but is supplied for
+ * convenience. The resolved compile-time value should be called
+ * 'value' for consistency across typifiers.
**/
template <typename T, T VALUE> struct TypifyResultValue {
- static constexpr bool is_type = false;
static constexpr T value = VALUE;
};
/**
+ * Typification result for values resolving into simple templates
+ * (templated on one type). Using this exact template is not required,
+ * but is supplied for convenience and as example. The resolved
+ * template should be called 'templ' for consistency across typifiers.
+ **/
+template <template<typename> typename TT> struct TypifyResultSimpleTemplate {
+ template <typename T> using templ = TT<T>;
+};
+
+/**
* A Typifier is able to take a run-time value and resolve it into a
- * type. The resolve result is passed to the specified function in the
- * form of a thin result wrapper.
+ * type, non-type constant value or a template. The resolve result is
+ * passed to the specified function in the form of a thin result
+ * wrapper.
**/
struct TypifyBool {
template <bool VALUE> using Result = TypifyResultValue<bool, VALUE>;
@@ -63,14 +77,14 @@ template <size_t N, typename Typifier, typename Target, typename ...Rs> struct T
return Target::template invoke<Rs...>(std::forward<T>(value), std::forward<Args>(args)...);
} else {
return Typifier::resolve(value, [&](auto t)->decltype(auto)
- {
- using X = decltype(t);
- if constexpr (X::is_type) {
- return TypifyInvokeImpl<N, Typifier, Target, Rs..., typename X::type>::select(std::forward<Args>(args)...);
- } else {
- return TypifyInvokeImpl<N, Typifier, Target, Rs..., X>::select(std::forward<Args>(args)...);
- }
- });
+ {
+ using X = decltype(t);
+ if constexpr (has_type_type_v<X>) {
+ return TypifyInvokeImpl<N, Typifier, Target, Rs..., typename X::type>::select(std::forward<Args>(args)...);
+ } else {
+ return TypifyInvokeImpl<N, Typifier, Target, Rs..., X>::select(std::forward<Args>(args)...);
+ }
+ });
}
}
};
@@ -82,9 +96,9 @@ template <size_t N, typename Typifier, typename Target, typename ...Rs> struct T
* the typification results from the N first parameters as template
* parameters. Note that typification results that are types are
* unwrapped before being used as template parameters while
- * typification results that are compile-time values are kept in their
- * wrappers when passed as template parameters. Please refer to the
- * unit test for examples.
+ * typification results that are non-types or templates are kept in
+ * their wrappers when passed as template parameters. Please refer to
+ * the unit test for examples.
**/
template <size_t N, typename Typifier, typename Target, typename ...Args> decltype(auto) typify_invoke(Args && ...args) {
static_assert(N > 0);