169 lines
3.5 KiB
C++
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();
|
|
}
|