diff --git a/lib/concurrent/test/BlockingDequeueUnitTest.cpp b/lib/concurrent/test/BlockingDequeueUnitTest.cpp index 293c89fd..e0d4dd46 100644 --- a/lib/concurrent/test/BlockingDequeueUnitTest.cpp +++ b/lib/concurrent/test/BlockingDequeueUnitTest.cpp @@ -120,7 +120,33 @@ TEST(BlockingDequeueUnitTest, take_is_last) { ASSERT_EQ(dequeue.take(), 222); } -TEST(BlockingDequeueUnitTest, poll_is_block_when_empty) { +TEST(BlockingDequeueUnitTest, poll_is_not_block_when_empty) { + size_t capacity = 1; + bool isOk; + auto conditionVar = new MockConditionVar(); + PIBlockingDequeue dequeue(capacity, conditionVar); + dequeue.poll(111, &isOk); + EXPECT_FALSE(conditionVar->isWaitForCalled); +} + +TEST(BlockingDequeueUnitTest, poll_is_default_value_when_empty) { + size_t capacity = 1; + bool isOk; + auto conditionVar = new MockConditionVar(); + PIBlockingDequeue dequeue(capacity, conditionVar); + ASSERT_EQ(dequeue.poll(111, &isOk), 111); +} + +TEST(BlockingDequeueUnitTest, poll_is_offer_value_when_not_empty) { + size_t capacity = 1; + bool isOk; + auto conditionVar = new MockConditionVar(); + PIBlockingDequeue dequeue(capacity, conditionVar); + dequeue.offer(111); + ASSERT_EQ(dequeue.poll(-1, &isOk), 111); +} + +TEST(BlockingDequeueUnitTest, poll_timeouted_is_block_when_empty) { size_t capacity = 1; int timeout = 11; auto conditionVar = new MockConditionVar(); @@ -131,7 +157,7 @@ TEST(BlockingDequeueUnitTest, poll_is_block_when_empty) { ASSERT_FALSE(conditionVar->isTrueCondition); } -TEST(BlockingDequeueUnitTest, poll_is_default_value_when_empty) { +TEST(BlockingDequeueUnitTest, poll_timeouted_is_default_value_when_empty) { size_t capacity = 1; int timeout = 11; auto conditionVar = new MockConditionVar(); @@ -139,7 +165,7 @@ TEST(BlockingDequeueUnitTest, poll_is_default_value_when_empty) { ASSERT_EQ(dequeue.poll(timeout, 111), 111); } -TEST(BlockingDequeueUnitTest, poll_is_not_block_when_not_empty) { +TEST(BlockingDequeueUnitTest, poll_timeouted_is_not_block_when_not_empty) { size_t capacity = 1; int timeout = 11; auto conditionVar = new MockConditionVar(); @@ -151,7 +177,7 @@ TEST(BlockingDequeueUnitTest, poll_is_not_block_when_not_empty) { ASSERT_TRUE(conditionVar->isTrueCondition); } -TEST(BlockingDequeueUnitTest, poll_is_offer_value_when_not_empty) { +TEST(BlockingDequeueUnitTest, poll_timeouted_is_offer_value_when_not_empty) { size_t capacity = 1; int timeout = 11; auto conditionVar = new MockConditionVar(); @@ -160,7 +186,7 @@ TEST(BlockingDequeueUnitTest, poll_is_offer_value_when_not_empty) { ASSERT_EQ(dequeue.poll(timeout, -1), 111); } -TEST(BlockingDequeueUnitTest, poll_is_last) { +TEST(BlockingDequeueUnitTest, poll_timeouted_is_last) { size_t capacity = 10; auto conditionVar = new MockConditionVar(); PIBlockingDequeue dequeue(capacity, conditionVar); diff --git a/lib/main/concurrent/piblockingdequeue.h b/lib/main/concurrent/piblockingdequeue.h index 7ec78f11..5f64da06 100644 --- a/lib/main/concurrent/piblockingdequeue.h +++ b/lib/main/concurrent/piblockingdequeue.h @@ -136,9 +136,11 @@ public: * * @param timeoutMs how long to wait before giving up, in milliseconds * @param defaultVal value, which returns if the specified waiting time elapses before an element is available + * @param isOk flag, which indicates result of method execution. It will be set to false if timeout, or true if + * return value is retrieved value * @return the head of this queue, or defaultVal if the specified waiting time elapses before an element is available */ - T poll(int timeoutMs, const T & defaultVal, bool* isOk = nullptr) { + T poll(int timeoutMs, const T & defaultVal = T(), bool* isOk = nullptr) { T t; mutex.lock(); bool isNotEmpty = cond_var_add->waitFor(mutex, timeoutMs, [&]() { return !PIDeque::isEmpty(); }); @@ -149,6 +151,26 @@ public: return t; } + /** + * @brief Retrieves and removes the head of this queue and return it if queue not empty, otherwise return defaultVal. + * Do it immediately without waiting. + * + * @param defaultVal value, which returns if the specified waiting time elapses before an element is available + * @param isOk flag, which indicates result of method execution. It will be set to false if timeout, or true if + * return value is retrieved value + * @return the head of this queue, or defaultVal if the specified waiting time elapses before an element is available + */ + T poll(const T & defaultVal = T(), bool* isOk = nullptr) { + T t; + mutex.lock(); + bool isNotEmpty = !PIDeque::isEmpty(); + t = isNotEmpty ? T(PIDeque::take_front()) : defaultVal; + mutex.unlock(); + if (isNotEmpty) cond_var_rem->notifyOne(); + if (isOk != nullptr) *isOk = isNotEmpty; + return t; + } + /** * @brief Returns the number of elements that this queue can ideally (in the absence of memory or resource * constraints) contains. This is always equal to the initial capacity of this queue less the current size of this queue.