aboutsummaryrefslogtreecommitdiffstats
path: root/vespalib
diff options
context:
space:
mode:
Diffstat (limited to 'vespalib')
-rw-r--r--vespalib/CMakeLists.txt1
-rw-r--r--vespalib/src/tests/coro/active_work/CMakeLists.txt9
-rw-r--r--vespalib/src/tests/coro/active_work/active_work_test.cpp66
-rw-r--r--vespalib/src/tests/objects/nbostream/nbostream_test.cpp10
-rw-r--r--vespalib/src/vespa/vespalib/coro/CMakeLists.txt1
-rw-r--r--vespalib/src/vespa/vespalib/coro/active_work.cpp21
-rw-r--r--vespalib/src/vespa/vespalib/coro/active_work.h42
-rw-r--r--vespalib/src/vespa/vespalib/coro/lazy.h4
-rw-r--r--vespalib/src/vespa/vespalib/objects/deserializer.h5
-rw-r--r--vespalib/src/vespa/vespalib/objects/deserializer.hpp12
-rw-r--r--vespalib/src/vespa/vespalib/objects/nbostream.h21
-rw-r--r--vespalib/src/vespa/vespalib/objects/serializer.h4
-rw-r--r--vespalib/src/vespa/vespalib/objects/serializer.hpp10
-rw-r--r--vespalib/src/vespa/vespalib/objects/visit.hpp4
-rw-r--r--vespalib/src/vespa/vespalib/stllike/cache.h4
-rw-r--r--vespalib/src/vespa/vespalib/stllike/cache.hpp7
-rw-r--r--vespalib/src/vespa/vespalib/util/array.h97
-rw-r--r--vespalib/src/vespa/vespalib/util/array.hpp10
-rw-r--r--vespalib/src/vespa/vespalib/util/array_equal.hpp4
19 files changed, 201 insertions, 131 deletions
diff --git a/vespalib/CMakeLists.txt b/vespalib/CMakeLists.txt
index dc99146fd3f..6d19988b96b 100644
--- a/vespalib/CMakeLists.txt
+++ b/vespalib/CMakeLists.txt
@@ -46,6 +46,7 @@ vespa_define_module(
src/tests/component
src/tests/compress
src/tests/compression
+ src/tests/coro/active_work
src/tests/coro/async_io
src/tests/coro/detached
src/tests/coro/generator
diff --git a/vespalib/src/tests/coro/active_work/CMakeLists.txt b/vespalib/src/tests/coro/active_work/CMakeLists.txt
new file mode 100644
index 00000000000..b230e10dbc7
--- /dev/null
+++ b/vespalib/src/tests/coro/active_work/CMakeLists.txt
@@ -0,0 +1,9 @@
+# Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+vespa_add_executable(vespalib_active_work_test_app TEST
+ SOURCES
+ active_work_test.cpp
+ DEPENDS
+ vespalib
+ GTest::GTest
+)
+vespa_add_test(NAME vespalib_active_work_test_app COMMAND vespalib_active_work_test_app)
diff --git a/vespalib/src/tests/coro/active_work/active_work_test.cpp b/vespalib/src/tests/coro/active_work/active_work_test.cpp
new file mode 100644
index 00000000000..26c0c3dd71a
--- /dev/null
+++ b/vespalib/src/tests/coro/active_work/active_work_test.cpp
@@ -0,0 +1,66 @@
+// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+
+#include <vespa/vespalib/coro/lazy.h>
+#include <vespa/vespalib/coro/schedule.h>
+#include <vespa/vespalib/coro/completion.h>
+#include <vespa/vespalib/coro/active_work.h>
+#include <vespa/vespalib/util/time.h>
+#include <vespa/vespalib/util/threadstackexecutor.h>
+#include <vespa/vespalib/gtest/gtest.h>
+
+using namespace vespalib;
+using namespace vespalib::coro;
+
+Lazy<int> make_expensive_task(Executor &executor, int value) {
+ co_await schedule(executor);
+ auto cpu_cost = 20ms;
+ std::this_thread::sleep_for(cpu_cost);
+ co_return value;
+}
+
+Lazy<int> make_cheap_task(Executor &, int value) {
+ co_return value;
+}
+
+Lazy<int> concurrent_sum(Executor &executor, std::vector<int> values,
+ std::function<Lazy<int>(Executor &,int)> make_task)
+{
+ std::vector<Lazy<int>> work;
+ for (int v: values) {
+ work.push_back(make_task(executor, v));
+ }
+ ActiveWork active;
+ for (auto &task: work) {
+ active.start(task);
+ }
+ co_await active.join();
+ int res = 0;
+ for (auto &task: work) {
+ res += co_await task; // await_ready == true
+ }
+ co_return res;
+}
+
+TEST(ActiveWorkTest, run_expensive_subtasks_concurrently) {
+ vespalib::ThreadStackExecutor executor(8);
+ auto t0 = steady_clock::now();
+ auto result = sync_wait(concurrent_sum(executor, {1, 2, 3, 4, 5, 6, 7, 8,
+ 9,10,11,12,13,14,15,16},
+ make_expensive_task));
+ auto td = steady_clock::now() - t0;
+ EXPECT_EQ(result, 136);
+ fprintf(stderr, "time spent: %zu ms\n", count_ms(td));
+}
+
+TEST(ActiveWorkTest, run_cheap_subtasks_concurrently) {
+ vespalib::ThreadStackExecutor executor(1);
+ auto t0 = steady_clock::now();
+ auto result = sync_wait(concurrent_sum(executor, {1, 2, 3, 4, 5, 6, 7, 8,
+ 9,10,11,12,13,14,15,16},
+ make_cheap_task));
+ auto td = steady_clock::now() - t0;
+ EXPECT_EQ(result, 136);
+ fprintf(stderr, "time spent: %zu ms\n", count_ms(td));
+}
+
+GTEST_MAIN_RUN_ALL_TESTS()
diff --git a/vespalib/src/tests/objects/nbostream/nbostream_test.cpp b/vespalib/src/tests/objects/nbostream/nbostream_test.cpp
index 5d7f5c0504b..20ea2bf5aaa 100644
--- a/vespalib/src/tests/objects/nbostream/nbostream_test.cpp
+++ b/vespalib/src/tests/objects/nbostream/nbostream_test.cpp
@@ -216,16 +216,6 @@ TEST_F("Test serializing vespalib::string", Fixture)
f.assertSerialize(exp, val);
}
-TEST_F("Test serializing vespalib::Array", Fixture)
-{
- vespalib::Array<int16_t> val;
- val.resize(2);
- val[0] = 0x0123;
- val[1] = 0x4567;
- ExpBuffer exp({ 0x00, 0x00, 0x00, 0x02, 0x01, 0x23, 0x45, 0x67 });
- f.assertSerialize(exp, val);
-}
-
TEST_F("Test serializing std::vector", Fixture)
{
std::vector<int16_t> val({ 0x0123, 0x4567 });
diff --git a/vespalib/src/vespa/vespalib/coro/CMakeLists.txt b/vespalib/src/vespa/vespalib/coro/CMakeLists.txt
index 8a7a0ade049..ed30f224eab 100644
--- a/vespalib/src/vespa/vespalib/coro/CMakeLists.txt
+++ b/vespalib/src/vespa/vespalib/coro/CMakeLists.txt
@@ -1,6 +1,7 @@
# Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
vespa_add_library(vespalib_vespalib_coro OBJECT
SOURCES
+ active_work.cpp
async_crypto_socket.cpp
async_io.cpp
DEPENDS
diff --git a/vespalib/src/vespa/vespalib/coro/active_work.cpp b/vespalib/src/vespa/vespalib/coro/active_work.cpp
new file mode 100644
index 00000000000..403da5173fe
--- /dev/null
+++ b/vespalib/src/vespa/vespalib/coro/active_work.cpp
@@ -0,0 +1,21 @@
+// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+
+#include "active_work.h"
+#include <cassert>
+
+namespace vespalib::coro {
+
+bool
+ActiveWork::join_awaiter::await_suspend(std::coroutine_handle<> handle) noexcept
+{
+ self._waiting = handle;
+ return (self._pending.fetch_sub(1, std::memory_order_acq_rel) > 1);
+}
+
+ActiveWork::~ActiveWork()
+{
+ // NB: join must be called, even if there is no other work
+ assert(_pending.load(std::memory_order_relaxed) == 0);
+}
+
+}
diff --git a/vespalib/src/vespa/vespalib/coro/active_work.h b/vespalib/src/vespa/vespalib/coro/active_work.h
new file mode 100644
index 00000000000..9f4079615c7
--- /dev/null
+++ b/vespalib/src/vespa/vespalib/coro/active_work.h
@@ -0,0 +1,42 @@
+// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+
+#pragma once
+
+#include "lazy.h"
+#include "detached.h"
+#include <coroutine>
+#include <atomic>
+
+namespace vespalib::coro {
+
+// Tracks work that is being performed concurrently
+class ActiveWork {
+private:
+ std::atomic<uint32_t> _pending;
+ std::coroutine_handle<> _waiting;
+ template <typename T>
+ Detached signal_when_done(Lazy<T> &lazy) {
+ co_await lazy.done();
+ if (_pending.fetch_sub(1, std::memory_order_acq_rel) == 1) {
+ _waiting.resume();
+ }
+ }
+ struct join_awaiter {
+ ActiveWork &self;
+ join_awaiter(ActiveWork &self_in) noexcept : self(self_in) {}
+ constexpr bool await_ready() const noexcept { return false; }
+ constexpr void await_resume() const noexcept {}
+ bool await_suspend(std::coroutine_handle<> handle) noexcept __attribute__((noinline));
+ };
+public:
+ ActiveWork() : _pending(1), _waiting(std::noop_coroutine()) {}
+ ~ActiveWork();
+ template <typename T>
+ void start(Lazy<T> &lazy) {
+ _pending.fetch_add(1, std::memory_order_relaxed);
+ signal_when_done(lazy);
+ }
+ auto join() noexcept { return join_awaiter(*this); }
+};
+
+}
diff --git a/vespalib/src/vespa/vespalib/coro/lazy.h b/vespalib/src/vespa/vespalib/coro/lazy.h
index 17077dccc9f..87abb2e4f99 100644
--- a/vespalib/src/vespa/vespalib/coro/lazy.h
+++ b/vespalib/src/vespa/vespalib/coro/lazy.h
@@ -75,6 +75,9 @@ private:
struct Result {
static Received<T>&& get(auto &&promise) { return std::move(promise.result); }
};
+ struct Nothing {
+ static void get(auto &&) {}
+ };
public:
Lazy(const Lazy &) = delete;
@@ -84,6 +87,7 @@ public:
auto operator co_await() & noexcept { return WaitFor<LValue>(_handle); }
auto operator co_await() && noexcept { return WaitFor<RValue>(_handle); }
auto forward() noexcept { return WaitFor<Result>(_handle); }
+ auto done() noexcept { return WaitFor<Nothing>(_handle); }
~Lazy() {
if (_handle) {
_handle.destroy();
diff --git a/vespalib/src/vespa/vespalib/objects/deserializer.h b/vespalib/src/vespa/vespalib/objects/deserializer.h
index e59d3e07581..dcb1b5176cb 100644
--- a/vespalib/src/vespa/vespalib/objects/deserializer.h
+++ b/vespalib/src/vespa/vespalib/objects/deserializer.h
@@ -1,7 +1,6 @@
// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
#pragma once
-#include <vespa/vespalib/util/array.h>
#include <vespa/vespalib/stllike/string.h>
#include <vector>
#include <cstdint>
@@ -44,11 +43,7 @@ public:
Deserializer & operator >> (double & value) { return get(value); }
Deserializer & operator >> (string & value) { return get(value); }
template <typename T>
- Deserializer & operator >> (vespalib::Array<T> & v);
- template <typename T>
Deserializer & operator >> (std::vector<T> & v);
-
};
}
-
diff --git a/vespalib/src/vespa/vespalib/objects/deserializer.hpp b/vespalib/src/vespa/vespalib/objects/deserializer.hpp
index b90867fa153..cf9bd5b0a48 100644
--- a/vespalib/src/vespa/vespalib/objects/deserializer.hpp
+++ b/vespalib/src/vespa/vespalib/objects/deserializer.hpp
@@ -7,18 +7,6 @@ namespace vespalib {
template <typename T>
Deserializer &
-Deserializer::operator >> (vespalib::Array<T> & v) {
- uint32_t sz;
- get(sz);
- v.resize(sz);
- for(size_t i(0); i < sz; i++) {
- (*this) >> v[i];
- }
- return *this;
-}
-
-template <typename T>
-Deserializer &
Deserializer::operator >> (std::vector<T> & v) {
uint32_t sz;
get(sz);
diff --git a/vespalib/src/vespa/vespalib/objects/nbostream.h b/vespalib/src/vespa/vespalib/objects/nbostream.h
index 12d4fac04cc..bf2adc7b486 100644
--- a/vespalib/src/vespa/vespalib/objects/nbostream.h
+++ b/vespalib/src/vespa/vespalib/objects/nbostream.h
@@ -87,25 +87,6 @@ public:
return *this;
}
template <typename T>
- nbostream & operator << (const vespalib::Array<T> & v) {
- uint32_t sz(v.size());
- (*this) << sz;
- for(size_t i(0); i < sz; i++) {
- (*this) << v[i];
- }
- return *this;
- }
- template <typename T>
- nbostream & operator >> (vespalib::Array<T> & v) {
- uint32_t sz;
- (*this) >> sz;
- v.resize(sz);
- for(size_t i(0); i < sz; i++) {
- (*this) >> v[i];
- }
- return *this;
- }
- template <typename T>
nbostream & operator << (const std::vector<T> & v) {
uint32_t sz(v.size());
(*this) << sz;
@@ -175,8 +156,6 @@ public:
}
void swap(Buffer & buf);
void swap(nbostream & os);
- /** extract the underlying Array<char>; nbostream will be empty afterwards. */
- Buffer extract_buffer() { Buffer rv; swap(rv); return rv; }
/**
* This flag can be used to tell that a buffer will live at least as long as
* any objects it will be the backing for. In those cases there is no need for
diff --git a/vespalib/src/vespa/vespalib/objects/serializer.h b/vespalib/src/vespa/vespalib/objects/serializer.h
index f10d03b1c04..f8a43ab104a 100644
--- a/vespalib/src/vespa/vespalib/objects/serializer.h
+++ b/vespalib/src/vespa/vespalib/objects/serializer.h
@@ -1,7 +1,6 @@
// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
#pragma once
-#include <vespa/vespalib/util/array.h>
#include <vespa/vespalib/stllike/string.h>
#include <vector>
#include <cstdint>
@@ -42,10 +41,7 @@ public:
Serializer & operator << (double value) { return put(value); }
Serializer & operator << (stringref value) { return put(value); }
template <typename T>
- Serializer & operator << (const vespalib::Array<T> & v);
- template <typename T>
Serializer & operator << (const std::vector<T> & v);
};
}
-
diff --git a/vespalib/src/vespa/vespalib/objects/serializer.hpp b/vespalib/src/vespa/vespalib/objects/serializer.hpp
index 87c02ddf693..1962ddd4359 100644
--- a/vespalib/src/vespa/vespalib/objects/serializer.hpp
+++ b/vespalib/src/vespa/vespalib/objects/serializer.hpp
@@ -9,16 +9,6 @@ namespace vespalib {
template <typename T>
Serializer &
-Serializer::operator << (const vespalib::Array<T> & v) {
- uint32_t sz(v.size());
- put(sz);
- for(size_t i(0); i < sz; i++) {
- (*this) << v[i];
- }
- return *this;
-}
-template <typename T>
-Serializer &
Serializer::operator << (const std::vector<T> & v) {
uint32_t sz(v.size());
put(sz);
diff --git a/vespalib/src/vespa/vespalib/objects/visit.hpp b/vespalib/src/vespa/vespalib/objects/visit.hpp
index e3a82b212c0..9838e331823 100644
--- a/vespalib/src/vespa/vespalib/objects/visit.hpp
+++ b/vespalib/src/vespa/vespalib/objects/visit.hpp
@@ -2,9 +2,9 @@
#pragma once
#include "visit.h"
-#include <vector>
-#include <vespa/vespalib/util/stringfmt.h>
#include "objectvisitor.h"
+#include <vespa/vespalib/util/stringfmt.h>
+#include <vespa/vespalib/util/array.h>
#include "identifiable.hpp"
template<typename T>
diff --git a/vespalib/src/vespa/vespalib/stllike/cache.h b/vespalib/src/vespa/vespalib/stllike/cache.h
index 907fbdd54c9..f7456cda197 100644
--- a/vespalib/src/vespa/vespalib/stllike/cache.h
+++ b/vespalib/src/vespa/vespalib/stllike/cache.h
@@ -69,10 +69,6 @@ public:
* Can be used for controlling max number of elements.
*/
cache & maxElements(size_t elems);
- /**
- * Can be used for reserving space for elements.
- */
- cache & reserveElements(size_t elems);
cache & setCapacityBytes(size_t sz);
diff --git a/vespalib/src/vespa/vespalib/stllike/cache.hpp b/vespalib/src/vespa/vespalib/stllike/cache.hpp
index 8e449fcfca4..4e7736c9e5f 100644
--- a/vespalib/src/vespa/vespalib/stllike/cache.hpp
+++ b/vespalib/src/vespa/vespalib/stllike/cache.hpp
@@ -16,13 +16,6 @@ cache<P>::maxElements(size_t elems) {
template< typename P >
cache<P> &
-cache<P>::reserveElements(size_t elems) {
- Lru::reserve(elems);
- return *this;
-}
-
-template< typename P >
-cache<P> &
cache<P>::setCapacityBytes(size_t sz) {
_maxBytes.store(sz, std::memory_order_relaxed);
return *this;
diff --git a/vespalib/src/vespa/vespalib/util/array.h b/vespalib/src/vespa/vespalib/util/array.h
index e9d8c9ccfdb..7b23f6245c7 100644
--- a/vespalib/src/vespa/vespalib/util/array.h
+++ b/vespalib/src/vespa/vespalib/util/array.h
@@ -16,77 +16,76 @@ class Array {
public:
class reverse_iterator {
public:
- reverse_iterator() : _p(NULL) { }
- reverse_iterator(T * p) : _p(p) { }
- T & operator *() { return _p[0]; }
- T * operator -> () { return _p; }
- reverse_iterator operator -(size_t n) { return _p + n; }
- reverse_iterator operator +(size_t n) { return _p - n; }
- reverse_iterator & operator ++ () {
+ reverse_iterator() noexcept : _p(nullptr) { }
+ reverse_iterator(T * p) noexcept : _p(p) { }
+ T & operator *() noexcept { return _p[0]; }
+ T * operator -> () noexcept { return _p; }
+ reverse_iterator operator -(size_t n) noexcept { return _p + n; }
+ reverse_iterator operator +(size_t n) noexcept { return _p - n; }
+ reverse_iterator & operator ++ () noexcept {
_p--;
return *this;
}
- reverse_iterator operator ++ (int) {
+ reverse_iterator operator ++ (int) noexcept {
reverse_iterator prev = *this;
_p--;
return prev;
}
- reverse_iterator & operator -- () {
+ reverse_iterator & operator -- () noexcept {
_p++;
return *this;
}
- reverse_iterator operator -- (int) {
+ reverse_iterator operator -- (int) noexcept {
reverse_iterator prev = *this;
_p++;
return prev;
}
- T * get() { return _p; }
+ T * get() noexcept { return _p; }
private:
- friend size_t operator -(reverse_iterator a, reverse_iterator b) { return b._p - a._p; }
+ friend size_t operator -(reverse_iterator a, reverse_iterator b) noexcept { return b._p - a._p; }
T * _p;
};
class const_reverse_iterator {
public:
- const_reverse_iterator() : _p(NULL) { }
- const_reverse_iterator(const T * p) : _p(p) { }
- const_reverse_iterator(reverse_iterator i) : _p(i.get()) { }
- const T & operator *() const { return _p[0]; }
- const T * operator -> () const { return _p; }
- const_reverse_iterator operator -(size_t n) { return _p + n; }
- const_reverse_iterator operator +(size_t n) { return _p - n; }
- const_reverse_iterator & operator ++ () {
+ const_reverse_iterator() noexcept : _p(nullptr) { }
+ const_reverse_iterator(const T * p) noexcept : _p(p) { }
+ const_reverse_iterator(reverse_iterator i) noexcept : _p(i.get()) { }
+ const T & operator *() const noexcept { return _p[0]; }
+ const T * operator -> () const noexcept { return _p; }
+ const_reverse_iterator operator -(size_t n) noexcept { return _p + n; }
+ const_reverse_iterator operator +(size_t n) noexcept { return _p - n; }
+ const_reverse_iterator & operator ++ () noexcept {
_p--;
return *this;
}
- const_reverse_iterator operator ++ (int) {
+ const_reverse_iterator operator ++ (int) noexcept {
const_reverse_iterator prev = *this;
_p--;
return prev;
}
- const_reverse_iterator & operator -- () {
+ const_reverse_iterator & operator -- () noexcept {
_p++;
return *this;
}
- const_reverse_iterator operator -- (int) {
+ const_reverse_iterator operator -- (int) noexcept {
const_reverse_iterator prev = *this;
_p++;
return prev;
}
private:
- friend size_t operator -(const_reverse_iterator a, const_reverse_iterator b) { return b._p - a._p; }
+ friend size_t operator -(const_reverse_iterator a, const_reverse_iterator b) noexcept { return b._p - a._p; }
const T * _p;
};
using Alloc = alloc::Alloc;
using const_iterator = const T *;
using iterator = T *;
- using const_reference = const T &;
using value_type = T;
using size_type = size_t;
Array(const Alloc & initial=Alloc::alloc());
Array(size_t sz, const Alloc & initial=Alloc::alloc());
- Array(Alloc && buf, size_t sz);
+ Array(Alloc && buf, size_t sz) noexcept;
Array(Array &&rhs) noexcept;
Array(size_t sz, T value, const Alloc & initial=Alloc::alloc());
Array(const_iterator begin, const_iterator end, const Alloc & initial=Alloc::alloc());
@@ -94,7 +93,7 @@ public:
Array & operator =(const Array & rhs);
Array & operator =(Array && rhs) noexcept;
~Array();
- void swap(Array & rhs) {
+ void swap(Array & rhs) noexcept {
_array.swap(rhs._array);
std::swap(_sz, rhs._sz);
}
@@ -117,39 +116,39 @@ public:
std::destroy_at(array(_sz));
}
- T & back() { return *array(_sz-1); }
- const T & back() const { return *array(_sz-1); }
- const_iterator begin() const { return array(0); }
- const_iterator end() const { return array(_sz); }
- iterator begin() { return array(0); }
- iterator end() { return array(_sz); }
- const_reverse_iterator rbegin() const { return empty() ? array(0) : array(_sz) - 1; }
- const_reverse_iterator rend() const { return empty() ? array(0) : array(0) - 1; }
- reverse_iterator rbegin() { return empty() ? array(0) : array(_sz) - 1; }
- reverse_iterator rend() { return empty() ? array(0) : array(0) - 1; }
- size_t size() const { return _sz; }
- size_t capacity() const { return _array.size()/sizeof(T); }
+ T & back() noexcept { return *array(_sz-1); }
+ const T & back() const noexcept { return *array(_sz-1); }
+ const_iterator begin() const noexcept { return array(0); }
+ const_iterator end() const noexcept { return array(_sz); }
+ iterator begin() noexcept { return array(0); }
+ iterator end() noexcept { return array(_sz); }
+ const_reverse_iterator rbegin() const noexcept { return empty() ? array(0) : array(_sz) - 1; }
+ const_reverse_iterator rend() const noexcept { return empty() ? array(0) : array(0) - 1; }
+ reverse_iterator rbegin() noexcept { return empty() ? array(0) : array(_sz) - 1; }
+ reverse_iterator rend() noexcept { return empty() ? array(0) : array(0) - 1; }
+ size_t size() const noexcept { return _sz; }
+ size_t capacity() const noexcept { return _array.size()/sizeof(T); }
void clear() {
std::destroy(array(0), array(_sz));
_sz = 0;
}
void reset();
- bool empty() const { return _sz == 0; }
- T * data() noexcept { return static_cast<T *>(_array.get()); }
- const T * data() const noexcept { return static_cast<const T *>(_array.get()); }
- T & operator [] (size_t i) { return *array(i); }
- const T & operator [] (size_t i) const { return *array(i); }
- bool operator == (const Array & rhs) const;
- bool operator != (const Array & rhs) const;
+ bool empty() const noexcept { return _sz == 0; }
+ T * data() noexcept { return static_cast<T *>(_array.get()); }
+ const T * data() const noexcept { return static_cast<const T *>(_array.get()); }
+ T & operator [] (size_t i) noexcept { return *array(i); }
+ const T & operator [] (size_t i) const noexcept { return *array(i); }
+ bool operator == (const Array & rhs) const noexcept;
+ bool operator != (const Array & rhs) const noexcept;
- static Alloc stealAlloc(Array && rhs) {
+ static Alloc stealAlloc(Array && rhs) noexcept {
rhs._sz = 0;
return std::move(rhs._array);
}
Array<T> create() const;
private:
- T * array(size_t i) { return static_cast<T *>(_array.get()) + i; }
- const T * array(size_t i) const { return static_cast<const T *>(_array.get()) + i; }
+ T * array(size_t i) noexcept { return static_cast<T *>(_array.get()) + i; }
+ const T * array(size_t i) const noexcept { return static_cast<const T *>(_array.get()) + i; }
void cleanup();
void increase(size_t n);
void extend(size_t n) {
diff --git a/vespalib/src/vespa/vespalib/util/array.hpp b/vespalib/src/vespa/vespalib/util/array.hpp
index 24136e544b8..a68aca1ddb0 100644
--- a/vespalib/src/vespa/vespalib/util/array.hpp
+++ b/vespalib/src/vespa/vespalib/util/array.hpp
@@ -17,7 +17,7 @@ void construct(T * dest, const T * source, size_t sz, std::false_type)
}
template <typename T>
-void construct(T * dest, const T * source, size_t sz, std::true_type)
+void construct(T * dest, const T * source, size_t sz, std::true_type) noexcept
{
memcpy(dest, source, sz*sizeof(T));
}
@@ -32,7 +32,7 @@ void construct(T * dest, size_t sz, std::false_type)
}
template <typename T>
-void construct(T * dest, size_t sz, std::true_type)
+void construct(T * dest, size_t sz, std::true_type) noexcept
{
(void) dest;
(void) sz;
@@ -123,7 +123,7 @@ void Array<T>::resize(size_t n)
}
template <typename T>
-void move(T * dest, T * source, size_t sz, std::false_type)
+void move(T * dest, T * source, size_t sz, std::false_type) noexcept
{
for (size_t i(0); i < sz; i++) {
::new (static_cast<void *>(dest + i)) T(std::move(*(source + i)));
@@ -132,7 +132,7 @@ void move(T * dest, T * source, size_t sz, std::false_type)
}
template <typename T>
-void move(T * dest, const T * source, size_t sz, std::true_type)
+void move(T * dest, const T * source, size_t sz, std::true_type) noexcept
{
memcpy(dest, source, sz*sizeof(T));
}
@@ -154,7 +154,7 @@ Array<T>::Array(const Alloc & initial)
{ }
template <typename T>
-Array<T>::Array(Alloc && buf, size_t sz) :
+Array<T>::Array(Alloc && buf, size_t sz) noexcept :
_array(std::move(buf)),
_sz(sz)
{
diff --git a/vespalib/src/vespa/vespalib/util/array_equal.hpp b/vespalib/src/vespa/vespalib/util/array_equal.hpp
index 3b3aab6280b..3e7e624b6e9 100644
--- a/vespalib/src/vespa/vespalib/util/array_equal.hpp
+++ b/vespalib/src/vespa/vespalib/util/array_equal.hpp
@@ -6,7 +6,7 @@
namespace vespalib {
template <typename T>
-bool Array<T>::operator ==(const Array & rhs) const
+bool Array<T>::operator ==(const Array & rhs) const noexcept
{
bool retval(size() == rhs.size());
for (size_t i(0); retval && (i < _sz); i++) {
@@ -18,7 +18,7 @@ bool Array<T>::operator ==(const Array & rhs) const
}
template <typename T>
-bool Array<T>::operator != (const Array & rhs) const {
+bool Array<T>::operator != (const Array & rhs) const noexcept {
return !(*this == rhs);
}