未验证 提交 6b494015 编写于 作者: C chengduo 提交者: GitHub

Merge pull request #8222 from chengduoZH/feature/fix_buffer_unit_test

Refine Channel's unit test
...@@ -176,7 +176,7 @@ TEST(Channel, ConcurrentSendNonConcurrentReceiveWithSufficientBufferSize) { ...@@ -176,7 +176,7 @@ TEST(Channel, ConcurrentSendNonConcurrentReceiveWithSufficientBufferSize) {
sum += i; sum += i;
} }
}); });
std::this_thread::sleep_for(std::chrono::milliseconds(100)); // wait 0.5 sec std::this_thread::sleep_for(std::chrono::milliseconds(100)); // wait 0.1 sec
EXPECT_EQ(sum, 45U); EXPECT_EQ(sum, 45U);
CloseChannel(ch); CloseChannel(ch);
...@@ -194,10 +194,7 @@ TEST(Channel, RecevingOrderEqualToSendingOrderWithBufferedChannel) { ...@@ -194,10 +194,7 @@ TEST(Channel, RecevingOrderEqualToSendingOrderWithBufferedChannel) {
RecevingOrderEqualToSendingOrder(ch); RecevingOrderEqualToSendingOrder(ch);
} }
// This tests that closing a buffered channel also unblocks void ChannelCloseUnblocksReceiversTest(Channel<int> *ch) {
// any receivers waiting on the channel
TEST(Channel, BufferedChannelCloseUnblocksReceiversTest) {
auto ch = MakeChannel<int>(1);
size_t num_threads = 5; size_t num_threads = 5;
std::thread t[num_threads]; std::thread t[num_threads];
bool thread_ended[num_threads]; bool thread_ended[num_threads];
...@@ -208,15 +205,14 @@ TEST(Channel, BufferedChannelCloseUnblocksReceiversTest) { ...@@ -208,15 +205,14 @@ TEST(Channel, BufferedChannelCloseUnblocksReceiversTest) {
t[i] = std::thread( t[i] = std::thread(
[&](bool *p) { [&](bool *p) {
int data; int data;
// All reads should return false
EXPECT_EQ(ch->Receive(&data), false); EXPECT_EQ(ch->Receive(&data), false);
*p = true; *p = true;
}, },
&thread_ended[i]); &thread_ended[i]);
} }
std::this_thread::sleep_for(std::chrono::milliseconds(100)); // wait std::this_thread::sleep_for(std::chrono::milliseconds(100)); // wait 0.1 sec
// Verify that all threads are blocked // Verify that all the threads are blocked
for (size_t i = 0; i < num_threads; i++) { for (size_t i = 0; i < num_threads; i++) {
EXPECT_EQ(thread_ended[i], false); EXPECT_EQ(thread_ended[i], false);
} }
...@@ -225,7 +221,7 @@ TEST(Channel, BufferedChannelCloseUnblocksReceiversTest) { ...@@ -225,7 +221,7 @@ TEST(Channel, BufferedChannelCloseUnblocksReceiversTest) {
// This should unblock all receivers // This should unblock all receivers
CloseChannel(ch); CloseChannel(ch);
std::this_thread::sleep_for(std::chrono::milliseconds(200)); // wait std::this_thread::sleep_for(std::chrono::milliseconds(100)); // wait 0.1 sec
// Verify that all threads got unblocked // Verify that all threads got unblocked
for (size_t i = 0; i < num_threads; i++) { for (size_t i = 0; i < num_threads; i++) {
...@@ -233,13 +229,12 @@ TEST(Channel, BufferedChannelCloseUnblocksReceiversTest) { ...@@ -233,13 +229,12 @@ TEST(Channel, BufferedChannelCloseUnblocksReceiversTest) {
} }
for (size_t i = 0; i < num_threads; i++) t[i].join(); for (size_t i = 0; i < num_threads; i++) t[i].join();
delete ch;
} }
// This tests that closing a buffered channel also unblocks void ChannelCloseUnblocksSendersTest(Channel<int> *ch) {
// any senders waiting for channel to have write space using paddle::framework::details::Buffered;
TEST(Channel, BufferedChannelCloseUnblocksSendersTest) { using paddle::framework::details::UnBuffered;
auto ch = MakeChannel<int>(1);
size_t num_threads = 5; size_t num_threads = 5;
std::thread t[num_threads]; std::thread t[num_threads];
bool thread_ended[num_threads]; bool thread_ended[num_threads];
...@@ -259,34 +254,56 @@ TEST(Channel, BufferedChannelCloseUnblocksSendersTest) { ...@@ -259,34 +254,56 @@ TEST(Channel, BufferedChannelCloseUnblocksSendersTest) {
} }
std::this_thread::sleep_for(std::chrono::milliseconds(100)); // wait std::this_thread::sleep_for(std::chrono::milliseconds(100)); // wait
// Verify that atleast 4 threads are blocked if (dynamic_cast<Buffered<int> *>(ch)) {
int ct = 0; // If ch is Buffered, atleast 4 threads must be blocked.
for (size_t i = 0; i < num_threads; i++) { int ct = 0;
if (thread_ended[i] == false) ct++; for (size_t i = 0; i < num_threads; i++) {
if (!thread_ended[i]) ct++;
}
EXPECT_GE(ct, 4);
} else {
// If ch is UnBuffered, all the threads should be blocked.
for (size_t i = 0; i < num_threads; i++) {
EXPECT_EQ(thread_ended[i], false);
}
} }
// Atleast 4 threads must be blocked
EXPECT_GE(ct, 4);
// Explicitly close the thread // Explicitly close the thread
// This should unblock all senders // This should unblock all senders
CloseChannel(ch); CloseChannel(ch);
std::this_thread::sleep_for(std::chrono::milliseconds(200)); // wait std::this_thread::sleep_for(std::chrono::milliseconds(100)); // wait
// Verify that all threads got unblocked // Verify that all threads got unblocked
for (size_t i = 0; i < num_threads; i++) { for (size_t i = 0; i < num_threads; i++) {
EXPECT_EQ(thread_ended[i], true); EXPECT_EQ(thread_ended[i], true);
} }
// Verify that only 1 send was successful if (dynamic_cast<Buffered<int> *>(ch)) {
ct = 0; // Verify that only 1 send was successful
for (size_t i = 0; i < num_threads; i++) { int ct = 0;
if (send_success[i]) ct++; for (size_t i = 0; i < num_threads; i++) {
if (send_success[i]) ct++;
}
// Only 1 send must be successful
EXPECT_EQ(ct, 1);
} }
// Only 1 send must be successful
EXPECT_EQ(ct, 1);
for (size_t i = 0; i < num_threads; i++) t[i].join(); for (size_t i = 0; i < num_threads; i++) t[i].join();
}
// This tests that closing a buffered channel also unblocks
// any receivers waiting on the channel
TEST(Channel, BufferedChannelCloseUnblocksReceiversTest) {
auto ch = MakeChannel<int>(1);
ChannelCloseUnblocksReceiversTest(ch);
delete ch;
}
// This tests that closing a buffered channel also unblocks
// any senders waiting for channel to have write space
TEST(Channel, BufferedChannelCloseUnblocksSendersTest) {
auto ch = MakeChannel<int>(1);
ChannelCloseUnblocksSendersTest(ch);
delete ch; delete ch;
} }
...@@ -294,40 +311,7 @@ TEST(Channel, BufferedChannelCloseUnblocksSendersTest) { ...@@ -294,40 +311,7 @@ TEST(Channel, BufferedChannelCloseUnblocksSendersTest) {
// unblocks any receivers waiting for senders // unblocks any receivers waiting for senders
TEST(Channel, UnbufferedChannelCloseUnblocksReceiversTest) { TEST(Channel, UnbufferedChannelCloseUnblocksReceiversTest) {
auto ch = MakeChannel<int>(0); auto ch = MakeChannel<int>(0);
size_t num_threads = 5; ChannelCloseUnblocksReceiversTest(ch);
std::thread t[num_threads];
bool thread_ended[num_threads];
// Launches threads that try to read and are blocked becausew of no writers
for (size_t i = 0; i < num_threads; i++) {
thread_ended[i] = false;
t[i] = std::thread(
[&](bool *p) {
int data;
EXPECT_EQ(ch->Receive(&data), false);
*p = true;
},
&thread_ended[i]);
}
std::this_thread::sleep_for(std::chrono::milliseconds(500)); // wait 0.5 sec
// Verify that all the threads are blocked
for (size_t i = 0; i < num_threads; i++) {
EXPECT_EQ(thread_ended[i], false);
}
// Explicitly close the thread
// This should unblock all receivers
CloseChannel(ch);
std::this_thread::sleep_for(std::chrono::milliseconds(500)); // wait 0.5 sec
// Verify that all threads got unblocked
for (size_t i = 0; i < num_threads; i++) {
EXPECT_EQ(thread_ended[i], true);
}
for (size_t i = 0; i < num_threads; i++) t[i].join();
delete ch; delete ch;
} }
...@@ -335,40 +319,7 @@ TEST(Channel, UnbufferedChannelCloseUnblocksReceiversTest) { ...@@ -335,40 +319,7 @@ TEST(Channel, UnbufferedChannelCloseUnblocksReceiversTest) {
// unblocks any senders waiting for senders // unblocks any senders waiting for senders
TEST(Channel, UnbufferedChannelCloseUnblocksSendersTest) { TEST(Channel, UnbufferedChannelCloseUnblocksSendersTest) {
auto ch = MakeChannel<int>(0); auto ch = MakeChannel<int>(0);
size_t num_threads = 5; ChannelCloseUnblocksReceiversTest(ch);
std::thread t[num_threads];
bool thread_ended[num_threads];
// Launches threads that try to read and are blocked becausew of no writers
for (size_t i = 0; i < num_threads; i++) {
thread_ended[i] = false;
t[i] = std::thread(
[&](bool *p) {
int data = 10;
EXPECT_EQ(ch->Send(&data), false);
*p = true;
},
&thread_ended[i]);
}
std::this_thread::sleep_for(std::chrono::milliseconds(500)); // wait 0.5 sec
// Verify that all the threads are blocked
for (size_t i = 0; i < num_threads; i++) {
EXPECT_EQ(thread_ended[i], false);
}
// Explicitly close the thread
// This should unblock all receivers
CloseChannel(ch);
std::this_thread::sleep_for(std::chrono::milliseconds(500)); // wait 0.5 sec
// Verify that all threads got unblocked
for (size_t i = 0; i < num_threads; i++) {
EXPECT_EQ(thread_ended[i], true);
}
for (size_t i = 0; i < num_threads; i++) t[i].join();
delete ch; delete ch;
} }
......
...@@ -25,6 +25,14 @@ namespace paddle { ...@@ -25,6 +25,14 @@ namespace paddle {
namespace framework { namespace framework {
namespace details { namespace details {
// Four of the properties of Buffered Channel:
// - A send to a full channel blocks temporarily until a receive from the
// channel or the channel is closed.
// - A receive from an empty channel blocks temporarily until a send to the
// channel or the channel is closed.
// - A send to a closed channel returns false immediately.
// - A receive from a closed channel returns false immediately.
template <typename T> template <typename T>
class Buffered : public paddle::framework::Channel<T> { class Buffered : public paddle::framework::Channel<T> {
friend Channel<T>* paddle::framework::MakeChannel<T>(size_t); friend Channel<T>* paddle::framework::MakeChannel<T>(size_t);
......
...@@ -23,6 +23,13 @@ namespace paddle { ...@@ -23,6 +23,13 @@ namespace paddle {
namespace framework { namespace framework {
namespace details { namespace details {
// Four of the properties of UnBuffered Channel:
// - A send to a channel blocks temporarily until a receive from the
// channel or the channel is closed.
// - A receive from a channel blocks temporarily until a send to the
// channel or the channel is closed.
// - A send to a closed channel returns false immediately.
// - A receive from a closed channel returns false immediately.
template <typename T> template <typename T>
class UnBuffered : public paddle::framework::Channel<T> { class UnBuffered : public paddle::framework::Channel<T> {
friend Channel<T>* paddle::framework::MakeChannel<T>(size_t); friend Channel<T>* paddle::framework::MakeChannel<T>(size_t);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册