2020-11-04 20:24:54 -05:00
|
|
|
#include <glibmm.h>
|
|
|
|
|
|
|
|
#include "rcu_test.h"
|
|
|
|
|
|
|
|
using namespace std;
|
|
|
|
|
|
|
|
RCUTest::RCUTest ()
|
|
|
|
: CppUnit::TestFixture ()
|
|
|
|
, _values (new Values)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
CPPUNIT_TEST_SUITE_REGISTRATION (RCUTest);
|
|
|
|
|
|
|
|
void
|
|
|
|
RCUTest::setUp ()
|
|
|
|
{
|
|
|
|
if (!Glib::thread_supported ()) {
|
|
|
|
Glib::thread_init ();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void*
|
|
|
|
launch_reader(void* self)
|
|
|
|
{
|
|
|
|
RCUTest* r = static_cast<RCUTest *>(self);
|
|
|
|
r->read_thread ();
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void*
|
|
|
|
launch_writer(void* self)
|
|
|
|
{
|
|
|
|
RCUTest* r = static_cast<RCUTest *>(self);
|
|
|
|
r->write_thread ();
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
RCUTest::race ()
|
|
|
|
{
|
2020-11-05 13:55:39 -05:00
|
|
|
#ifdef __APPLE__
|
|
|
|
pthread_mutex_init (&_mutex, NULL);
|
|
|
|
pthread_cond_init (&_cond, NULL);
|
|
|
|
_cnt = 0;
|
|
|
|
#else
|
2020-11-04 20:24:54 -05:00
|
|
|
pthread_barrier_init (&_barrier, NULL, 2);
|
2020-11-05 13:55:39 -05:00
|
|
|
#endif
|
2020-11-04 20:24:54 -05:00
|
|
|
|
|
|
|
pthread_t reader_thread;
|
|
|
|
pthread_t writer_thread;
|
|
|
|
|
|
|
|
CPPUNIT_ASSERT (pthread_create (&writer_thread, NULL, launch_writer, this) == 0);
|
|
|
|
CPPUNIT_ASSERT (pthread_create (&reader_thread, NULL, launch_reader, this) == 0);
|
|
|
|
|
|
|
|
void* return_value;
|
|
|
|
CPPUNIT_ASSERT (pthread_join (writer_thread, &return_value) == 0);
|
|
|
|
CPPUNIT_ASSERT (pthread_join (reader_thread, &return_value) == 0);
|
|
|
|
|
2020-11-05 13:55:39 -05:00
|
|
|
#ifdef __APPLE__
|
|
|
|
pthread_mutex_destroy (&_mutex);
|
|
|
|
pthread_cond_destroy (&_cond);
|
|
|
|
#else
|
2020-11-04 20:24:54 -05:00
|
|
|
pthread_barrier_destroy (&_barrier);
|
2020-11-05 13:55:39 -05:00
|
|
|
#endif
|
2020-11-04 20:24:54 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/* ****************************************************************************/
|
|
|
|
|
|
|
|
void
|
|
|
|
RCUTest::read_thread ()
|
|
|
|
{
|
2020-11-05 13:55:39 -05:00
|
|
|
#ifdef __APPLE__
|
|
|
|
pthread_mutex_lock (&_mutex);
|
|
|
|
if (++_cnt == 2) {
|
|
|
|
pthread_cond_broadcast (&_cond);
|
|
|
|
pthread_mutex_unlock (&_mutex);
|
|
|
|
} else {
|
|
|
|
pthread_cond_wait (&_cond, &_mutex);
|
|
|
|
}
|
|
|
|
pthread_mutex_unlock (&_mutex);
|
|
|
|
#else
|
2020-11-04 20:24:54 -05:00
|
|
|
pthread_barrier_wait (&_barrier);
|
2020-11-05 13:55:39 -05:00
|
|
|
#endif
|
2020-11-04 20:24:54 -05:00
|
|
|
|
|
|
|
for (int i = 0; i < 15000; ++i) {
|
2023-04-07 17:33:13 -04:00
|
|
|
std::shared_ptr<Values const> reader = _values.reader ();
|
2020-11-04 20:24:54 -05:00
|
|
|
for (Values::const_iterator i = reader->begin (); i != reader->end(); ++i) {
|
|
|
|
CPPUNIT_ASSERT (i->first == i->second->val);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
RCUTest::write_thread ()
|
|
|
|
{
|
2020-11-05 13:55:39 -05:00
|
|
|
#ifdef __APPLE__
|
|
|
|
pthread_mutex_lock (&_mutex);
|
|
|
|
if (++_cnt == 2) {
|
|
|
|
pthread_cond_broadcast (&_cond);
|
|
|
|
pthread_mutex_unlock (&_mutex);
|
|
|
|
} else {
|
|
|
|
pthread_cond_wait (&_cond, &_mutex);
|
|
|
|
}
|
|
|
|
pthread_mutex_unlock (&_mutex);
|
|
|
|
#else
|
2020-11-04 20:24:54 -05:00
|
|
|
pthread_barrier_wait (&_barrier);
|
2020-11-05 13:55:39 -05:00
|
|
|
#endif
|
2020-11-04 20:24:54 -05:00
|
|
|
|
|
|
|
for (int i = 0; i < 10000; ++i) {
|
|
|
|
RCUWriter<Values> writer (_values);
|
2023-02-16 18:33:28 -05:00
|
|
|
std::shared_ptr<Values> w = writer.get_copy ();
|
2020-11-04 20:24:54 -05:00
|
|
|
char tmp [64];
|
|
|
|
sprintf (tmp, "foo %d", i);
|
|
|
|
w->insert (make_pair (tmp, new Value (tmp)));
|
|
|
|
}
|
|
|
|
|
|
|
|
/* replace */
|
|
|
|
for (int i = 0; i < 2500; ++i) {
|
|
|
|
RCUWriter<Values> writer (_values);
|
2023-02-16 18:33:28 -05:00
|
|
|
std::shared_ptr<Values> w = writer.get_copy ();
|
2020-11-04 20:24:54 -05:00
|
|
|
|
|
|
|
char tmp [64];
|
|
|
|
sprintf (tmp, "foo %d", i);
|
|
|
|
|
|
|
|
Values::iterator x = w->find (tmp);
|
|
|
|
CPPUNIT_ASSERT (x != w->end ());
|
|
|
|
sprintf (tmp, "bar %d", i);
|
|
|
|
|
|
|
|
w->erase (x);
|
|
|
|
w->insert (make_pair (tmp, new Value (tmp)));
|
|
|
|
}
|
|
|
|
|
|
|
|
/* clear */
|
|
|
|
{
|
|
|
|
RCUWriter<Values> writer (_values);
|
2023-02-16 18:33:28 -05:00
|
|
|
std::shared_ptr<Values> w = writer.get_copy ();
|
2020-11-04 20:24:54 -05:00
|
|
|
w->clear ();
|
|
|
|
}
|
|
|
|
_values.flush ();
|
|
|
|
}
|