set(PACKAGE_NAME stress-sequential)
+add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/sequential-misc)
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/sequential-set)
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/sequential-map)
--- /dev/null
+set(PACKAGE_NAME stress-sequential-misc)
+
+set(CDSSTRESS_STACK_SOURCES
+ ../../main.cpp
+ spinlock_driver.cpp
+ deque_driver.cpp
+ seqlock_driver.cpp
+ rwlock_driver.cpp
+ mcslock_driver.cpp
+)
+
+include_directories(
+ ${CMAKE_CURRENT_SOURCE_DIR}
+)
+
+add_executable(${PACKAGE_NAME} ${CDSSTRESS_STACK_SOURCES})
+target_link_libraries(${PACKAGE_NAME} ${CDS_TEST_LIBRARIES} ${CDSSTRESS_FRAMEWORK_LIBRARY})
+
+add_test(NAME ${PACKAGE_NAME} COMMAND ${PACKAGE_NAME} WORKING_DIRECTORY ${EXECUTABLE_OUTPUT_PATH})
--- /dev/null
+#ifndef _CDS_STRESS_TEST_COMMON_H
+#define _CDS_STRESS_TEST_COMMON_H
+
+#include <cds_test/stress_test.h>
+
+typedef unsigned long long ullong;
+
+#define GetConfig(field) s_n##field = cfg.get_size_t(#field, s_n##field)
+
+
+#ifdef PERFORMANCE
+#define DEBUG(stmt)
+#else
+#define DEBUG(stmt) stmt
+#endif
+
+#endif
--- /dev/null
+#include "common.h"
+#include <cds/container/chase-lev-deque.h>
+#include <cds_test/stress_test.h>
+#include <cstdlib>
+#include <ctime>
+#include <iostream>
+#include <memory>
+#include <thread>
+
+using namespace std;
+
+namespace {
+
+typedef cds_others::ChaseLevDeque Deque;
+static size_t s_nDequePassCount = 1000;
+static size_t s_nDequeStealerThreadCount = 5;
+static size_t s_nDequeMainPassCount = 100000000;
+
+class ChaseLevDequeTest : public cds_test::stress_fixture {
+protected:
+ static Deque *deque;
+ static atomic_int terminate_stealer;
+ static ullong *sums;
+ static ullong *succ_counts;
+ static ullong push_sum;
+ static ullong push_count;
+
+ static void SetUpTestCase() {
+ cds_test::config const &cfg = get_config("SequentialMisc");
+ GetConfig(DequePassCount);
+ GetConfig(DequeStealerThreadCount);
+ GetConfig(DequeMainPassCount);
+ }
+
+ static void StealerThread(int index) {
+ while (!terminate_stealer.load(memory_order_relaxed)) {
+ int res = deque->steal();
+ if (res != EMPTY && res != ABORT) {
+ sums[index] += res;
+ succ_counts[index]++;
+ }
+ }
+ }
+
+ static void MainThread(int index, int push_percentage) {
+ for (ullong i = 0; i < s_nDequeMainPassCount; i++) {
+ if ((::rand() % 100) < push_percentage) {
+ int item = ::rand() % 100;
+ deque->push(item);
+ push_sum += item;
+ push_count++;
+ } else {
+ int res = deque->take();
+ if (res != EMPTY) {
+ sums[index] += res;
+ succ_counts[index]++;
+ }
+ }
+ }
+ while (true) {
+ int res = deque->take();
+ if (res != EMPTY) {
+ sums[index] += res;
+ succ_counts[index]++;
+ } else {
+ break;
+ }
+ }
+ }
+};
+
+atomic_int ChaseLevDequeTest::terminate_stealer;
+ullong *ChaseLevDequeTest::sums;
+ullong *ChaseLevDequeTest::succ_counts;
+ullong ChaseLevDequeTest::push_count;
+ullong ChaseLevDequeTest::push_sum;
+Deque *ChaseLevDequeTest::deque;
+
+TEST_F(ChaseLevDequeTest, ChaseLevDeque) {
+ deque = new Deque();
+ for (size_t i = 0; i < s_nDequePassCount; ++i) {
+ deque->push(i);
+ int res = deque->take();
+ deque->push(i);
+ res = deque->steal();
+ }
+}
+
+} // namespace
--- /dev/null
+#include "common.h"
+#include <atomic>
+#include <cds/gc/dhp.h>
+#include <cds/gc/hp.h>
+#include <cds/sync/mcs-lock.h>
+#include <cds_test/stress_test.h>
+#include <iostream>
+#include <memory>
+#include <thread>
+
+using namespace std;
+
+namespace {
+
+static size_t s_nMCSLockThreadCount = 6;
+static size_t s_nMCSLockPassCount = 3000000;
+
+class MCSLockTest : public cds_test::stress_fixture {
+protected:
+ static ullong x;
+ static cds_others::mcs_mutex *my_mutex;
+
+ static void SetUpTestCase() {
+ cds_test::config const &cfg = get_config("SequentialMisc");
+ GetConfig(MCSLockPassCount);
+ GetConfig(MCSLockThreadCount);
+ }
+
+ static void Thread() {
+ cds_others::mcs_mutex::guard g(my_mutex);
+ my_mutex->unlock(&g);
+ for (ullong i = 0; i < s_nMCSLockPassCount; i++) {
+ my_mutex->lock(&g);
+ x++;
+ my_mutex->unlock(&g);
+ }
+ my_mutex->lock(&g);
+ }
+};
+
+ullong MCSLockTest::x;
+cds_others::mcs_mutex *MCSLockTest::my_mutex;
+
+TEST_F(MCSLockTest, MCSLock) {
+ my_mutex = new cds_others::mcs_mutex();
+ cds_others::mcs_mutex::guard g(my_mutex);
+ my_mutex->unlock(&g);
+ for (size_t i = 0; i < s_nMCSLockPassCount; i++) {
+ my_mutex->lock(&g);
+ x++;
+ my_mutex->unlock(&g);
+ }
+ my_mutex->lock(&g);
+}
+
+} // namespace
--- /dev/null
+#include "common.h"
+#include <atomic>
+#include <cds/gc/dhp.h>
+#include <cds/gc/hp.h>
+#include <cds/sync/rwlock.h>
+#include <cds_test/stress_test.h>
+#include <iostream>
+#include <memory>
+#include <thread>
+
+using namespace std;
+
+namespace {
+
+static size_t s_nRWLockThreadCount = 6;
+static size_t s_nRWLockPassCount = 200000;
+
+typedef cds_others::RWLock RWLock;
+class RWLockTest : public cds_test::stress_fixture {
+protected:
+ static size_t sum;
+ static size_t x;
+ static RWLock *rwlock;
+
+ static void SetUpTestCase() {
+ cds_test::config const &cfg = get_config("SequentialMisc");
+ GetConfig(RWLockThreadCount);
+ GetConfig(RWLockPassCount);
+ }
+
+ static void ReaderWriterThread(int write_percentage) {
+ for (size_t i = 0; i < s_nRWLockPassCount; i++) {
+ if (rand(100) < write_percentage) {
+ if (rwlock->read_can_lock()) {
+ if (!rwlock->read_trylock()) {
+ rwlock->read_lock();
+ }
+ sum += x;
+ rwlock->read_unlock();
+ } else {
+ rwlock->read_lock();
+ sum += x;
+ rwlock->read_unlock();
+ }
+ } else {
+ if (rwlock->write_can_lock()) {
+ if (!rwlock->write_trylock()) {
+ rwlock->write_lock();
+ }
+ x++;
+ rwlock->write_unlock();
+ } else {
+ rwlock->write_lock();
+ x++;
+ rwlock->write_unlock();
+ }
+ }
+ }
+ }
+};
+
+size_t RWLockTest::x;
+size_t RWLockTest::sum;
+RWLock *RWLockTest::rwlock;
+
+TEST_F(RWLockTest, ReadWriteLock) {
+ rwlock = new RWLock();
+ for (int write_percentage = 5; write_percentage < 40; write_percentage += 5) {
+ ReaderWriterThread(write_percentage);
+ }
+}
+
+} // namespace
--- /dev/null
+#include "common.h"
+#include <atomic>
+#include <cds/gc/dhp.h>
+#include <cds/gc/hp.h>
+#include <cds/sync/seqlock.h>
+#include <cds_test/stress_test.h>
+#include <iostream>
+#include <memory>
+#include <thread>
+
+using namespace std;
+
+namespace {
+
+typedef cds_others::SeqLock SeqLock;
+
+static size_t s_nSeqLockReaderWriterThreadCount = 6;
+static size_t s_nSeqLockPassCount = 2000000;
+
+class SeqLockTest : public cds_test::stress_fixture {
+protected:
+ static size_t sum;
+ static SeqLock *seqlock;
+
+ static void SetUpTestCase() {
+ cds_test::config const &cfg = get_config("SequentialMisc");
+ GetConfig(SeqLockReaderWriterThreadCount);
+ GetConfig(SeqLockPassCount);
+ }
+
+ static void ReaderWriterThread(int write_percentage) {
+ for (size_t i = 0; i < s_nSeqLockPassCount; i++) {
+ if (rand(100) < write_percentage) {
+ sum += seqlock->read();
+ } else {
+ seqlock->write(rand(10));
+ }
+ }
+ }
+};
+
+size_t SeqLockTest::sum;
+SeqLock *SeqLockTest::seqlock;
+
+TEST_F(SeqLockTest, SeqLock) {
+ seqlock = new SeqLock();
+ for (int write_percentage = 5; write_percentage < 50; write_percentage += 5) {
+ ReaderWriterThread(write_percentage);
+ }
+}
+
+} // namespace
--- /dev/null
+#include "common.h"
+#include <atomic>
+#include <cds/gc/dhp.h>
+#include <cds/gc/hp.h>
+#include <cds/sync/spinlock.h>
+#include <cds/sync/ticket_lock.h>
+#include <cds_test/stress_test.h>
+#include <iostream>
+#include <iostream>
+#include <memory>
+#include <thread>
+
+using namespace std;
+
+namespace {
+
+typedef cds_others::TicketLock TicketLock;
+typedef cds::sync::spin SpinLock;
+typedef cds::sync::reentrant_spin32 Reentrant32;
+typedef cds::sync::reentrant_spin64 Reentrant64;
+static size_t s_nSpinLockThreadCount = 6;
+static size_t s_nSpinLockPassCount = 2500000000;
+static size_t s_nTicketLockPassCount = 4000000;
+
+#define TASK(lock_type, lock_ptr, pass_cnt) \
+ static void Thread##lock_type() { \
+ for (size_t i = 0; i < pass_cnt; i++) { \
+ lock_ptr->lock(); \
+ x++; \
+ lock_ptr->unlock(); \
+ } \
+ }
+
+#define LOCK_TEST(lock_type, lock_ptr, pass_cnt) \
+ TEST_F(SpinLockTest, lock_type) { \
+ lock_ptr = new lock_type(); \
+ x = 0; \
+ Thread##lock_type(); \
+ }
+
+class SpinLockTest : public cds_test::stress_fixture {
+protected:
+ static size_t x;
+ static TicketLock *ticket_mutex;
+ static SpinLock *spin_mutex;
+ static Reentrant32 *reentrant_mutex32;
+ static Reentrant64 *reentrant_mutex64;
+
+ static void SetUpTestCase() {
+ cds_test::config const &cfg = get_config("SequentialMisc");
+ GetConfig(SpinLockThreadCount);
+ GetConfig(SpinLockPassCount);
+ GetConfig(TicketLockPassCount);
+ }
+
+ TASK(TicketLock, ticket_mutex, s_nTicketLockPassCount)
+ TASK(SpinLock, spin_mutex, s_nSpinLockPassCount)
+ TASK(Reentrant32, reentrant_mutex32, s_nSpinLockPassCount)
+ TASK(Reentrant64, reentrant_mutex64, s_nSpinLockPassCount)
+};
+
+size_t SpinLockTest::x;
+TicketLock *SpinLockTest::ticket_mutex;
+SpinLock *SpinLockTest::spin_mutex;
+Reentrant32 *SpinLockTest::reentrant_mutex32;
+Reentrant64 *SpinLockTest::reentrant_mutex64;
+
+LOCK_TEST(TicketLock, ticket_mutex, s_nTicketLockPassCount)
+LOCK_TEST(SpinLock, spin_mutex, s_nSpinLockPassCount)
+LOCK_TEST(Reentrant32, reentrant_mutex32, s_nSpinLockPassCount)
+LOCK_TEST(Reentrant64, reentrant_mutex64, s_nSpinLockPassCount)
+
+} // namespace