summaryrefslogtreecommitdiffstats
path: root/vespalib
diff options
context:
space:
mode:
authorHenning Baldersheim <balder@yahoo-inc.com>2017-08-11 12:29:46 +0200
committerHenning Baldersheim <balder@yahoo-inc.com>2017-08-11 12:30:24 +0200
commit41709673f0165f16496ecf37162ed7dac06b5295 (patch)
treec213da683873bbe88927a3de58eb93f3f231a693 /vespalib
parent2fe073e8e1875bc891c38099c880d156bd228e9d (diff)
Use std::atomic all over and completely get rid of homegrown atomics.
Diffstat (limited to 'vespalib')
-rw-r--r--vespalib/CMakeLists.txt2
-rw-r--r--vespalib/src/testlist.txt1
-rw-r--r--vespalib/src/tests/atomic/.gitignore6
-rw-r--r--vespalib/src/tests/atomic/CMakeLists.txt15
-rw-r--r--vespalib/src/tests/atomic/DESC1
-rw-r--r--vespalib/src/tests/atomic/FILES1
-rw-r--r--vespalib/src/tests/atomic/atomic_bench.cpp105
-rw-r--r--vespalib/src/tests/atomic/atomic_test.cpp339
-rw-r--r--vespalib/src/tests/executor/threadstackexecutor_test.cpp14
-rw-r--r--vespalib/src/tests/weakref/.gitignore4
-rw-r--r--vespalib/src/tests/weakref/CMakeLists.txt8
-rw-r--r--vespalib/src/tests/weakref/DESC1
-rw-r--r--vespalib/src/tests/weakref/FILES1
-rw-r--r--vespalib/src/tests/weakref/weakref_test.cpp43
-rw-r--r--vespalib/src/vespa/vespalib/util/CMakeLists.txt1
-rw-r--r--vespalib/src/vespa/vespalib/util/atomic.cpp221
-rw-r--r--vespalib/src/vespa/vespalib/util/atomic.h468
-rw-r--r--vespalib/src/vespa/vespalib/util/overview.h5
-rw-r--r--vespalib/src/vespa/vespalib/util/ptrholder.h1
-rw-r--r--vespalib/src/vespa/vespalib/util/referencecounter.h13
-rw-r--r--vespalib/src/vespa/vespalib/util/weakref.h259
21 files changed, 14 insertions, 1495 deletions
diff --git a/vespalib/CMakeLists.txt b/vespalib/CMakeLists.txt
index 93ac717d9ef..cab5ce0ff4a 100644
--- a/vespalib/CMakeLists.txt
+++ b/vespalib/CMakeLists.txt
@@ -16,7 +16,6 @@ vespa_define_module(
src/tests/approx
src/tests/array
src/tests/arrayqueue
- src/tests/atomic
src/tests/barrier
src/tests/benchmark_timer
src/tests/box
@@ -98,7 +97,6 @@ vespa_define_module(
src/tests/util/generationhandler
src/tests/util/generationhandler_stress
src/tests/valgrind
- src/tests/weakref
src/tests/websocket
src/tests/zcurve
diff --git a/vespalib/src/testlist.txt b/vespalib/src/testlist.txt
index 02e66607eeb..68a1136e025 100644
--- a/vespalib/src/testlist.txt
+++ b/vespalib/src/testlist.txt
@@ -6,7 +6,6 @@ tests/alloc
tests/approx
tests/array
tests/arrayqueue
-tests/atomic
tests/barrier
tests/benchmark_timer
tests/box
diff --git a/vespalib/src/tests/atomic/.gitignore b/vespalib/src/tests/atomic/.gitignore
deleted file mode 100644
index 7ec00432065..00000000000
--- a/vespalib/src/tests/atomic/.gitignore
+++ /dev/null
@@ -1,6 +0,0 @@
-.depend
-Makefile
-atomic_test
-/atomic_bench
-vespalib_atomic_test_app
-vespalib_atomic_bench_app
diff --git a/vespalib/src/tests/atomic/CMakeLists.txt b/vespalib/src/tests/atomic/CMakeLists.txt
deleted file mode 100644
index b20a5891318..00000000000
--- a/vespalib/src/tests/atomic/CMakeLists.txt
+++ /dev/null
@@ -1,15 +0,0 @@
-# Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-vespa_add_executable(vespalib_atomic_test_app TEST
- SOURCES
- atomic_test.cpp
- DEPENDS
- vespalib
-)
-vespa_add_test(NAME vespalib_atomic_test_app COMMAND vespalib_atomic_test_app)
-vespa_add_executable(vespalib_atomic_bench_app
- SOURCES
- atomic_bench.cpp
- DEPENDS
- vespalib
-)
-vespa_add_test(NAME vespalib_atomic_bench_app COMMAND vespalib_atomic_bench_app BENCHMARK)
diff --git a/vespalib/src/tests/atomic/DESC b/vespalib/src/tests/atomic/DESC
deleted file mode 100644
index ec5b4379673..00000000000
--- a/vespalib/src/tests/atomic/DESC
+++ /dev/null
@@ -1 +0,0 @@
-atomic test. Take a look at atomic.cpp for details.
diff --git a/vespalib/src/tests/atomic/FILES b/vespalib/src/tests/atomic/FILES
deleted file mode 100644
index 83c6c518c67..00000000000
--- a/vespalib/src/tests/atomic/FILES
+++ /dev/null
@@ -1 +0,0 @@
-atomic.cpp
diff --git a/vespalib/src/tests/atomic/atomic_bench.cpp b/vespalib/src/tests/atomic/atomic_bench.cpp
deleted file mode 100644
index 24fe67cfb77..00000000000
--- a/vespalib/src/tests/atomic/atomic_bench.cpp
+++ /dev/null
@@ -1,105 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-
-#include <vespa/vespalib/testkit/testapp.h>
-#include <vespa/vespalib/util/atomic.h>
-#include <vespa/fastos/thread.h>
-#include <vector>
-#include <algorithm>
-#include <sstream>
-
-#include <vespa/log/log.h>
-LOG_SETUP("atomic_bench");
-
-class Test : public vespalib::TestApp
-{
-public:
- template<typename C, typename T>
- void testInc(size_t threads, size_t loops);
- int Main() override;
-};
-
-template <typename T>
-class Changer : public FastOS_Runnable
-{
-protected:
- volatile T * const _idata;
- const int _times;
-public:
- Changer(int times, T *data)
- : _idata(data), _times(times) {}
-};
-
-template <typename T>
-class Incrementer : public Changer<T>
-{
-public:
- Incrementer(int times, T *data) : Changer<T>(times, data) {}
- void Run(FastOS_ThreadInterface *, void *) override {
- using vespalib::Atomic;
- for (int i = 0; i < this->_times; ++i) {
- Atomic::postInc(this->_idata);
- }
- }
-};
-
-template <typename T>
-class IncrementerByCmpSwap : public Changer<T>
-{
-public:
- IncrementerByCmpSwap(int times, T *data) : Changer<T>(times, data) {}
- void Run(FastOS_ThreadInterface *, void *) override {
- using vespalib::Atomic;
- T oldVal(0);
- for (int i = 0; i < this->_times; ++i) {
- do {
- oldVal = *this->_idata;
- } while ( ! Atomic::cmpSwap(this->_idata, oldVal+1, oldVal));
- }
- }
-};
-
-int
-Test::Main()
-{
- TEST_INIT("atomic_bench");
- size_t concurrency(1);
- size_t numRuns(10000000ul);
- size_t benchType(0);
- if (_argc > 1) {
- benchType = strtoul(_argv[1], NULL, 0);
- if (_argc > 2) {
- numRuns = strtoul(_argv[2], NULL, 0);
- if (_argc > 3) {
- concurrency = strtoul(_argv[3], NULL, 0);
- }
- }
- }
- LOG(info, "Running test number %ld with %ld loops and concurrency of %ld", benchType, numRuns, concurrency);
- if (benchType == 1) {
- testInc<IncrementerByCmpSwap<uint64_t>, uint64_t>(concurrency, numRuns);
- } else {
- testInc<Incrementer<uint64_t>, uint64_t>(concurrency, numRuns);
- }
-
- TEST_FLUSH();
- TEST_DONE();
-}
-
-
-template<typename C, typename T>
-void
-Test::testInc(size_t numThreads, size_t loopCount)
-{
- std::vector<std::unique_ptr<C>> threads3(numThreads);
- T uintcounter = 0;
- FastOS_ThreadPool tpool3(65000, numThreads);
- for (size_t i = 0; i < numThreads; i++) {
- threads3[i] = std::make_unique<C>(loopCount, &uintcounter);
- tpool3.NewThread(threads3[i].get());
- }
- tpool3.Close();
- EXPECT_TRUE(uintcounter == numThreads * loopCount);
- TEST_FLUSH();
-}
-
-TEST_APPHOOK(Test)
diff --git a/vespalib/src/tests/atomic/atomic_test.cpp b/vespalib/src/tests/atomic/atomic_test.cpp
deleted file mode 100644
index 0cd3b9f3e98..00000000000
--- a/vespalib/src/tests/atomic/atomic_test.cpp
+++ /dev/null
@@ -1,339 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-
-#include <vespa/vespalib/testkit/testapp.h>
-#include <vespa/vespalib/util/atomic.h>
-#include <vespa/fastos/thread.h>
-#include <vector>
-#include <algorithm>
-#include <sstream>
-
-#include <vespa/log/log.h>
-LOG_SETUP("atomic_test");
-
-class Test : public vespalib::TestApp
-{
-public:
- template<typename T, typename U>
- void testAdd();
- template<typename T, typename U>
- void testAddSub();
- template<typename T>
- void testInc();
- template<typename T>
- void testDec();
- template<typename T>
- void testSemantics();
- int Main() override;
-};
-
-static const int numadders = 7;
-static const int loopcnt = 100000;
-
-int
-Test::Main()
-{
- TEST_INIT("atomic_test");
-
- testSemantics<int32_t>();
- testSemantics<int64_t>();
- testAdd<int32_t, uint32_t>();
- testAdd<int64_t, uint64_t>();
- testAddSub<int32_t, uint32_t>();
- testAddSub<int64_t, uint64_t>();
- testInc<uint32_t>();
- testInc<uint64_t>();
- testDec<uint32_t>();
- testDec<uint64_t>();
-
- TEST_FLUSH();
- TEST_DONE();
-}
-
-template<typename T>
-void
-Test::testSemantics()
-{
- using vespalib::Atomic;
- volatile T value(0);
- EXPECT_EQUAL(0, value);
- EXPECT_EQUAL(0, Atomic::postInc(&value));
- EXPECT_EQUAL(1, Atomic::postInc(&value));
- EXPECT_EQUAL(2, value);
- EXPECT_EQUAL(2, Atomic::postDec(&value));
- EXPECT_EQUAL(1, value);
- EXPECT_EQUAL(1, Atomic::postAdd(&value, 17));
- EXPECT_EQUAL(18, value);
- EXPECT_EQUAL(18, Atomic::postAdd(&value, 17));
- EXPECT_EQUAL(35, value);
- EXPECT_EQUAL(35, Atomic::postAdd(&value, -7));
- EXPECT_EQUAL(28, value);
-}
-
-class NotAtomic
-{
-public:
- static inline void add(volatile int *data, int xdelta) {
- (*data) += xdelta;
- }
- static inline void sub(volatile int *data, int xdelta) {
- (*data) -= xdelta;
- }
- static inline void add(volatile unsigned int *data, unsigned int xdelta) {
- (*data) += xdelta;
- }
- static inline void sub(volatile unsigned int *data, unsigned int xdelta) {
- (*data) -= xdelta;
- }
- static inline unsigned int postDec(volatile unsigned int *data) {
- return (*data)--;
- }
- static inline unsigned int postInc(volatile unsigned int *data) {
- return (*data)++;
- }
-};
-
-template<typename T, typename U>
-class Adder : public FastOS_Runnable
-{
-private:
- int _added;
- const T _toadd;
- const int _times;
- volatile T * const _idata;
- volatile U * const _udata;
-public:
- Adder(T toadd, int times, T *i, U *u) :
- _added(0),
- _toadd(toadd),
- _times(times),
- _idata(i),
- _udata(u)
- {}
- void Run(FastOS_ThreadInterface *, void *) override {
- using vespalib::Atomic;
- for (int i = 0; i < _times; ++i) {
- Atomic::add(_idata, _toadd);
- Atomic::add(_udata, _toadd);
- _added += _toadd;
- }
- }
- int getAdded() { return _added; }
-};
-
-
-template<typename T, typename U>
-class Subtracter : public FastOS_Runnable
-{
-private:
- int _subed;
- const T _tosub;
- const int _times;
- volatile T * const _idata;
- volatile U * const _udata;
-public:
- Subtracter(T tosub, int times, T *i, U *u) :
- _subed(0),
- _tosub(tosub),
- _times(times),
- _idata(i),
- _udata(u)
- {}
- void Run(FastOS_ThreadInterface *, void *) override {
- using vespalib::Atomic;
- for (int i = 0; i < _times; ++i) {
- Atomic::sub(_idata, _tosub);
- Atomic::sub(_udata, _tosub);
- _subed += _tosub;
- }
- }
- int getSubtracted() { return _subed; }
-};
-
-template <typename T>
-class Changer : public FastOS_Runnable
-{
-protected:
- std::vector<T> _counts;
- volatile T * const _idata;
- const int _times;
-public:
- Changer(int times, T *data)
- : _counts(), _idata(data), _times(times) {}
- const std::vector<T> & getCounts() const { return _counts; }
-};
-
-
-template <typename T>
-class Incrementer : public Changer<T>
-{
-public:
- Incrementer(int times, T *data) : Changer<T>(times, data) {}
- void Run(FastOS_ThreadInterface *, void *) override {
- using vespalib::Atomic;
- for (int i = 0; i < this->_times; ++i) {
- this->_counts.push_back(Atomic::postInc(this->_idata));
- }
- }
-};
-
-
-template <typename T>
-class Decrementer : public Changer<T>
-{
-public:
- Decrementer(int times, T *data) : Changer<T>(times, data) {}
- void Run(FastOS_ThreadInterface *, void *) override {
- using vespalib::Atomic;
- for (int i = 0; i < this->_times; ++i) {
- this->_counts.push_back(Atomic::postDec(this->_idata));
- }
- }
-};
-
-
-template<typename T, typename U>
-void
-Test::testAdd()
-{
- Adder<T, U> *threads1[numadders];
-
- T intcounter = 0;
- U uintcounter = 0;
-
- FastOS_ThreadPool tpool1(65000, numadders);
- for (int i = 0; i < numadders; i++) {
- threads1[i] = new Adder<T, U>(2+i, loopcnt, &intcounter, &uintcounter);
- tpool1.NewThread(threads1[i]);
- }
- tpool1.Close();
- T intcorrect = 0;
- U uintcorrect = 0;
- for (int i = 0; i < numadders; i++) {
- intcorrect += threads1[i]->getAdded();
- uintcorrect += threads1[i]->getAdded();
- }
- for (int i = 0; i < numadders; i++) {
- delete threads1[i];
- }
- std::ostringstream os;
- os << "intcounter = " << intcounter << ", intcorrect = " << intcorrect;
- LOG(debug, "%s", os.str().c_str());
- EXPECT_TRUE( intcounter == intcorrect);
- std::ostringstream uos;
- uos << "uintcounter = " << uintcounter << ", uintcorrect = " << uintcorrect;
- LOG(debug, "%s", uos.str().c_str());
- EXPECT_TRUE(uintcounter == uintcorrect);
-}
-
-
-template<typename T, typename U>
-void
-Test::testAddSub()
-{
- FastOS_Runnable *threads2[numadders*2];
- T intcounter = 0;
- U uintcounter = 0;
-
- FastOS_ThreadPool tpool2(65000, 2*numadders);
- for (int i = 0; i < numadders; i++) {
- threads2[i] = new Adder<T, U>(2+i, loopcnt, &intcounter, &uintcounter);
- threads2[numadders+i] = new Subtracter<T, U>(2+i, loopcnt,
- &intcounter, &uintcounter);
- }
- for (int i = 0; i < numadders*2; i++) {
- tpool2.NewThread(threads2[i]);
- }
- tpool2.Close();
-
- for (int i = 0; i < numadders*2; i++) {
- delete threads2[i];
- }
- std::ostringstream os;
- os << "intcounter = " << intcounter << ", uintcounter = " << uintcounter;
- LOG(debug, "%s", os.str().c_str());
- EXPECT_TRUE( intcounter == 0);
- EXPECT_TRUE(uintcounter == 0);
-}
-
-
-template<typename T>
-void
-Test::testInc()
-{
- Incrementer<T> *threads3[numadders];
- T uintcounter = 0;
- FastOS_ThreadPool tpool3(65000, numadders);
- for (int i = 0; i < numadders; i++) {
- threads3[i] = new Incrementer<T>(loopcnt, &uintcounter);
- tpool3.NewThread(threads3[i]);
- }
- tpool3.Close();
- std::vector<T> all;
- for (int i = 0; i < numadders; i++) {
- const std::vector<T> & cnts = threads3[i]->getCounts();
- typename std::vector<T>::const_iterator it = cnts.begin();
- while (it != cnts.end()) {
- all.push_back(*it);
- ++it;
- }
- }
- for (int i = 0; i < numadders; i++) {
- delete threads3[i];
- }
- std::sort(all.begin(), all.end());
- for (unsigned int n = 0; n < all.size(); ++n) {
- EXPECT_TRUE(all[n] == n);
- if (all[n] != n) {
- std::ostringstream os;
- os << all[n];
- LOG(info, "all[%d] = %s", n, os.str().c_str());
- break;
- }
- }
- TEST_FLUSH();
- EXPECT_TRUE(uintcounter == numadders * loopcnt);
- TEST_FLUSH();
-}
-
-template<typename T>
-void
-Test::testDec()
-{
- T uintcounter = numadders * loopcnt;
- Decrementer<T> *threads4[numadders];
- FastOS_ThreadPool tpool4(65000, numadders);
- for (int i = 0; i < numadders; i++) {
- threads4[i] = new Decrementer<T>(loopcnt, &uintcounter);
- tpool4.NewThread(threads4[i]);
- }
- tpool4.Close();
- std::vector<T> all;
- for (int i = 0; i < numadders; i++) {
- const std::vector<T> & cnts = threads4[i]->getCounts();
- typename std::vector<T>::const_iterator it = cnts.begin();
- while (it != cnts.end()) {
- all.push_back(*it);
- ++it;
- }
- }
- for (int i = 0; i < numadders; i++) {
- delete threads4[i];
- }
- std::sort(all.begin(), all.end());
- for (size_t n = 0; n < all.size(); ++n) {
- EXPECT_TRUE(all[n] == n+1);
- if (all[n] != n+1) {
- for (size_t i = n; i < std::min(n+20, all.size()); ++i) {
- std::ostringstream os;
- os << std::dec << "all[" << i << "] = " << std::hex << all[i];
- LOG(warning, "%s", os.str().c_str());
- }
- break;
- }
- }
- TEST_FLUSH();
- EXPECT_TRUE(uintcounter == 0);
-}
-
-
-TEST_APPHOOK(Test)
diff --git a/vespalib/src/tests/executor/threadstackexecutor_test.cpp b/vespalib/src/tests/executor/threadstackexecutor_test.cpp
index cfdcd8ba79d..3e092ef145f 100644
--- a/vespalib/src/tests/executor/threadstackexecutor_test.cpp
+++ b/vespalib/src/tests/executor/threadstackexecutor_test.cpp
@@ -1,10 +1,10 @@
// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
#include <vespa/vespalib/testkit/test_kit.h>
-#include <vespa/vespalib/util/atomic.h>
#include <vespa/vespalib/util/threadstackexecutor.h>
#include <vespa/vespalib/util/sync.h>
#include <vespa/vespalib/util/backtrace.h>
+#include <atomic>
using namespace vespalib;
@@ -13,24 +13,24 @@ typedef Executor::Task Task;
struct MyTask : public Executor::Task {
Gate &gate;
CountDownLatch &latch;
- static uint32_t runCnt;
- static uint32_t deleteCnt;
+ static std::atomic<uint32_t> runCnt;
+ static std::atomic<uint32_t> deleteCnt;
MyTask(Gate &g, CountDownLatch &l) : gate(g), latch(l) {}
void run() override {
- Atomic::postInc(&runCnt);
+ runCnt++;
latch.countDown();
gate.await();
}
~MyTask() {
- Atomic::postInc(&deleteCnt);
+ deleteCnt++;
}
static void resetStats() {
runCnt = 0;
deleteCnt = 0;
}
};
-uint32_t MyTask::runCnt = 0;
-uint32_t MyTask::deleteCnt = 0;
+std::atomic<uint32_t> MyTask::runCnt(0);
+std::atomic<uint32_t> MyTask::deleteCnt(0);
struct MyState {
Gate gate; // to block workers
diff --git a/vespalib/src/tests/weakref/.gitignore b/vespalib/src/tests/weakref/.gitignore
deleted file mode 100644
index 8ef27437213..00000000000
--- a/vespalib/src/tests/weakref/.gitignore
+++ /dev/null
@@ -1,4 +0,0 @@
-.depend
-Makefile
-weakref_test
-vespalib_weakref_test_app
diff --git a/vespalib/src/tests/weakref/CMakeLists.txt b/vespalib/src/tests/weakref/CMakeLists.txt
deleted file mode 100644
index 5fea9d2299a..00000000000
--- a/vespalib/src/tests/weakref/CMakeLists.txt
+++ /dev/null
@@ -1,8 +0,0 @@
-# Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-vespa_add_executable(vespalib_weakref_test_app TEST
- SOURCES
- weakref_test.cpp
- DEPENDS
- vespalib
-)
-vespa_add_test(NAME vespalib_weakref_test_app COMMAND vespalib_weakref_test_app)
diff --git a/vespalib/src/tests/weakref/DESC b/vespalib/src/tests/weakref/DESC
deleted file mode 100644
index d2a0b5757a6..00000000000
--- a/vespalib/src/tests/weakref/DESC
+++ /dev/null
@@ -1 +0,0 @@
-Unit test for the WeakRef class.
diff --git a/vespalib/src/tests/weakref/FILES b/vespalib/src/tests/weakref/FILES
deleted file mode 100644
index 82209bcb6ae..00000000000
--- a/vespalib/src/tests/weakref/FILES
+++ /dev/null
@@ -1 +0,0 @@
-weakref.cpp
diff --git a/vespalib/src/tests/weakref/weakref_test.cpp b/vespalib/src/tests/weakref/weakref_test.cpp
deleted file mode 100644
index bf85edbc15f..00000000000
--- a/vespalib/src/tests/weakref/weakref_test.cpp
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-
-#include <vespa/vespalib/util/weakref.h>
-#include <vespa/vespalib/testkit/testapp.h>
-
-using vespalib::WeakRef;
-
-class Test : public vespalib::TestApp
-{
-public:
- int getFive() { return 5; }
- void testSimple();
- int Main() override;
-};
-
-
-void
-Test::testSimple()
-{
- WeakRef<Test>::Owner owner(this);
- WeakRef<Test> ref(owner);
- {
- WeakRef<Test>::Usage use(ref);
- ASSERT_TRUE(use.valid());
- EXPECT_TRUE(use->getFive() == 5);
- }
- owner.clear();
- {
- WeakRef<Test>::Usage use(ref);
- EXPECT_TRUE(!use.valid());
- }
-}
-
-
-int
-Test::Main()
-{
- TEST_INIT("weakref_test");
- testSimple();
- TEST_DONE();
-}
-
-TEST_APPHOOK(Test)
diff --git a/vespalib/src/vespa/vespalib/util/CMakeLists.txt b/vespalib/src/vespa/vespalib/util/CMakeLists.txt
index 7f42385b1fc..310e1dde68d 100644
--- a/vespalib/src/vespa/vespalib/util/CMakeLists.txt
+++ b/vespalib/src/vespa/vespalib/util/CMakeLists.txt
@@ -6,7 +6,6 @@ vespa_add_library(vespalib_vespalib_util OBJECT
alloc.cpp
approx.cpp
array.cpp
- atomic.cpp
backtrace.cpp
barrier.cpp
benchmark_timer.cpp
diff --git a/vespalib/src/vespa/vespalib/util/atomic.cpp b/vespalib/src/vespa/vespalib/util/atomic.cpp
deleted file mode 100644
index 8bf245fcc72..00000000000
--- a/vespalib/src/vespa/vespalib/util/atomic.cpp
+++ /dev/null
@@ -1,221 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-
-#include "atomic.h"
-
-namespace vespalib {
-
-// here are 5 operation, on unsigned 32-bit integers:
-/**
- * @fn void Atomic::add(volatile uint32_t *data, uint32_t xdelta)
- * @brief perform atomic add instruction
- *
- * Atomically perform { *data += xdelta }
- * @param data pointer to the integer the add should be performed on
- * @param xdelta the delta to add
- **/
-/**
- * @fn void Atomic::sub(volatile uint32_t *data, uint32_t xdelta)
- * @brief perform atomic substract instruction
- *
- * Atomically perform { *data -= xdelta }
- * @param data pointer to the integer the subtract should be performed on
- * @param xdelta the delta to subtract
- **/
-/**
- * @fn uint32_t Atomic::postDec(volatile uint32_t *data)
- * @brief perform atomic post-decrement
- *
- * Atomically perform { (*data)-- }
- * @param data pointer to the integer the decrement should be performed on
- **/
-/**
- * @fn uint32_t Atomic::postInc(volatile uint32_t *data)
- * @brief perform atomic post-increment
- *
- * Atomically perform { (*data)++ }
- * @param data pointer to the integer the increment should be performed on
- **/
-/**
- * @fn bool Atomic::cmpSwap(volatile uint32_t * dest, uint32_t newVal, uint32_t oldVal)
- * @brief atomic compare and set
- *
- * Compares the current contents of the destination with oldVal; if they are
- * equal, change destination to newVal.
- * See http://en.wikipedia.org/wiki/Compare-and-swap for more details.
- * @param dest pointer to memory that shall be compared and set
- * @param newVal new value to store in dest
- * @param oldVal expected old value in dest
- * @return true if the swap was performed, false if the destination data had changed
- **/
-
-
-// the rest is variants with slightly different argument types
-
-// signed 32-bit:
-
-/**
- * @fn void Atomic::add(volatile int32_t *data, int32_t xdelta)
- * @brief perform atomic add instruction
- *
- * Atomically perform { *data += xdelta }
- * @param data pointer to the integer the add should be performed on
- * @param xdelta the delta to add
- **/
-/**
- * @fn void Atomic::sub(volatile int32_t *data, int32_t xdelta)
- * @brief perform atomic substract instruction
- *
- * Atomically perform { *data -= xdelta }
- * @param data pointer to the integer the subtract should be performed on
- * @param xdelta the delta to subtract
- **/
-/**
- * @fn int32_t Atomic::postDec(volatile int32_t *data)
- * @brief perform atomic post-decrement
- *
- * Atomically perform { (*data)-- }
- * @param data pointer to the integer the decrement should be performed on
- **/
-/**
- * @fn int32_t Atomic::postInc(volatile int32_t *data)
- * @brief perform atomic post-increment
- *
- * Atomically perform { (*data)++ }
- * @param data pointer to the integer the increment should be performed on
- **/
-/**
- * @fn bool Atomic::cmpSwap(volatile int32_t * dest, int32_t newVal, int32_t oldVal)
- * @brief atomic compare and set
- * @param dest pointer to memory that shall be compared and set
- * @param newVal new value to store in dest
- * @param oldVal expected old value in dest
- * @return true if the swap was performed, false if the destination data had changed
- **/
-
-// unsigned 64-bit:
-
-/**
- * @fn void Atomic::add(volatile uint64_t *data, uint64_t xdelta)
- * @brief perform atomic add instruction
- *
- * Atomically perform { *data += xdelta }
- * @param data pointer to the integer the add should be performed on
- * @param xdelta the delta to add
- **/
-/**
- * @fn void Atomic::sub(volatile uint64_t *data, uint64_t xdelta)
- * @brief perform atomic substract instruction
- *
- * Atomically perform { *data -= xdelta }
- * @param data pointer to the integer the subtract should be performed on
- * @param xdelta the delta to subtract
- **/
-/**
- * @fn uint64_t Atomic::postInc(volatile uint64_t *data)
- * @brief perform atomic post-increment
- *
- * Atomically perform { (*data)++ }
- * @param data pointer to the integer the increment should be performed on
- * @return old value of memory location
- **/
-/**
- * @fn uint64_t Atomic::postDec(volatile uint64_t *data)
- * @brief perform atomic post-decrement
- *
- * Atomically perform { (*data)-- }
- * @param data pointer to the integer the decrement should be performed on
- * @return old value of memory location
- **/
-/**
- * @fn bool Atomic::cmpSwap(volatile uint64_t * dest, uint64_t newVal, uint64_t oldVal)
- * @brief atomic compare and set
- * @param dest pointer to memory that shall be compared and set
- * @param newVal new value to store in dest
- * @param oldVal expected old value in dest
- * @return true if the swap was performed, false if the destination data had changed
- **/
-
-// signed 64-bit:
-
-/**
- * @fn void Atomic::add(volatile int64_t *data, int64_t xdelta)
- * @brief perform atomic add instruction
- *
- * Atomically perform { *data += xdelta }
- * @param data pointer to the integer the add should be performed on
- * @param xdelta the delta to add
- **/
-/**
- * @fn void Atomic::sub(volatile int64_t *data, int64_t xdelta)
- * @brief perform atomic substract instruction
- *
- * Atomically perform { *data -= xdelta }
- * @param data pointer to the integer the subtract should be performed on
- * @param xdelta the delta to subtract
- **/
-/**
- * @fn int64_t Atomic::postInc(volatile int64_t *data)
- * @brief perform atomic post-increment
- *
- * Atomically perform { (*data)++ }
- * @param data pointer to the integer the increment should be performed on
- * @return old value of memory location
- **/
-/**
- * @fn int64_t Atomic::postDec(volatile int64_t *data)
- * @brief perform atomic post-decrement
- *
- * Atomically perform { (*data)-- }
- * @param data pointer to the integer the decrement should be performed on
- * @return old value of memory location
- **/
-/**
- * @fn bool Atomic::cmpSwap(volatile int64_t * dest, int64_t newVal, int64_t oldVal)
- * @brief atomic compare and set
- * @param dest pointer to memory that shall be compared and set
- * @param newVal new value to store in dest
- * @param oldVal expected old value in dest
- * @return true if the swap was performed, false if the destination data had changed
- **/
-
-
-
-
-
-// signed 128-bit:
-
-/**
- * @fn bool Atomic::cmpSwap(volatile long long * dest, long long newVal, long long oldVal)
- * @brief atomic compare and set
- * @param dest pointer to memory that shall be compared and set
- * @param newVal new value to store in dest
- * @param oldVal expected old value in dest
- * @return true if the swap was performed, false if the destination data had changed
- **/
-
-// pointer plus tag:
-/**
- * @fn bool Atomic::cmpSwap(volatile TaggedPtr * dest, TaggedPtr newVal, TaggedPtr oldVal)
- * @brief atomic compare and set
- *
- * Compares the current contents of the destination with oldVal; if they are
- * equal, change destination to newVal. Note that the entire TaggedPtr struct
- * (pointer plus tag) is compared and set in one atomic opertion.
- * See http://en.wikipedia.org/wiki/Compare-and-swap for more details.
- *
- * @param dest pointer to memory that shall be compared and set
- * @param newVal new value to store in dest
- * @param oldVal expected old value in dest
- * @return true if the swap was performed, false if the destination data had changed
- **/
-/**
- * @fn bool Atomic::cmpSwap(volatile unsigned long long * dest, unsigned long long newVal, unsigned long long oldVal)
- * @brief atomic compare and set
- * @param dest pointer to memory that shall be compared and set
- * @param newVal new value to store in dest
- * @param oldVal expected old value in dest
- * @return true if the swap was performed, false if the destination data had changed
- **/
-
-
-} // end namespace
diff --git a/vespalib/src/vespa/vespalib/util/atomic.h b/vespalib/src/vespa/vespalib/util/atomic.h
deleted file mode 100644
index 5a89b41d274..00000000000
--- a/vespalib/src/vespa/vespalib/util/atomic.h
+++ /dev/null
@@ -1,468 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-// Copyright (C) 2003 Fast Search & Transfer ASA
-// Copyright (C) 2003 Overture Services Norway AS
-
-#pragma once
-
-#include <sys/types.h>
-#include <stdint.h>
-
-namespace vespalib {
-
-/**
- * @brief Atomic instructions class
- *
- * To avoid mutexes around simple counters, use these functions.
- * Currently only implemented for GCC on i386 and x86_64 platforms.
- * To check if instructions are available, test the feature macro
- * HAVE_VESPALIB_ATOMIC with \#ifdef.
- **/
-class Atomic
-{
-public:
- /**
- * @brief Pointer and tag - use instead of bare pointer for cmpSwap()
- *
- * When making a lock-free data structure by using cmpSwap
- * on pointers, you'll often run into the "ABA problem", see
- * http://en.wikipedia.org/wiki/ABA_problem for details.
- * The TaggedPtr makes it easy to do the woraround with tag bits,
- * but requires the double-word compare-and-swap instruction.
- * Very early Amd K7/8 CPUs are lacking this and will fail (Illegal Instruction).
- **/
- struct TaggedPtr
- {
- TaggedPtr() : _ptr(nullptr), _tag(0) { }
- TaggedPtr(void * h, size_t t) : _ptr(h), _tag(t) { }
- TaggedPtr(const TaggedPtr & h) : _ptr(h._ptr), _tag(h._tag) { }
- TaggedPtr & operator = (const TaggedPtr & h) { if (this != &h) {_ptr = h._ptr; _tag = h._tag; }; return *this; }
-
- void * _ptr;
- size_t _tag;
- };
- static inline bool cmpSwap(volatile TaggedPtr * dest, TaggedPtr newVal, TaggedPtr oldVal);
-
- static inline void add(volatile uint32_t *data, uint32_t xdelta);
- static inline void sub(volatile uint32_t *data, uint32_t xdelta);
- static inline uint32_t postInc(volatile uint32_t *data);
- static inline uint32_t postDec(volatile uint32_t *data);
- static inline bool cmpSwap(volatile uint32_t * dest, uint32_t newVal, uint32_t oldVal);
-
- static inline int32_t postAdd(volatile int32_t *data, int32_t xdelta);
- static inline void add(volatile int32_t *data, int32_t xdelta);
- static inline void sub(volatile int32_t *data, int32_t xdelta);
- static inline int32_t postInc(volatile int32_t *data);
- static inline int32_t postDec(volatile int32_t *data);
- static inline bool cmpSwap(volatile int32_t * dest, int32_t newVal, int32_t oldVal);
-
- static inline void add(volatile uint64_t *data, uint64_t xdelta);
- static inline void sub(volatile uint64_t *data, uint64_t xdelta);
- static inline uint64_t postInc(volatile uint64_t *data);
- static inline uint64_t postDec(volatile uint64_t *data);
- static inline bool cmpSwap(volatile uint64_t * dest, uint64_t newVal, uint64_t oldVal);
-
- static inline int64_t postAdd(volatile int64_t *data, int64_t xdelta);
- static inline void add(volatile int64_t *data, int64_t xdelta);
- static inline void sub(volatile int64_t *data, int64_t xdelta);
- static inline int64_t postInc(volatile int64_t *data);
- static inline int64_t postDec(volatile int64_t *data);
- static inline bool cmpSwap(volatile int64_t * dest, int64_t newVal, int64_t oldVal);
-
-#if defined(__x86_64__)
- static inline bool cmpSwap(volatile long long * dest, long long newVal, long long oldVal);
- static inline bool cmpSwap(volatile unsigned long long * dest, unsigned long long newVal, unsigned long long oldVal);
-#endif
-};
-
-#if defined(__x86_64__)
- #define VESPALIB_ATOMIC_TAGGEDPTR_ALIGNMENT __attribute__ ((aligned (16)))
-#else
- #error "VESPALIB_ATOMIC_TAGGEDPTR_ALIGNMENT can not be defined."
-#endif
-
-/**
- * @fn void Atomic::add(volatile int32_t *data, int32_t xdelta)
- * @brief perform atomic add instruction
- *
- * Atomically perform { *data += xdelta }
- * @param data pointer to the integer the add should be performed on
- * @param xdelta the delta to add
- **/
-
-/**
- * @fn void Atomic::sub(volatile int32_t *data, int32_t xdelta)
- * @brief perform atomic substract instruction
- *
- * Atomically perform { *data -= xdelta }
- * @param data pointer to the integer the subtract should be performed on
- * @param xdelta the delta to subtract
- **/
-
-/**
- * @fn void Atomic::add(volatile uint32_t *data, uint32_t xdelta)
- * @brief perform atomic add instruction
- *
- * Atomically perform { *data += xdelta }
- * @param data pointer to the integer the add should be performed on
- * @param xdelta the delta to add
- **/
-
-/**
- * @fn void Atomic::sub(volatile uint32_t *data, uint32_t xdelta)
- * @brief perform atomic substract instruction
- *
- * Atomically perform { *data -= xdelta }
- * @param data pointer to the integer the subtract should be performed on
- * @param xdelta the delta to subtract
- **/
-
-
-/**
- * @fn uint32_t Atomic::postDec(volatile uint32_t *data)
- * @brief perform atomic post-decrement
- *
- * Atomically perform { (*data)-- }
- * @param data pointer to the integer the decrement should be performed on
- **/
-
-/**
- * @fn uint32_t Atomic::postInc(volatile uint32_t *data)
- * @brief perform atomic post-increment
- *
- * Atomically perform { (*data)++ }
- * @param data pointer to the integer the increment should be performed on
- **/
-
-#if defined(__x86_64__)
-
-#define HAVE_VESPALIB_ATOMIC
-
-inline int32_t
-Atomic::postAdd(volatile int32_t *data, int32_t xdelta)
-{
- __asm__("lock ; xaddl %0,%1"
- : "+r" (xdelta),
- "+m" (*data)
- : : "memory");
- return xdelta;
-}
-
-inline void
-Atomic::add(volatile int32_t *data, int32_t xdelta)
-{
- __asm__("lock ; addl %1,%0"
- : "=m" (*data)
- : "ir" (xdelta), "m" (*data));
-}
-
-inline void
-Atomic::add(volatile uint32_t *data, uint32_t xdelta)
-{
- __asm__("lock ; addl %1,%0"
- : "=m" (*data)
- : "ir" (xdelta), "m" (*data));
-}
-
-inline void
-Atomic::sub(volatile int32_t *data, int32_t xdelta)
-{
- __asm__("lock ; subl %1,%0"
- : "=m" (*data)
- : "ir" (xdelta), "m" (*data));
-}
-
-inline void
-Atomic::sub(volatile uint32_t *data, uint32_t xdelta)
-{
- __asm__("lock ; subl %1,%0"
- : "=m" (*data)
- : "ir" (xdelta), "m" (*data));
-}
-
-
-inline int
-Atomic::postDec(volatile int32_t *data)
-{
- int32_t result;
-
- __asm__("lock ; xaddl %0, %1"
- : "=r" (result), "=m" (*data) : "0" (-1), "m" (*data));
- return result;
-}
-
-inline uint32_t
-Atomic::postDec(volatile uint32_t *data)
-{
- int32_t result;
-
- __asm__("lock ; xaddl %0, %1"
- : "=r" (result), "=m" (*data) : "0" (-1), "m" (*data));
- return result;
-}
-
-inline int
-Atomic::postInc(volatile int32_t *data)
-{
- int32_t result;
-
- __asm__("lock ; xaddl %0, %1"
- : "=r" (result), "=m" (*data) : "0" (1), "m" (*data));
- return result;
-}
-
-inline uint32_t
-Atomic::postInc(volatile uint32_t *data)
-{
- int32_t result;
-
- __asm__("lock ; xaddl %0, %1"
- : "=r" (result), "=m" (*data) : "0" (1), "m" (*data));
- return result;
-}
-
-inline bool
-Atomic::cmpSwap(volatile int32_t * dest, int32_t newVal, int32_t oldVal)
-{
- char result;
- __asm__ __volatile__("lock; cmpxchgl %2, %0;"
- "setz %1"
- : "+m"(*dest), "=q"(result)
- : "r" (newVal), "a"(oldVal) : "memory");
- return result;
-}
-
-inline bool
-Atomic::cmpSwap(volatile uint32_t * dest, uint32_t newVal, uint32_t oldVal)
-{
- char result;
- __asm__ __volatile__("lock; cmpxchgl %2, %0;"
- "setz %1"
- : "+m"(*dest), "=q"(result)
- : "r" (newVal), "a"(oldVal) : "memory");
- return result;
-}
-
-inline int64_t
-Atomic::postAdd(volatile int64_t *data, int64_t xdelta)
-{
- __asm__("lock ; xaddq %0,%1"
- : "+r" (xdelta),
- "+m" (*data)
- : : "memory");
- return xdelta;
-}
-
-inline void
-Atomic::add(volatile int64_t *data, int64_t xdelta)
-{
- __asm__("lock ; addq %1,%0"
- : "=m" (*data)
- : "ir" (xdelta), "m" (*data));
-}
-
-inline void
-Atomic::add(volatile uint64_t *data, uint64_t xdelta)
-{
- __asm__("lock ; addq %1,%0"
- : "=m" (*data)
- : "ir" (xdelta), "m" (*data));
-}
-
-inline void
-Atomic::sub(volatile int64_t *data, int64_t xdelta)
-{
- __asm__("lock ; subq %1,%0"
- : "=m" (*data)
- : "ir" (xdelta), "m" (*data));
-}
-
-inline void
-Atomic::sub(volatile uint64_t *data, uint64_t xdelta)
-{
- __asm__("lock ; subq %1,%0"
- : "=m" (*data)
- : "ir" (xdelta), "m" (*data));
-}
-
-
-inline int64_t
-Atomic::postDec(volatile int64_t *data)
-{
- int64_t result;
-
- __asm__("lock ; xaddq %0, %1"
- : "=r" (result), "=m" (*data) : "0" (int64_t(-1)), "m" (*data));
- return result;
-}
-
-inline uint64_t
-Atomic::postDec(volatile uint64_t *data)
-{
- uint64_t result;
-
-#if defined(__i386__)
- do {
- result = *data;
- } while(!cmpSwap(data, result-1, result));
-#else
- __asm__("lock ; xaddq %0, %1"
- : "=r" (result), "=m" (*data) : "0" (uint64_t(-1)), "m" (*data));
-#endif
- return result;
-}
-
-inline int64_t
-Atomic::postInc(volatile int64_t *data)
-{
- int64_t result;
-
-#if defined(__i386__)
- do {
- result = *data;
- } while(!cmpSwap(data, result+1, result));
-#else
- __asm__("lock ; xaddq %0, %1"
- : "=r" (result), "=m" (*data) : "0" (1), "m" (*data));
-#endif
- return result;
-}
-
-inline uint64_t
-Atomic::postInc(volatile uint64_t *data)
-{
- uint64_t result;
-
-#if defined(__i386__)
- do {
- result = *data;
- } while(!cmpSwap(data, result+1, result));
-#else
- __asm__("lock ; xaddq %0, %1"
- : "=r" (result), "=m" (*data) : "0" (1), "m" (*data));
-#endif
- return result;
-}
-
-inline bool
-Atomic::cmpSwap(volatile uint64_t * dest, uint64_t newVal, uint64_t oldVal) {
- bool result;
- __asm__ __volatile__("lock; cmpxchgq %3, %0;"
- "setz %1"
- : "+m"(*dest), "=q"(result), "+a"(oldVal)
- : "r" (newVal)
- : "memory", "cc");
- return result;
-}
-
-inline bool
-Atomic::cmpSwap(volatile int64_t * dest, int64_t newVal, int64_t oldVal)
-{
- return cmpSwap((volatile uint64_t *) dest, newVal, oldVal);
-}
-
-#if defined(__x86_64__)
-inline bool
-Atomic::cmpSwap(volatile unsigned long long * dest, unsigned long long newVal, unsigned long long oldVal)
-{
- char result;
- unsigned long long res;
- union pair {
- uint64_t v64[2];
- unsigned long long v128;
- };
- pair nv;
- nv.v128 = newVal;
- __asm__ volatile (
- "lock ;"
- "cmpxchg16b %6;"
- "setz %2;"
- : "=A" (res),
- "=m" (*dest),
- "=q" (result)
- : "0" (oldVal),
- "b" (nv.v64[0]),
- "c" (nv.v64[1]),
- "m" (*dest)
- : "memory"
- );
- return result;
-}
-
-inline bool
-Atomic::cmpSwap(volatile long long * dest, long long newVal, long long oldVal)
-{
- return cmpSwap((volatile unsigned long long *) dest, newVal, oldVal);
-}
-
-#endif
-
-inline bool
-Atomic::cmpSwap(volatile TaggedPtr * dest, TaggedPtr newVal, TaggedPtr oldVal)
-{
- char result;
- void * ptr;
- size_t tag;
-#if defined(__x86_64__)
- __asm__ volatile (
- "lock ;"
- "cmpxchg16b %8;"
- "setz %1;"
- : "=m" (*dest),
- "=q" (result),
- "=a" (ptr),
- "=d" (tag)
- : "a" (oldVal._ptr),
- "d" (oldVal._tag),
- "b" (newVal._ptr),
- "c" (newVal._tag),
- "m" (*dest)
- : "memory"
- );
-#else
-#ifdef __pic__
- __asm__ volatile (
- "pushl %%ebx;"
- "movl %6, %%ebx;"
- "lock ;"
- "cmpxchg8b %8;"
- "setz %1;"
- "popl %%ebx;"
- : "=m" (*dest),
- "=q" (result),
- "=a" (ptr),
- "=d" (tag)
- : "2" (oldVal._ptr),
- "3" (oldVal._tag),
- "m" (newVal._ptr),
- "c" (newVal._tag),
- "m" (*dest)
- : "memory"
- );
-#else
- __asm__ volatile (
- "lock ;"
- "cmpxchg8b %8;"
- "setz %1;"
- : "=m" (*dest),
- "=q" (result),
- "=a" (ptr),
- "=d" (tag)
- : "a" (oldVal._ptr),
- "d" (oldVal._tag),
- "b" (newVal._ptr),
- "c" (newVal._tag),
- "m" (*dest)
- : "memory"
- );
-#endif
-
-#endif
-
- return result;
-}
-#else
- #error "Atomic methods has not been defined for this platform."
-#endif // #ifdef __x86_64__
-
-} // namespace vespalib
-
diff --git a/vespalib/src/vespa/vespalib/util/overview.h b/vespalib/src/vespa/vespalib/util/overview.h
index 8c1cf2daf70..7fc48e2f19e 100644
--- a/vespalib/src/vespa/vespalib/util/overview.h
+++ b/vespalib/src/vespa/vespalib/util/overview.h
@@ -33,20 +33,17 @@
* <BR> vespalib::RWLockReader
* <BR> vespalib::RWLockWriter
*
- * Reference counting and atomic operations
+ * Reference counting
*
- * vespalib::Atomic
* <BR> vespalib::ReferenceCounter
*
* Simple smart pointers (deprecated)
*
- * \ref vespalib::SharedPtr&lt;T&gt;
* <BR> \ref vespalib::LinkedPtr&lt;T&gt;
*
* Advanced pointer utilities
*
* \ref vespalib::PtrHolder&lt;T&gt;
- * <BR> \ref vespalib::WeakRef&lt;T&gt;
*
* Simple hashmap
*
diff --git a/vespalib/src/vespa/vespalib/util/ptrholder.h b/vespalib/src/vespa/vespalib/util/ptrholder.h
index 7f2f413a00b..7a1ef8b0ccd 100644
--- a/vespalib/src/vespa/vespalib/util/ptrholder.h
+++ b/vespalib/src/vespa/vespalib/util/ptrholder.h
@@ -6,7 +6,6 @@
#include <algorithm>
#include <memory>
#include <vespa/vespalib/util/sync.h>
-#include <vespa/vespalib/util/atomic.h>
namespace vespalib {
diff --git a/vespalib/src/vespa/vespalib/util/referencecounter.h b/vespalib/src/vespa/vespalib/util/referencecounter.h
index cd704a37613..63353d51cf8 100644
--- a/vespalib/src/vespa/vespalib/util/referencecounter.h
+++ b/vespalib/src/vespa/vespalib/util/referencecounter.h
@@ -8,8 +8,8 @@
#pragma once
-#include <vespa/vespalib/util/atomic.h>
-#include <assert.h>
+#include <atomic>
+#include <cassert>
namespace vespalib
{
@@ -28,7 +28,7 @@ public:
/**
* @brief Constructor. The object will initially have 1 reference.
**/
- ReferenceCounter() : _refs(1) {};
+ ReferenceCounter() : _refs(1) {}
/**
* @brief Add an owner of this object.
@@ -36,7 +36,7 @@ public:
* When the owner is finished with the
* object, call subRef().
**/
- void addRef() { vespalib::Atomic::postInc(&_refs); };
+ void addRef() { _refs.fetch_add(1); }
/**
* @brief Remove an owner of this object.
@@ -44,8 +44,7 @@ public:
* If that was the last owner, delete the object.
**/
void subRef() {
- unsigned oldVal = vespalib::Atomic::postDec(&_refs);
- if (oldVal == 1) {
+ if (_refs.fetch_sub(1) == 1) {
delete this;
}
}
@@ -56,7 +55,7 @@ protected:
**/
virtual ~ReferenceCounter() { assert (_refs == 0); };
private:
- volatile unsigned _refs;
+ std::atomic<unsigned> _refs;
};
} // namespace vespalib
diff --git a/vespalib/src/vespa/vespalib/util/weakref.h b/vespalib/src/vespa/vespalib/util/weakref.h
deleted file mode 100644
index 4bcc8a8e0fb..00000000000
--- a/vespalib/src/vespa/vespalib/util/weakref.h
+++ /dev/null
@@ -1,259 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-// Copyright (C) 2005 Overture Services Norway AS
-
-#pragma once
-
-#include <algorithm>
-#include <vespa/vespalib/util/sync.h>
-#include <vespa/vespalib/util/atomic.h>
-
-namespace vespalib {
-
-/**
- * @brief A WeakRef is a pointer to an object that may disappear
- *
- * The object pointer is owned by a WeakRef::Owner. The owner can
- * decide to remove the pointer at any time, but not while it is being
- * used. To signal that a WeakRef is being used, you need to create a
- * WeakRef::Usage. This will ensure that the pointer is not removed
- * until you are done using it.
- **/
-template <typename T>
-class WeakRef
-{
-public:
- class Usage;
- friend class WeakRef::Usage;
-private:
- struct Core {
- Monitor monitor;
- uint32_t refcnt;
- uint32_t usecnt;
- bool dead;
- T *pt;
-
- Core(T *p) : monitor("WeakRef::Core", true),
- refcnt(1), usecnt(0), dead(false), pt(p) {}
- ~Core() {
- assert(refcnt == 0);
- assert(usecnt == 0);
- assert(dead);
- assert(pt == 0);
- }
-
- Core *getRef() {
- Atomic::postInc(&refcnt);
- return this;
- }
-
- void dropRef() {
- if (Atomic::postDec(&refcnt) != 1) {
- return;
- }
- delete this;
- }
-
- Core *getUse() {
- MonitorGuard mon(monitor);
- if (dead) {
- return 0;
- }
- ++usecnt;
- return getRef();
- }
-
- void dropUse() {
- {
- MonitorGuard mon(monitor);
- --usecnt;
- if (dead && usecnt == 0) {
- mon.signal();
- }
- }
- dropRef();
- }
-
- void kill() {
- {
- MonitorGuard mon(monitor);
- dead = true;
- while (usecnt != 0) {
- mon.wait();
- }
- pt = 0;
- }
- dropRef();
- }
-
- private:
- Core(const Core &);
- Core &operator=(const Core &);
- };
-
-public:
- /**
- * @brief A WeakRef::Owner owns the object pointer used by WeakRef
- * instances.
- **/
- class Owner {
- friend class WeakRef;
-
- private:
- Core *_core;
- Owner(const Owner &);
- Owner &operator=(const Owner &);
-
- Core *getRef() const { return (_core != 0) ? _core->getRef() : 0; }
-
- public:
- /**
- * @brief Create an owner with the given pointer
- *
- * @param pt object pointer
- **/
- Owner(T *pt) : _core(new Core(pt)) {}
-
- /**
- * @brief Remove the object pointer
- *
- * This method will block until all current usage of the
- * object pointer is complete (All WeakRef::Usage instances
- * created from WeakRef instances based on this WeakRef::Owner
- * has been destructed). Any further usage of the object
- * pointer will be denied.
- **/
- void clear() {
- if (_core != 0) {
- _core->kill();
- _core = 0;
- }
- }
-
- /**
- * @brief Remove the object pointer if it is not yet removed
- *
- * Note that if you use an embedded owner to point to the
- * embedding object, you should invoke the clear method at an
- * earlier stage in the destruction process of the embedding
- * object to avoid a weak reference to a half-destructed
- * object.
- **/
- ~Owner() { clear(); }
- };
-
- /**
- * @brief A WeakRef::Usage signals that a WeakRef is in use
- **/
- class Usage {
- private:
- Core *_core;
- Usage(const Usage &);
- Usage &operator=(const Usage &);
-
- public:
- /**
- * @brief Start using the given WeakRef
- *
- * @param rhs the WeakRef you want to use
- **/
- Usage(const WeakRef &rhs) : _core(rhs.getUse()) {}
-
- /**
- * @brief Stop using the underlying WeakRef
- *
- * This will signal that the WeakRef given in the constructor
- * is no longer in use.
- **/
- ~Usage() {
- if (_core != 0) {
- _core->dropUse();
- }
- }
-
- /**
- * @brief Check if the object pointer is valid
- *
- * This method will return false if we try to use a WeakRef
- * after the WeakRef::Owner has cleared the object pointer. If
- * this method returns true, the object pointer will not
- * become invalid while this object is alive.
- *
- * @return true if the object pointer is still valid
- **/
- bool valid() const { return (_core != 0); }
-
- /**
- * @brief Access the weakly referenced object
- *
- * This is the preferred way to access the weakly referenced
- * object as it makes the usage object act as a smart pointer.
- *
- * @return object pointer
- **/
- T *operator->() const { return _core->pt; }
-
- /**
- * @brief Obtain the weakly referenced object
- *
- * @return object pointer
- **/
- T *get() const { return _core->pt; }
- };
-
-private:
- Core *_core;
-
- Core *getRef() const { return (_core != 0) ? _core->getRef() : 0; }
- Core *getUse() const { return (_core != 0) ? _core->getUse() : 0; }
-
-public:
- /**
- * @brief Create a WeakRef not pointing to anything
- **/
- WeakRef() : _core(0) {}
-
- /**
- * @brief Copy constructor
- *
- * This will result in a WeakRef pointing to the same object as
- * <i>rhs</i>
- *
- * @param rhs copy this
- **/
- WeakRef(const WeakRef &rhs) : _core(rhs.getRef()) {}
-
- /**
- * @brief Create a WeakRef based on the given WeakRef::Owner
- *
- * This WeakRef will point to the object dictated by rhs
- *
- * @param rhs pointer owner
- **/
- WeakRef(const WeakRef::Owner &rhs) : _core(rhs.getRef()) {}
-
- /**
- * @brief Assignment operator
- *
- * This is implemented as a copy-swap-delete operation.
- *
- * @return reference to this
- * @param rhs copy this
- **/
- WeakRef &operator=(const WeakRef &rhs) {
- WeakRef tmp(rhs);
- std::swap(tmp._core, _core);
- return *this;
- }
-
- /**
- * @brief Perform internal cleanup.
- **/
- ~WeakRef() {
- if (_core != 0) {
- _core->dropRef();
- }
- }
-};
-
-} // namespace vespalib
-