src.dualinventive.com/dinet/libdipp/tests/mailbox.cpp

169 lines
3.5 KiB
C++

/**
* @file mailbox.cpp
* @brief <brief>
* @date Aug 16, 2015
* @author rheijden
* @copyright 2015 Dual Inventive Technology Centre B.V.
*
* <description>
*/
#include <memory>
#include <thread>
#include <chrono>
#include <di/Log.h>
#include <di/Time.h>
#include <di/Mailbox.h>
#include <gtest/gtest.h>
using namespace Di;
using namespace std;
static Mailbox<int> mb;
TEST(Mailbox, empty) {
shared_ptr<int> a = make_shared<int>(100);
shared_ptr<int> b = make_shared<int>(50);
EXPECT_FALSE(mb.fetch(&b, false));
EXPECT_EQ(50, *b);
EXPECT_FALSE(mb.fetch(&b, true, chrono::milliseconds(50)));
mb.post(a);
EXPECT_TRUE(mb.fetch(&b, true));
EXPECT_EQ(100, *b);
mb.reset();
}
void worker(int w) {
shared_ptr<int> b;
Log::debug("Worker %d waiting", w);
EXPECT_TRUE(mb.fetch(&b));
Log::debug("Worker %d shutting down (b = %d)", w, b.get());
}
TEST(Mailbox, workers) {
shared_ptr<int> a = make_shared<int>(0);
thread w1(worker, 1), w2(worker, 2), w3(worker, 3), w4(worker, 4), w5(worker, 5), w6(worker, 6), w7(worker, 7),
w8(worker, 8), w9(worker, 9), w10(worker, 10);
this_thread::sleep_for(chrono::milliseconds(1000));
for (int i = 0; i < 10; i++) {
*a = i;
mb.post(a);
this_thread::sleep_for(chrono::milliseconds(100));
}
w1.join();
w2.join();
w3.join();
w4.join();
w5.join();
w6.join();
w7.join();
w8.join();
w9.join();
w10.join();
mb.reset();
}
TEST(Mailbox, postorder) {
mb.reset();
shared_ptr<int> a = make_shared<int>(10);
shared_ptr<int> b = make_shared<int>(10);
shared_ptr<int> c;
mb.post(a);
mb.postAhead(b);
EXPECT_TRUE(mb.fetch(&c, false));
EXPECT_EQ(*b, *c);
EXPECT_TRUE(mb.fetch(&c, false));
EXPECT_EQ(*a, *c);
EXPECT_FALSE(mb.fetch(&c, false));
mb.post(b);
mb.post(a);
EXPECT_TRUE(mb.fetch(&c, true, chrono::milliseconds(100)));
EXPECT_EQ(*b, *c);
EXPECT_TRUE(mb.fetch(&c, true, chrono::milliseconds(100)));
EXPECT_EQ(*a, *c);
EXPECT_FALSE(mb.fetch(&c, true, chrono::milliseconds(10)));
}
class Mailbox_test : public Mailbox<int> {
public:
void setLock(void) {
Log::debug("Locking the mutex");
_lock.lock();
}
void unsetLock(void) {
Log::debug("Unlocking the mutex");
_lock.unlock();
}
};
static Mailbox_test mt;
void poster(int w) {
uint64_t t1, t2;
Log::debug("Poster %d about to post", w);
t1 = Time::getNow();
mt.post(nullptr);
t2 = Time::getNow();
Log::debug("Poster %d shutting down (t1 = %lu, t2 = %lu)", w, t1, t2);
ASSERT_GE((t2 - t1), 400UL);
}
TEST(Mailbox, post_lock) {
shared_ptr<int> b;
mt.setLock();
thread w1(poster, 1);
this_thread::sleep_for(chrono::milliseconds(500));
mt.unsetLock();
w1.join();
mt.reset();
}
void aheadPoster(int w) {
uint64_t t1, t2;
Log::debug("AheadPoster %d about to post", w);
t1 = Time::getNow();
mt.postAhead(nullptr);
t2 = Time::getNow();
Log::debug("AheadPoster %d shutting down (t1 = %lu, t2 = %lu)", w, t1, t2);
ASSERT_GE((t2 - t1), 400UL);
}
TEST(Mailbox, postahead_lock) {
shared_ptr<int> b;
mt.setLock();
thread w1(aheadPoster, 1);
this_thread::sleep_for(chrono::milliseconds(500));
mt.unsetLock();
w1.join();
mt.reset();
}
void resetter(int w) {
uint64_t t1, t2;
Log::debug("Resetter %d about to post", w);
t1 = Time::getNow();
mt.reset();
t2 = Time::getNow();
Log::debug("Resetter %d shutting down (t1 = %lu, t2 = %lu)", w, t1, t2);
ASSERT_GE((t2 - t1), 400UL);
}
TEST(Mailbox, reset_lock) {
shared_ptr<int> b;
mt.setLock();
thread w1(resetter, 1);
this_thread::sleep_for(chrono::milliseconds(500));
mt.unsetLock();
w1.join();
mt.reset();
}