cmake_minimum_required(VERSION 2.8.12)
+#SET(CMAKE_C_COMPILER clang-native)
+#SET(CMAKE_CXX_COMPILER clang++-native)
+SET(CMAKE_C_COMPILER clang-cross)
+SET(CMAKE_CXX_COMPILER clang++-cross)
+
cmake_policy(SET CMP0016 NEW)
if(POLICY CMP0042)
cmake_policy(SET CMP0042 NEW)
message("Boost: Using CMake-fied boost")
endif()
+
if(CMAKE_SYSTEM_NAME STREQUAL "AIX")
set(CMAKE_CXX_ARCHIVE_CREATE "<CMAKE_AR> -q -c ${CMAKE_STATIC_LINKER_FLAGS} -o <TARGET> <OBJECTS>")
endif()
install(EXPORT LibCDSConfig FILE LibCDSConfig.cmake NAMESPACE LibCDS:: DESTINATION lib/cmake/LibCDS)
install(DIRECTORY ${PROJECT_SOURCE_DIR}/cds DESTINATION include COMPONENT ${HEADERS_COMPONENT})
+add_subdirectory(${PROJECT_SOURCE_DIR}/benchmark-drivers)
if(WITH_TESTS)
enable_testing()
add_subdirectory(${PROJECT_SOURCE_DIR}/test)
--- /dev/null
+set(PACKAGE_NAME test-drivers)
+
+set(CDS_LIBRARIES
+ ${CDS_SHARED_LIBRARY}
+ ${Boost_THREAD_LIBRARY}
+ ${Boost_SYSTEM_LIBRARY}
+ ${CMAKE_THREAD_LIBS_INIT}
+ ${EXTERNAL_SYSTEM_LIBS}
+)
+
+set(TEST_DRIVERS_SOURCES
+ test.cc
+)
+
+include_directories(
+ ${CMAKE_CURRENT_SOURCE_DIR}
+)
+
+add_executable(rwqueue_driver rwqueue_driver.cpp)
+target_link_libraries(rwqueue_driver ${CDS_LIBRARIES})
+
+add_executable(spinlock_driver spinlock_driver.cpp)
+target_link_libraries(spinlock_driver ${CDS_LIBRARIES})
+
+add_executable(treiber_stack_driver treiber_stack_driver.cpp)
+target_link_libraries(treiber_stack_driver ${CDS_LIBRARIES})
+
+#add_executable(fcstack_driver fcstack_driver.cpp)
+#target_link_libraries(fcstack_driver ${CDS_LIBRARIES})
+
+# Not compiling
+#add_executable(cuckoo_map_driver cuckoo_map_driver.cpp)
+#target_link_libraries(cuckoo_map_driver ${CDS_LIBRARIES})
+
+add_executable(msqueue_driver msqueue_driver.cpp)
+target_link_libraries(msqueue_driver ${CDS_LIBRARIES})
+
+add_executable(moirqueue_driver moirqueue_driver.cpp)
+target_link_libraries(moirqueue_driver ${CDS_LIBRARIES})
+
+add_executable(basketqueue_driver basketqueue_driver.cpp)
+target_link_libraries(basketqueue_driver ${CDS_LIBRARIES})
+
+add_executable(optimisticqueue_driver optimisticqueue_driver.cpp)
+target_link_libraries(optimisticqueue_driver ${CDS_LIBRARIES})
+
+add_executable(segmentedqueue_driver segmentedqueue_driver.cpp)
+target_link_libraries(segmentedqueue_driver ${CDS_LIBRARIES})
+
+add_executable(vyukovqueue_driver vyukovqueue_driver.cpp)
+target_link_libraries(vyukovqueue_driver ${CDS_LIBRARIES})
+
+add_executable(fcqueue_driver fcqueue_driver.cpp)
+target_link_libraries(fcqueue_driver ${CDS_LIBRARIES})
+
+add_executable(fcdeque_driver fcdeque_driver.cpp)
+target_link_libraries(fcdeque_driver ${CDS_LIBRARIES})
--- /dev/null
+#include <cds/gc/dhp.h>
+#include <cds/gc/hp.h>
+#include <cds/init.h>
+#include <cds/intrusive/basket_queue.h>
+#include <iostream>
+#include <string>
+
+using namespace std;
+
+namespace ci = cds::intrusive;
+typedef cds::gc::HP hp_gc;
+
+struct Foo : public ci::basket_queue::node<hp_gc> {
+ Foo(int x) : x(x) {}
+ int x;
+};
+
+// Declare traits for the queue
+struct MyTraits : public cds::intrusive::basket_queue::traits {
+ typedef cds::intrusive::basket_queue::stat<> stat;
+ typedef cds::atomicity::item_counter item_counter;
+};
+
+// At least, declare the queue type
+typedef ci::BasketQueue<hp_gc, Foo, MyTraits> MyQueue;
+
+int main() {
+ cds::Initialize();
+
+ {
+ // Initialize Hazard Pointer singleton
+ cds::gc::HP hpGC(128, 8, 128);
+ // If main thread uses lock-free containers
+ // the main thread should be attached to libcds infrastructure
+ cds::threading::Manager::attachThread();
+
+ MyQueue q;
+ Foo *f = new Foo(1);
+ Foo *res = nullptr;
+ q.enqueue(*f);
+ res = q.dequeue();
+ if (res) {
+ cout << "Dequeued " << res->x << "\n";
+ } else {
+ cout << "Dequeued none\n";
+ }
+ }
+
+ cds::Terminate();
+ return 0;
+}
--- /dev/null
+#include <cds/container/cuckoo_map.h>
+#include <iostream>
+#include <string>
+
+using namespace std;
+
+int main() {
+ string msg = "Hello world\n";
+ cout << msg;
+ cds::container::CuckooMap<int, int> map;
+ return 0;
+}
--- /dev/null
+#include <cds/gc/dhp.h>
+#include <cds/gc/hp.h>
+#include <cds/init.h>
+#include <cds/container/fcdeque.h>
+#include <cds/intrusive/fcqueue.h>
+#include <iostream>
+#include <string>
+
+using namespace std;
+
+namespace ci = cds::intrusive;
+namespace cc = cds::container;
+typedef cds::gc::HP hp_gc;
+
+struct Foo {
+ Foo(int x) : x(x) {}
+ int x;
+};
+
+// At least, declare the queue type
+typedef cc::FCDeque<Foo> MyDeque;
+
+int main() {
+ cds::Initialize();
+
+ {
+ // Initialize Hazard Pointer singleton
+ cds::gc::HP hpGC(128, 8, 128);
+ // If main thread uses lock-free containers
+ // the main thread should be attached to libcds infrastructure
+ cds::threading::Manager::attachThread();
+
+ MyDeque q;
+ Foo *f = new Foo(1);
+ Foo res(0);
+ q.push_front(*f);
+ bool succ = q.pop_front(res);
+ if (succ) {
+ cout << "Dequeued " << res.x << "\n";
+ } else {
+ cout << "Dequeued none\n";
+ }
+ }
+
+ cds::Terminate();
+ return 0;
+}
--- /dev/null
+#include <cds/gc/dhp.h>
+#include <cds/gc/hp.h>
+#include <cds/init.h>
+#include <cds/intrusive/fcqueue.h>
+#include <iostream>
+#include <list>
+#include <string>
+
+using namespace std;
+
+namespace ci = cds::intrusive;
+typedef cds::gc::HP hp_gc;
+
+struct Foo : boost::intrusive::list_base_hook<> {
+ Foo(int x) : x(x) {}
+ int x;
+};
+
+// At least, declare the queue type
+typedef ci::FCQueue<Foo> MyQueue;
+
+int main() {
+ cds::Initialize();
+
+ {
+ // Initialize Hazard Pointer singleton
+ cds::gc::HP hpGC(128, 8, 128);
+ // If main thread uses lock-free containers
+ // the main thread should be attached to libcds infrastructure
+ cds::threading::Manager::attachThread();
+
+ MyQueue q;
+ Foo *f = new Foo(1);
+ Foo *res = nullptr;
+ q.enqueue(*f);
+ res = q.dequeue();
+ if (res) {
+ cout << "Dequeued " << res->x << "\n";
+ } else {
+ cout << "Dequeued none\n\n";
+ }
+ }
+
+ cds::Terminate();
+ return 0;
+}
--- /dev/null
+#include <cds/gc/dhp.h>
+#include <cds/gc/hp.h>
+#include <cds/init.h>
+#include <cds/intrusive/fcstack.h>
+#include <iostream>
+#include <list>
+#include <string>
+
+using namespace std;
+
+namespace ci = cds::intrusive;
+typedef cds::gc::HP hp_gc;
+
+struct Foo : boost::intrusive::list_base_hook<> {
+ Foo(int x) : x(x) {}
+ int x;
+};
+
+typedef ci::FCStack<Foo> MyStack;
+
+int main() {
+ cds::Initialize();
+
+ {
+ // Initialize Hazard Pointer singleton
+ cds::gc::HP hpGC(128, 8, 128);
+ // If main thread uses lock-free containers
+ // the main thread should be attached to libcds infrastructure
+ cds::threading::Manager::attachThread();
+
+ MyStack s;
+ Foo *f = new Foo(1);
+ Foo *res = nullptr;
+ s.push(*f);
+ res = s.pop();
+ if (res) {
+ cout << "Dequeued " << res->x << "\n";
+ } else {
+ cout << "Dequeued none\n\n";
+ }
+ }
+
+ cds::Terminate();
+ return 0;
+}
--- /dev/null
+#include <cds/container/michael_kvlist_rcu.h>
+#include <iostream>
+#include <string>
+
+using namespace std;
+
+int main() {
+ string msg = "Hello world\n";
+ cout << msg;
+ cds::container::RWQueue<int> queue;
+ queue.enqueue(1);
+ int element;
+ if (queue.dequeue(element)) {
+ cout << "Queue element: " << element << '\n';
+ }
+ return 0;
+}
--- /dev/null
+#include <cds/gc/dhp.h>
+#include <cds/gc/hp.h>
+#include <cds/init.h>
+#include <cds/intrusive/moir_queue.h>
+#include <iostream>
+#include <string>
+
+using namespace std;
+
+namespace ci = cds::intrusive;
+typedef cds::gc::HP hp_gc;
+
+struct Foo : public ci::msqueue::node<hp_gc> {
+ Foo(int x) : x(x) {}
+ int x;
+};
+
+// Declare traits for the queue
+struct MyTraits : public cds::intrusive::msqueue::traits {
+ typedef cds::intrusive::msqueue::stat<> stat;
+ typedef cds::atomicity::item_counter item_counter;
+};
+
+// At least, declare the queue type
+typedef ci::MoirQueue<hp_gc, Foo, MyTraits> MyQueue;
+
+int main() {
+ cds::Initialize();
+
+ {
+ // Initialize Hazard Pointer singleton
+ cds::gc::HP hpGC(128, 8, 128);
+ // If main thread uses lock-free containers
+ // the main thread should be attached to libcds infrastructure
+ cds::threading::Manager::attachThread();
+
+ MyQueue q;
+ Foo *f = new Foo(1);
+ Foo *res = nullptr;
+ q.enqueue(*f);
+ res = q.dequeue();
+ if (res) {
+ cout << "Dequeued " << res->x << "\n";
+ } else {
+ cout << "Dequeued none\n";
+ }
+ }
+
+ cds::Terminate();
+ return 0;
+}
--- /dev/null
+#include <cds/gc/dhp.h>
+#include <cds/gc/hp.h>
+#include <cds/init.h>
+#include <cds/intrusive/msqueue.h>
+#include <iostream>
+#include <string>
+
+using namespace std;
+
+namespace ci = cds::intrusive;
+typedef cds::gc::HP hp_gc;
+
+struct Foo : public ci::msqueue::node<hp_gc> {
+ Foo(int x) : x(x) {}
+ int x;
+};
+
+// Declare traits for the queue
+struct MyTraits : public cds::intrusive::msqueue::traits {
+ typedef cds::intrusive::msqueue::stat<> stat;
+ typedef cds::atomicity::item_counter item_counter;
+};
+
+// At least, declare the queue type
+typedef ci::MSQueue<hp_gc, Foo, MyTraits> MyQueue;
+
+int main() {
+ cds::Initialize();
+
+ {
+ // Initialize Hazard Pointer singleton
+ cds::gc::HP hpGC(128, 8, 128);
+ // If main thread uses lock-free containers
+ // the main thread should be attached to libcds infrastructure
+ cds::threading::Manager::attachThread();
+
+ MyQueue q;
+ Foo *f = new Foo(1);
+ Foo *res = nullptr;
+ q.enqueue(*f);
+ res = q.dequeue();
+ if (res) {
+ cout << "Dequeued " << res->x << "\n";
+ } else {
+ cout << "Dequeued none\n";
+ }
+ }
+
+ cds::Terminate();
+ return 0;
+}
--- /dev/null
+#include <cds/gc/dhp.h>
+#include <cds/gc/hp.h>
+#include <cds/init.h>
+#include <cds/intrusive/optimistic_queue.h>
+#include <iostream>
+#include <string>
+
+using namespace std;
+
+namespace ci = cds::intrusive;
+typedef cds::gc::HP hp_gc;
+
+struct Foo : public ci::optimistic_queue::node<hp_gc> {
+ Foo(int x) : x(x) {}
+ int x;
+};
+
+// Declare traits for the queue
+struct MyTraits : public cds::intrusive::optimistic_queue::traits {
+ typedef cds::intrusive::optimistic_queue::stat<> stat;
+ typedef cds::atomicity::item_counter item_counter;
+};
+
+// At least, declare the queue type
+typedef ci::OptimisticQueue<hp_gc, Foo, MyTraits> MyQueue;
+
+int main() {
+ cds::Initialize();
+
+ {
+ // Initialize Hazard Pointer singleton
+ cds::gc::HP hpGC(128, 8, 128);
+ // If main thread uses lock-free containers
+ // the main thread should be attached to libcds infrastructure
+ cds::threading::Manager::attachThread();
+
+ MyQueue q;
+ Foo *f = new Foo(1);
+ Foo *res = nullptr;
+ q.enqueue(*f);
+ res = q.dequeue();
+ if (res) {
+ cout << "Dequeued " << res->x << "\n";
+ } else {
+ cout << "Dequeued none\n";
+ }
+ }
+
+ cds::Terminate();
+ return 0;
+}
--- /dev/null
+#include <cds/container/rwqueue.h>
+#include <cstdlib>
+#include <ctime>
+#include <iostream>
+#include <string>
+
+using namespace std;
+
+cds::container::RWQueue<int> queue;
+
+void InitQueue() {
+ for (int i = 0; i < 2000000; i++) {
+ queue.enqueue(rand() % 100);
+ }
+}
+
+void ProducerThread() {
+ for (int i = 0; i < 1000000; i++) {
+ for (int j = 0; j < 50; j++) {
+ queue.enqueue(rand() % 100);
+ }
+ }
+}
+
+void ProducerConsumerThread() {
+ unsigned long long sum = 0;
+ int element;
+ for (int i = 0; i < 1000000; i++) {
+ for (int j = 0; j < 50; j++) {
+ if (!queue.empty() && queue.dequeue(element)) {
+ sum += element;
+ }
+ if (j % 2 == 0) {
+ queue.enqueue(rand() % 100);
+ }
+ }
+ }
+}
+
+void ConsumerThread() {
+ int element;
+ unsigned long long sum = 0;
+ int yield_times = 3;
+ while (yield_times > 0) {
+ while (queue.dequeue(element)) {
+ sum += element;
+ yield_times = 3;
+ }
+ std::this_thread::yield();
+ yield_times--;
+ }
+}
+
+int main() {
+ srand(time(NULL));
+ const int kThreads = 6;
+ // Initialize the queue with some elements.
+ InitQueue();
+ cout << "Starting " << kThreads << " threads for RWQueue...\n";
+
+ struct timespec start, finish;
+ double elapsed = 0.0;
+ clock_gettime(CLOCK_MONOTONIC, &start);
+
+ std::thread threads[kThreads];
+ // Producer thread
+ threads[0] = std::thread(ProducerThread);
+ // ProducerConsumer threads
+ for (int i = 1; i < kThreads; i++) {
+ threads[i] = std::thread(ProducerConsumerThread);
+ }
+
+ for (int i = 0; i < kThreads; i++) {
+ threads[i].join();
+ }
+
+ clock_gettime(CLOCK_MONOTONIC, &finish);
+ elapsed = (finish.tv_sec - start.tv_sec);
+ elapsed += (finish.tv_nsec - start.tv_nsec) / 1000000000.0;
+ cout << "All threads finished.\n";
+ cout << "Time: " << elapsed << " seconds\n";
+ return 0;
+}
--- /dev/null
+#include <cds/gc/dhp.h>
+#include <cds/gc/hp.h>
+#include <cds/init.h>
+#include <cds/intrusive/segmented_queue.h>
+#include <iostream>
+#include <string>
+
+using namespace std;
+
+namespace ci = cds::intrusive;
+typedef cds::gc::HP hp_gc;
+
+struct Foo {
+ Foo(int x) : x(x) {}
+ int x;
+};
+
+// Declare traits for the queue
+struct MyTraits : public cds::intrusive::segmented_queue::traits {
+ typedef cds::intrusive::segmented_queue::stat<> stat;
+ typedef cds::atomicity::item_counter item_counter;
+};
+
+// The queue stores the pointers to enqueued items so no special node hooks are
+// needed.
+// At least, declare the queue type
+typedef ci::SegmentedQueue<hp_gc, Foo, MyTraits> MyQueue;
+
+int main() {
+ cds::Initialize();
+
+ {
+ // Initialize Hazard Pointer singleton
+ cds::gc::HP hpGC(128, 8, 128);
+ // If main thread uses lock-free containers
+ // the main thread should be attached to libcds infrastructure
+ cds::threading::Manager::attachThread();
+
+ MyQueue q(1024);
+ Foo *f = new Foo(1);
+ q.enqueue(*f);
+ Foo *res = q.dequeue();
+ if (res) {
+ cout << "Dequeued " << res->x << "\n";
+ } else {
+ cout << "Dequeued none\n";
+ }
+ }
+
+ cds::Terminate();
+ return 0;
+}
--- /dev/null
+#include <atomic>
+#include <cds/sync/spinlock.h>
+#include <ctime>
+#include <iostream>
+#include <string>
+#include <thread>
+
+using namespace std;
+
+int x;
+atomic_int y;
+cds::sync::spin_lock<cds::backoff::LockDefault> mutex;
+
+void Thread() {
+ for (int i = 0; i < 100000; i++) {
+ for (int j = 0; j < 3000; j++) {
+ // for (int i = 0; i < 300000; i++) {
+ // for (int j = 0; j < 300000; j++) {
+ if (!mutex.is_locked()) {
+ mutex.lock();
+ x = 1;
+ y.load(memory_order_relaxed);
+ mutex.unlock();
+ }
+ }
+ }
+}
+
+int main() {
+ const int kThreads = 6;
+ cout << "Starting " << kThreads << " threads for Spinlock...\n";
+
+ struct timespec start, finish;
+ double elapsed = 0.0;
+ clock_gettime(CLOCK_MONOTONIC, &start);
+
+ std::thread threads[kThreads];
+ for (int i = 0; i < kThreads; i++) {
+ threads[i] = std::thread(Thread);
+ }
+
+ for (int i = 0; i < kThreads; i++) {
+ threads[i].join();
+ }
+ clock_gettime(CLOCK_MONOTONIC, &finish);
+ elapsed = (finish.tv_sec - start.tv_sec);
+ elapsed += (finish.tv_nsec - start.tv_nsec) / 1000000000.0;
+ cout << "All threads finished.\n";
+ cout << "Time: " << elapsed << " seconds\n";
+
+ return 0;
+}
--- /dev/null
+#include <cds/init.h>
+#include <cds/gc/dhp.h>
+#include <cds/intrusive/treiber_stack.h>
+#include <iostream>
+#include <string>
+
+using namespace std;
+
+namespace ci = cds::intrusive;
+typedef cds::gc::HP gc;
+
+struct Foo : public ci::treiber_stack::node<gc> {
+ Foo(int x) : x(x) {}
+ int x;
+};
+
+struct MyTraits : public cds::intrusive::treiber_stack::traits {
+ typedef cds::intrusive::treiber_stack::stat<> stat;
+};
+
+// Equivalent make_traits example:
+typedef cds::intrusive::TreiberStack<cds::gc::HP, Foo> MyStack;
+
+int main() {
+ cds::Initialize();
+
+ {
+ // Initialize Hazard Pointer singleton
+ cds::gc::HP hpGC(128, 8, 128);
+ // If main thread uses lock-free containers
+ // the main thread should be attached to libcds infrastructure
+ cds::threading::Manager::attachThread();
+
+ MyStack s(1024);
+ Foo* f = new Foo(1);
+ Foo* res = nullptr;
+ s.push(*f);
+ res = s.pop();
+ if (res) {
+ cout << "Pop " << res->x << "\n";
+ } else {
+ cout << "Pop none\n";
+ }
+ }
+
+ cds::Terminate();
+ return 0;
+}
--- /dev/null
+#include <cds/gc/dhp.h>
+#include <cds/gc/hp.h>
+#include <cds/init.h>
+#include <cds/intrusive/vyukov_mpmc_cycle_queue.h>
+#include <iostream>
+#include <string>
+
+using namespace std;
+
+namespace ci = cds::intrusive;
+typedef cds::gc::HP hp_gc;
+
+struct Foo {
+ Foo(int x) : x(x) {}
+ int x;
+};
+
+typedef cds::intrusive::VyukovMPMCCycleQueue<
+ Foo, typename cds::intrusive::vyukov_queue::make_traits<cds::opt::buffer<
+ cds::opt::v::uninitialized_static_buffer<Foo, 1024>>>::type>
+ static_queue;
+
+// Queue of Foo pointers, capacity is 1024, dynamically allocated buffer:
+struct queue_traits : public cds::intrusive::vyukov_queue::traits {
+ typedef cds::opt::v::uninitialized_dynamic_buffer<Foo> buffer;
+};
+typedef cds::intrusive::VyukovMPMCCycleQueue<Foo, queue_traits> dynamic_queue;
+
+int main() {
+ cds::Initialize();
+
+ {
+ // Initialize Hazard Pointer singleton
+ cds::gc::HP hpGC(128, 8, 128);
+ // If main thread uses lock-free containers
+ // the main thread should be attached to libcds infrastructure
+ cds::threading::Manager::attachThread();
+
+ static_queue q;
+ Foo *f = new Foo(1);
+ Foo *res = nullptr;
+ q.enqueue(*f);
+ res = q.dequeue();
+ if (res) {
+ cout << "Dequeued " << res->x << "\n";
+ } else {
+ cout << "Dequeued none\n";
+ }
+ }
+
+ cds::Terminate();
+ return 0;
+}