implement timeouts for events
Change-Id: I8ec89fc5bdc7b53ddc1d5c86494615c95be9bd0e
diff --git a/aos/common/BUILD b/aos/common/BUILD
index 45c1d72..4262b60 100644
--- a/aos/common/BUILD
+++ b/aos/common/BUILD
@@ -96,6 +96,7 @@
],
deps = [
'//aos/linux_code/ipc_lib:aos_sync',
+ ':time',
],
)
diff --git a/aos/common/common.gyp b/aos/common/common.gyp
index 9c43936..14619ad 100644
--- a/aos/common/common.gyp
+++ b/aos/common/common.gyp
@@ -253,10 +253,12 @@
],
'dependencies': [
'<(AOS)/linux_code/ipc_lib/ipc_lib.gyp:aos_sync',
+ 'time',
'<(AOS)/build/aos.gyp:logging_interface',
],
'export_dependent_settings': [
'<(AOS)/linux_code/ipc_lib/ipc_lib.gyp:aos_sync',
+ 'time',
],
},
{
diff --git a/aos/common/event.h b/aos/common/event.h
index 9839d41..b3ee87b 100644
--- a/aos/common/event.h
+++ b/aos/common/event.h
@@ -1,6 +1,8 @@
#ifndef AOS_COMMON_EVENT_H_
#define AOS_COMMON_EVENT_H_
+#include "aos/common/time.h"
+
#include "aos/linux_code/ipc_lib/aos_sync.h"
namespace aos {
@@ -37,6 +39,11 @@
// Waits for the event to be set. Returns immediately if it is already set.
void Wait();
+ // Waits for the event to be set or until timeout has elapsed. Returns
+ // immediately if it is already set.
+ // Returns true if the event was Set or false if the timeout expired.
+ bool WaitTimeout(const ::aos::time::Time &timeout);
+
// Wakes up all Wait()ers and sets the event (atomically).
void Set();
// Unsets the event so future Wait() callers will block instead of returning
diff --git a/aos/common/event_test.cc b/aos/common/event_test.cc
index d8671eb..7331309 100644
--- a/aos/common/event_test.cc
+++ b/aos/common/event_test.cc
@@ -12,7 +12,7 @@
class EventTest : public ::testing::Test {
public:
- Event test_event;
+ Event test_event_;
protected:
void SetUp() override {
@@ -22,13 +22,13 @@
// Makes sure that basic operations with no blocking or anything work.
TEST_F(EventTest, Basic) {
- EXPECT_FALSE(test_event.Clear());
- EXPECT_FALSE(test_event.Clear());
+ EXPECT_FALSE(test_event_.Clear());
+ EXPECT_FALSE(test_event_.Clear());
- test_event.Set();
- test_event.Wait();
- EXPECT_TRUE(test_event.Clear());
- EXPECT_FALSE(test_event.Clear());
+ test_event_.Set();
+ test_event_.Wait();
+ EXPECT_TRUE(test_event_.Clear());
+ EXPECT_FALSE(test_event_.Clear());
}
// Tests that tsan understands that events establish a happens-before
@@ -36,13 +36,13 @@
TEST_F(EventTest, ThreadSanitizer) {
for (int i = 0; i < 3000; ++i) {
int variable = 0;
- test_event.Clear();
+ test_event_.Clear();
::std::thread thread([this, &variable]() {
- test_event.Wait();
+ test_event_.Wait();
--variable;
});
++variable;
- test_event.Set();
+ test_event_.Set();
thread.join();
EXPECT_EQ(0, variable);
}
@@ -56,13 +56,33 @@
::std::thread thread([this, &start_time, &finish_time, &started]() {
start_time = time::Time::Now();
started.Set();
- test_event.Wait();
+ test_event_.Wait();
finish_time = time::Time::Now();
});
static const time::Time kWaitTime = time::Time::InSeconds(0.05);
started.Wait();
time::SleepFor(kWaitTime);
- test_event.Set();
+ test_event_.Set();
+ thread.join();
+ EXPECT_GE(finish_time - start_time, kWaitTime);
+}
+
+TEST_F(EventTest, WaitTimeout) {
+ EXPECT_FALSE(test_event_.WaitTimeout(time::Time::InSeconds(0.05)));
+
+ time::Time start_time, finish_time;
+ // Without this, it sometimes manages to fail under tsan.
+ Event started;
+ ::std::thread thread([this, &start_time, &finish_time, &started]() {
+ start_time = time::Time::Now();
+ started.Set();
+ EXPECT_TRUE(test_event_.WaitTimeout(time::Time::InSeconds(0.5)));
+ finish_time = time::Time::Now();
+ });
+ static const time::Time kWaitTime = time::Time::InSeconds(0.05);
+ started.Wait();
+ time::SleepFor(kWaitTime);
+ test_event_.Set();
thread.join();
EXPECT_GE(finish_time - start_time, kWaitTime);
}