[fbl] Add wrapper around Condition Variable
Test: utest/fbl/condition_variable_tests.cpp
Change-Id: I63be83d4935f7d8a19ec15e0c6298d1a5e425665
diff --git a/system/ulib/fbl/include/fbl/condition_variable.h b/system/ulib/fbl/include/fbl/condition_variable.h
new file mode 100644
index 0000000..21eab06
--- /dev/null
+++ b/system/ulib/fbl/include/fbl/condition_variable.h
@@ -0,0 +1,50 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#pragma once
+
+#ifdef __cplusplus
+
+// ConditionVariable is a C++ helper class intended to wrap a condition variable synchronization
+// primitive. It is also responsible for automatically initializing and destroying the internal
+// object.
+//
+// This object is currently only supported in userspace.
+#ifndef _KERNEL
+
+#include <threads.h>
+
+#include <fbl/macros.h>
+#include <fbl/mutex.h>
+#include <zircon/compiler.h>
+#include <zircon/types.h>
+
+namespace fbl {
+
+class ConditionVariable {
+public:
+ ConditionVariable() { cnd_init(&cond_); }
+ ~ConditionVariable() { cnd_destroy(&cond_); }
+ DISALLOW_COPY_ASSIGN_AND_MOVE(ConditionVariable);
+
+ void Wait(Mutex* mutex) __TA_REQUIRES(mutex) {
+ cnd_wait(&cond_, mutex->GetInternal());
+ }
+
+ void Signal() {
+ cnd_signal(&cond_);
+ }
+
+ void Broadcast() {
+ cnd_broadcast(&cond_);
+ }
+
+private:
+ cnd_t cond_;
+};
+
+}
+
+#endif // ifndef _KERNEL
+#endif // ifdef __cplusplus
diff --git a/system/utest/fbl/condition_variable_tests.cpp b/system/utest/fbl/condition_variable_tests.cpp
new file mode 100644
index 0000000..c933664
--- /dev/null
+++ b/system/utest/fbl/condition_variable_tests.cpp
@@ -0,0 +1,53 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <fbl/auto_lock.h>
+#include <fbl/condition_variable.h>
+#include <fbl/mutex.h>
+#include <unittest/unittest.h>
+
+namespace fbl {
+namespace {
+
+bool EmptySignalTest() {
+ BEGIN_TEST;
+
+ ConditionVariable cvar;
+ cvar.Signal();
+ cvar.Broadcast();
+
+ END_TEST;
+}
+
+bool WaitTest() {
+ BEGIN_TEST;
+
+ struct State {
+ Mutex mutex;
+ ConditionVariable cvar;
+ } state;
+
+ thrd_t thread;
+ AutoLock lock(&state.mutex);
+
+ thrd_create(&thread, [](void* arg) {
+ auto state = reinterpret_cast<State*>(arg);
+ AutoLock lock(&state->mutex);
+ state->cvar.Signal();
+ return 0;
+ }, &state);
+
+ state.cvar.Wait(&state.mutex);
+ thrd_join(thread, NULL);
+
+ END_TEST;
+}
+
+} // namespace
+} // namespace fbl
+
+BEGIN_TEST_CASE(ConditionVariableTests)
+RUN_TEST(fbl::EmptySignalTest)
+RUN_TEST(fbl::WaitTest)
+END_TEST_CASE(ConditionVariableTests);
diff --git a/system/utest/fbl/rules.mk b/system/utest/fbl/rules.mk
index 4fc4e89..2fac772 100644
--- a/system/utest/fbl/rules.mk
+++ b/system/utest/fbl/rules.mk
@@ -50,6 +50,7 @@
# See: TODO(ZX-1053)
#
fbl_device_tests += \
+ $(LOCAL_DIR)/condition_variable_tests.cpp \
$(LOCAL_DIR)/ref_counted_tests.cpp \
$(LOCAL_DIR)/ref_counted_upgradeable_tests.cpp \
$(LOCAL_DIR)/slab_allocator_tests.cpp \