summaryrefslogtreecommitdiffstats
path: root/mojo/public/cpp/environment
diff options
context:
space:
mode:
Diffstat (limited to 'mojo/public/cpp/environment')
-rw-r--r--mojo/public/cpp/environment/buffer_tls.h20
-rw-r--r--mojo/public/cpp/environment/default_async_waiter.h17
-rw-r--r--mojo/public/cpp/environment/environment.h24
-rw-r--r--mojo/public/cpp/environment/lib/DEPS4
-rw-r--r--mojo/public/cpp/environment/lib/buffer_tls.cc37
-rw-r--r--mojo/public/cpp/environment/lib/buffer_tls_setup.h17
-rw-r--r--mojo/public/cpp/environment/lib/default_async_waiter.cc93
-rw-r--r--mojo/public/cpp/environment/lib/environment.cc22
-rw-r--r--mojo/public/cpp/environment/tests/DEPS6
-rw-r--r--mojo/public/cpp/environment/tests/async_waiter_unittest.cc118
10 files changed, 358 insertions, 0 deletions
diff --git a/mojo/public/cpp/environment/buffer_tls.h b/mojo/public/cpp/environment/buffer_tls.h
new file mode 100644
index 0000000..42cf826
--- /dev/null
+++ b/mojo/public/cpp/environment/buffer_tls.h
@@ -0,0 +1,20 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_PUBLIC_CPP_ENVIRONMENT_BUFFER_TLS_H_
+#define MOJO_PUBLIC_CPP_ENVIRONMENT_BUFFER_TLS_H_
+
+namespace mojo {
+class Buffer;
+
+namespace internal {
+
+// Get/Set the |Buffer*| associated with current thread.
+Buffer* GetCurrentBuffer();
+Buffer* SetCurrentBuffer(Buffer* buffer);
+
+} // namespace internal
+} // namespace mojo
+
+#endif // MOJO_PUBLIC_CPP_ENVIRONMENT_BUFFER_TLS_H_
diff --git a/mojo/public/cpp/environment/default_async_waiter.h b/mojo/public/cpp/environment/default_async_waiter.h
new file mode 100644
index 0000000..d7f48bf
--- /dev/null
+++ b/mojo/public/cpp/environment/default_async_waiter.h
@@ -0,0 +1,17 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_PUBLIC_CPP_ENVIRONMENT_DEFAULT_ASYNC_WAITER_H_
+#define MOJO_PUBLIC_CPP_ENVIRONMENT_DEFAULT_ASYNC_WAITER_H_
+
+#include "mojo/public/c/system/async_waiter.h"
+
+namespace mojo {
+
+// Returns a default implementation of MojoAsyncWaiter.
+MojoAsyncWaiter* GetDefaultAsyncWaiter();
+
+} // namespace mojo
+
+#endif // MOJO_PUBLIC_CPP_ENVIRONMENT_DEFAULT_ASYNC_WAITER_H_
diff --git a/mojo/public/cpp/environment/environment.h b/mojo/public/cpp/environment/environment.h
new file mode 100644
index 0000000..f75e2f7
--- /dev/null
+++ b/mojo/public/cpp/environment/environment.h
@@ -0,0 +1,24 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_PUBLIC_CPP_ENVIRONMENT_ENVIRONMENT_H_
+#define MOJO_PUBLIC_CPP_ENVIRONMENT_ENVIRONMENT_H_
+
+#include "mojo/public/cpp/system/macros.h"
+
+namespace mojo {
+
+// This class must be instantiated before using any Mojo APIs.
+class Environment {
+ public:
+ Environment();
+ ~Environment();
+
+ private:
+ MOJO_DISALLOW_COPY_AND_ASSIGN(Environment);
+};
+
+} // namespace mojo
+
+#endif // MOJO_PUBLIC_CPP_ENVIRONMENT_ENVIRONMENT_H_
diff --git a/mojo/public/cpp/environment/lib/DEPS b/mojo/public/cpp/environment/lib/DEPS
new file mode 100644
index 0000000..1889e1f
--- /dev/null
+++ b/mojo/public/cpp/environment/lib/DEPS
@@ -0,0 +1,4 @@
+include_rules = [
+ "+mojo/public/cpp/environment",
+ "+mojo/public/cpp/utility",
+]
diff --git a/mojo/public/cpp/environment/lib/buffer_tls.cc b/mojo/public/cpp/environment/lib/buffer_tls.cc
new file mode 100644
index 0000000..d54faba
--- /dev/null
+++ b/mojo/public/cpp/environment/lib/buffer_tls.cc
@@ -0,0 +1,37 @@
+// Copyright 2014 The Chromium 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 "mojo/public/cpp/environment/buffer_tls.h"
+
+#include <assert.h>
+
+#include "mojo/public/cpp/environment/lib/buffer_tls_setup.h"
+#include "mojo/public/cpp/utility/lib/thread_local.h"
+
+namespace mojo {
+namespace internal {
+
+static ThreadLocalPointer<Buffer> current_buffer;
+
+void SetUpCurrentBuffer() {
+ current_buffer.Allocate();
+}
+
+void TearDownCurrentBuffer() {
+ assert(!current_buffer.Get());
+ current_buffer.Free();
+}
+
+Buffer* GetCurrentBuffer() {
+ return current_buffer.Get();
+}
+
+Buffer* SetCurrentBuffer(Buffer* buf) {
+ Buffer* old_buf = current_buffer.Get();
+ current_buffer.Set(buf);
+ return old_buf;
+}
+
+} // namespace internal
+} // namespace mojo
diff --git a/mojo/public/cpp/environment/lib/buffer_tls_setup.h b/mojo/public/cpp/environment/lib/buffer_tls_setup.h
new file mode 100644
index 0000000..f0ca0b1
--- /dev/null
+++ b/mojo/public/cpp/environment/lib/buffer_tls_setup.h
@@ -0,0 +1,17 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_PUBLIC_CPP_ENVIRONMENT_STANDALONE_BUFFER_TLS_SETUP_H_
+#define MOJO_PUBLIC_CPP_ENVIRONMENT_STANDALONE_BUFFER_TLS_SETUP_H_
+
+namespace mojo {
+namespace internal {
+
+void SetUpCurrentBuffer();
+void TearDownCurrentBuffer();
+
+} // namespace internal
+} // namespace mojo
+
+#endif // MOJO_PUBLIC_CPP_ENVIRONMENT_STANDALONE_BUFFER_TLS_SETUP_H_
diff --git a/mojo/public/cpp/environment/lib/default_async_waiter.cc b/mojo/public/cpp/environment/lib/default_async_waiter.cc
new file mode 100644
index 0000000..73e41de
--- /dev/null
+++ b/mojo/public/cpp/environment/lib/default_async_waiter.cc
@@ -0,0 +1,93 @@
+// Copyright 2014 The Chromium 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 "mojo/public/cpp/environment/default_async_waiter.h"
+
+#include <assert.h>
+
+#include "mojo/public/cpp/utility/run_loop.h"
+#include "mojo/public/cpp/utility/run_loop_handler.h"
+
+namespace mojo {
+namespace {
+
+// RunLoopHandler implementation used for a request to AsyncWait(). There are
+// two ways RunLoopHandlerImpl is deleted:
+// . when the handle is ready (or errored).
+// . when CancelWait() is invoked.
+class RunLoopHandlerImpl : public RunLoopHandler {
+ public:
+ RunLoopHandlerImpl(const Handle& handle,
+ MojoAsyncWaitCallback callback,
+ void* closure)
+ : handle_(handle),
+ callback_(callback),
+ closure_(closure) {
+ }
+
+ virtual ~RunLoopHandlerImpl() {
+ RunLoop::current()->RemoveHandler(handle_);
+ }
+
+ // RunLoopHandler:
+ virtual void OnHandleReady(const Handle& handle) MOJO_OVERRIDE {
+ NotifyCallback(MOJO_RESULT_OK);
+ }
+
+ virtual void OnHandleError(const Handle& handle,
+ MojoResult result) MOJO_OVERRIDE {
+ NotifyCallback(result);
+ }
+
+ private:
+ void NotifyCallback(MojoResult result) {
+ // Delete this to unregister the handle. That way if the callback
+ // reregisters everything is ok.
+ MojoAsyncWaitCallback callback = callback_;
+ void* closure = closure_;
+ delete this;
+
+ callback(closure, result);
+ }
+
+ const Handle handle_;
+ MojoAsyncWaitCallback callback_;
+ void* closure_;
+
+ MOJO_DISALLOW_COPY_AND_ASSIGN(RunLoopHandlerImpl);
+};
+
+MojoAsyncWaitID AsyncWait(MojoAsyncWaiter* waiter,
+ MojoHandle handle,
+ MojoWaitFlags flags,
+ MojoDeadline deadline,
+ MojoAsyncWaitCallback callback,
+ void* closure) {
+ RunLoop* run_loop = RunLoop::current();
+ assert(run_loop);
+
+ // |run_loop_handler| is destroyed either when the handle is ready or if
+ // CancelWait is invoked.
+ RunLoopHandlerImpl* run_loop_handler =
+ new RunLoopHandlerImpl(Handle(handle), callback, closure);
+ run_loop->AddHandler(run_loop_handler, Handle(handle), flags, deadline);
+ return reinterpret_cast<MojoAsyncWaitID>(run_loop_handler);
+}
+
+void CancelWait(MojoAsyncWaiter* waiter, MojoAsyncWaitID wait_id) {
+ delete reinterpret_cast<RunLoopHandlerImpl*>(wait_id);
+}
+
+MojoAsyncWaiter s_default_async_waiter = {
+ AsyncWait,
+ CancelWait
+};
+
+} // namespace
+
+MojoAsyncWaiter* GetDefaultAsyncWaiter() {
+ return &s_default_async_waiter;
+}
+
+} // namespace mojo
diff --git a/mojo/public/cpp/environment/lib/environment.cc b/mojo/public/cpp/environment/lib/environment.cc
new file mode 100644
index 0000000..b3148af
--- /dev/null
+++ b/mojo/public/cpp/environment/lib/environment.cc
@@ -0,0 +1,22 @@
+// Copyright 2014 The Chromium 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 "mojo/public/cpp/environment/environment.h"
+
+#include "mojo/public/cpp/environment/lib/buffer_tls_setup.h"
+#include "mojo/public/cpp/utility/run_loop.h"
+
+namespace mojo {
+
+Environment::Environment() {
+ internal::SetUpCurrentBuffer();
+ RunLoop::SetUp();
+}
+
+Environment::~Environment() {
+ RunLoop::TearDown();
+ internal::TearDownCurrentBuffer();
+}
+
+} // namespace mojo
diff --git a/mojo/public/cpp/environment/tests/DEPS b/mojo/public/cpp/environment/tests/DEPS
new file mode 100644
index 0000000..9266146
--- /dev/null
+++ b/mojo/public/cpp/environment/tests/DEPS
@@ -0,0 +1,6 @@
+include_rules = [
+ "+testing",
+ "+mojo/public/cpp/utility",
+ # TODO(vtl): Temporary until these are moved to mojo/public/cpp:
+ "+mojo/public/tests",
+]
diff --git a/mojo/public/cpp/environment/tests/async_waiter_unittest.cc b/mojo/public/cpp/environment/tests/async_waiter_unittest.cc
new file mode 100644
index 0000000..444fdef
--- /dev/null
+++ b/mojo/public/cpp/environment/tests/async_waiter_unittest.cc
@@ -0,0 +1,118 @@
+// Copyright 2014 The Chromium 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 <string>
+
+#include "mojo/public/cpp/environment/default_async_waiter.h"
+#include "mojo/public/cpp/environment/environment.h"
+#include "mojo/public/cpp/system/core.h"
+#include "mojo/public/cpp/system/macros.h"
+#include "mojo/public/cpp/utility/run_loop.h"
+#include "mojo/public/tests/test_utils.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace mojo {
+namespace {
+
+class TestAsyncWaitCallback {
+ public:
+ TestAsyncWaitCallback() : result_count_(0), last_result_(MOJO_RESULT_OK) {
+ }
+ virtual ~TestAsyncWaitCallback() {}
+
+ int result_count() const { return result_count_; }
+
+ MojoResult last_result() const { return last_result_; }
+
+ // MojoAsyncWaitCallback:
+ static void OnHandleReady(void* closure, MojoResult result) {
+ TestAsyncWaitCallback* self = static_cast<TestAsyncWaitCallback*>(closure);
+ self->result_count_++;
+ self->last_result_ = result;
+ }
+
+ private:
+ int result_count_;
+ MojoResult last_result_;
+
+ MOJO_DISALLOW_COPY_AND_ASSIGN(TestAsyncWaitCallback);
+};
+
+MojoAsyncWaitID CallAsyncWait(const Handle& handle,
+ MojoWaitFlags flags,
+ TestAsyncWaitCallback* callback) {
+ MojoAsyncWaiter* waiter = GetDefaultAsyncWaiter();
+ return waiter->AsyncWait(waiter,
+ handle.value(),
+ flags,
+ MOJO_DEADLINE_INDEFINITE,
+ &TestAsyncWaitCallback::OnHandleReady,
+ callback);
+}
+
+void CallCancelWait(MojoAsyncWaitID wait_id) {
+ MojoAsyncWaiter* waiter = GetDefaultAsyncWaiter();
+ waiter->CancelWait(waiter, wait_id);
+}
+
+class AsyncWaiterTest : public testing::Test {
+ public:
+ AsyncWaiterTest() {}
+
+ private:
+ Environment environment_;
+ RunLoop run_loop_;
+
+ MOJO_DISALLOW_COPY_AND_ASSIGN(AsyncWaiterTest);
+};
+
+// Verifies AsyncWaitCallback is notified when pipe is ready.
+TEST_F(AsyncWaiterTest, CallbackNotified) {
+ TestAsyncWaitCallback callback;
+ MessagePipe test_pipe;
+ EXPECT_TRUE(test::WriteTextMessage(test_pipe.handle1.get(), std::string()));
+
+ CallAsyncWait(test_pipe.handle0.get(),
+ MOJO_WAIT_FLAG_READABLE,
+ &callback);
+ RunLoop::current()->Run();
+ EXPECT_EQ(1, callback.result_count());
+ EXPECT_EQ(MOJO_RESULT_OK, callback.last_result());
+}
+
+// Verifies 2 AsyncWaitCallbacks are notified when there pipes are ready.
+TEST_F(AsyncWaiterTest, TwoCallbacksNotified) {
+ TestAsyncWaitCallback callback1;
+ TestAsyncWaitCallback callback2;
+ MessagePipe test_pipe1;
+ MessagePipe test_pipe2;
+ EXPECT_TRUE(test::WriteTextMessage(test_pipe1.handle1.get(), std::string()));
+ EXPECT_TRUE(test::WriteTextMessage(test_pipe2.handle1.get(), std::string()));
+
+ CallAsyncWait(test_pipe1.handle0.get(), MOJO_WAIT_FLAG_READABLE, &callback1);
+ CallAsyncWait(test_pipe2.handle0.get(), MOJO_WAIT_FLAG_READABLE, &callback2);
+
+ RunLoop::current()->Run();
+ EXPECT_EQ(1, callback1.result_count());
+ EXPECT_EQ(MOJO_RESULT_OK, callback1.last_result());
+ EXPECT_EQ(1, callback2.result_count());
+ EXPECT_EQ(MOJO_RESULT_OK, callback2.last_result());
+}
+
+// Verifies cancel works.
+TEST_F(AsyncWaiterTest, CancelCallback) {
+ TestAsyncWaitCallback callback;
+ MessagePipe test_pipe;
+ EXPECT_TRUE(test::WriteTextMessage(test_pipe.handle1.get(), std::string()));
+
+ CallCancelWait(
+ CallAsyncWait(test_pipe.handle0.get(),
+ MOJO_WAIT_FLAG_READABLE,
+ &callback));
+ RunLoop::current()->Run();
+ EXPECT_EQ(0, callback.result_count());
+}
+
+} // namespace
+} // namespace mojo