lockfree: add lockfree spsc ringbuffer
[boost_lockfree.git] / libs / lockfree / test / ringbuffer_test.cpp
blobdf2a915a5a959fe07590163c1214e0e718af2fae
1 #include <boost/lockfree/ringbuffer.hpp>
3 #include <climits>
4 #define BOOST_TEST_MODULE lockfree_tests
5 #include <boost/test/included/unit_test.hpp>
8 #include <boost/thread.hpp>
9 #include <iostream>
10 #include <memory>
13 #include "test_helpers.hpp"
15 using namespace boost;
16 using namespace boost::lockfree;
17 using namespace std;
20 BOOST_AUTO_TEST_CASE( simple_ringbuffer_test )
22 ringbuffer<int, 64> f;
24 BOOST_REQUIRE(f.empty());
25 f.enqueue(1);
26 f.enqueue(2);
28 int i1(0), i2(0);
30 BOOST_REQUIRE(f.dequeue(&i1));
31 BOOST_REQUIRE_EQUAL(i1, 1);
33 BOOST_REQUIRE(f.dequeue(&i2));
34 BOOST_REQUIRE_EQUAL(i2, 2);
35 BOOST_REQUIRE(f.empty());
39 struct ringbuffer_tester
41 ringbuffer<int, 128> sf;
43 atomic<long> ringbuffer_cnt, received_nodes;
45 static_hashed_set<int, 1<<16 > working_set;
47 static const uint nodes_per_thread = 20000000;
49 static const int reader_threads = 1;
50 static const int writer_threads = 1;
52 ringbuffer_tester(void):
53 ringbuffer_cnt(0), received_nodes(0)
56 void add(void)
58 for (uint i = 0; i != nodes_per_thread; ++i)
60 while(ringbuffer_cnt > 10000)
61 thread::yield();
63 int id = generate_id<int>();
65 working_set.insert(id);
67 while (sf.enqueue(id) == false)
69 thread::yield();
72 ++ringbuffer_cnt;
76 bool get_element(void)
78 int data;
80 bool success = sf.dequeue(&data);
82 if (success)
84 ++received_nodes;
85 --ringbuffer_cnt;
86 bool erased = working_set.erase(data);
87 assert(erased);
88 return true;
90 else
91 return false;
94 volatile bool running;
96 void get(void)
98 for(;;)
100 bool success = get_element();
101 if (not running and not success)
102 return;
103 if (not success)
104 thread::yield();
108 void run(void)
110 running = true;
112 thread_group writer;
113 thread_group reader;
115 BOOST_REQUIRE(sf.empty());
116 for (int i = 0; i != reader_threads; ++i)
117 reader.create_thread(boost::bind(&ringbuffer_tester::get, this));
119 for (int i = 0; i != writer_threads; ++i)
120 writer.create_thread(boost::bind(&ringbuffer_tester::add, this));
121 cout << "reader and writer threads created" << endl;
123 writer.join_all();
124 cout << "writer threads joined. waiting for readers to finish" << endl;
126 running = false;
127 reader.join_all();
129 BOOST_REQUIRE_EQUAL(received_nodes, writer_threads * nodes_per_thread);
130 BOOST_REQUIRE_EQUAL(ringbuffer_cnt, 0);
131 BOOST_REQUIRE(sf.empty());
132 BOOST_REQUIRE(working_set.count_nodes() == 0);
138 BOOST_AUTO_TEST_CASE( ringbuffer_test_caching )
140 ringbuffer_tester test1;
141 test1.run();