Commit 0a4310ff authored by darin@chromium.org's avatar darin@chromium.org

Mojo: re-org public/utility and public/environment

The plan:
- mojo/public/{subdir} contains public headers and scripts (if any).
- mojo/public/{subdir}/lib contains private headers and .cc files (if any).
- mojo/public/{subdir}/tests contains test files.

Also, as part of this CL:

1- I simplified the TLS implementation in utility and hid it as an internal API. I'm not happy providing the API to third-parties as is. It was really intended to be used with LazyInstance, etc. Without that there is some subtlety with setup and teardown of the TLS slot. Hiding it avoids having to deal with this for now.

2- Deleted thread_local_unittest.cc as that was still coded against base/threading/thread_local.h (oops)! Besides that this test has a large dependency on base threading and synchronization primitives. It also isn't that useful to test our wrappers for TLS as they are such thin wrappers around the OS provided APIs.

3- Renamed environment/standalone to environment/lib for consistency. From the point of view of a third-party, lib is the better name for this directory.

Review URL: https://codereview.chromium.org/148013006

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@247927 0039d316-1c4b-4281-b951-d872f2087c98
parent a2c724ab
......@@ -105,7 +105,7 @@
'mojo_utility',
],
'sources': [
'public/tests/environment/async_waiter_unittest.cc',
'public/environment/tests/async_waiter_unittest.cc',
],
},
{
......@@ -138,8 +138,7 @@
'mojo_utility',
],
'sources': [
'public/tests/utility/run_loop_unittest.cc',
'public/tests/utility/thread_local_unittest.cc',
'public/utility/tests/run_loop_unittest.cc',
],
},
{
......@@ -206,13 +205,13 @@
'target_name': 'mojo_environment_standalone',
'type': 'static_library',
'sources': [
'public/environment/default_async_waiter.h',
'public/environment/buffer_tls.h',
'public/environment/default_async_waiter.h',
'public/environment/environment.h',
'public/environment/standalone/default_async_waiter.cc',
'public/environment/standalone/buffer_tls.cc',
'public/environment/standalone/buffer_tls_setup.h',
'public/environment/standalone/environment.cc',
'public/environment/lib/default_async_waiter.cc',
'public/environment/lib/buffer_tls.cc',
'public/environment/lib/buffer_tls_setup.h',
'public/environment/lib/environment.cc',
],
'include_dirs': [
'..',
......@@ -222,12 +221,12 @@
'target_name': 'mojo_utility',
'type': 'static_library',
'sources': [
'public/utility/run_loop.cc',
'public/utility/lib/run_loop.cc',
'public/utility/lib/thread_local.h',
'public/utility/lib/thread_local_posix.cc',
'public/utility/lib/thread_local_win.cc',
'public/utility/run_loop.h',
'public/utility/run_loop_handler.h',
'public/utility/thread_local.h',
'public/utility/thread_local_posix.cc',
'public/utility/thread_local_win.cc',
],
'include_dirs': [
'..',
......
......@@ -4,29 +4,32 @@
#include "mojo/public/environment/buffer_tls.h"
#include "mojo/public/environment/standalone/buffer_tls_setup.h"
#include "mojo/public/utility/thread_local.h"
#include <assert.h>
#include "mojo/public/environment/lib/buffer_tls_setup.h"
#include "mojo/public/utility/lib/thread_local.h"
namespace mojo {
namespace internal {
static ThreadLocalPlatform::SlotType s_slot;
static ThreadLocalPointer<Buffer> current_buffer;
void SetUpCurrentBuffer() {
ThreadLocalPlatform::AllocateSlot(&s_slot);
current_buffer.Allocate();
}
void TearDownCurrentBuffer() {
ThreadLocalPlatform::FreeSlot(s_slot);
assert(!current_buffer.Get());
current_buffer.Free();
}
Buffer* GetCurrentBuffer() {
return static_cast<Buffer*>(ThreadLocalPlatform::GetValueFromSlot(s_slot));
return current_buffer.Get();
}
Buffer* SetCurrentBuffer(Buffer* buf) {
Buffer* old_buf = GetCurrentBuffer();
ThreadLocalPlatform::SetValueInSlot(s_slot, buf);
Buffer* old_buf = current_buffer.Get();
current_buffer.Set(buf);
return old_buf;
}
......
......@@ -4,7 +4,7 @@
#include "mojo/public/environment/environment.h"
#include "mojo/public/environment/standalone/buffer_tls_setup.h"
#include "mojo/public/environment/lib/buffer_tls_setup.h"
#include "mojo/public/utility/run_loop.h"
namespace mojo {
......
// Copyright 2013 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 "base/threading/thread_local.h"
#include "base/logging.h"
#include "base/synchronization/waitable_event.h"
#include "base/threading/simple_thread.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace base {
namespace {
class ThreadLocalTesterBase : public base::DelegateSimpleThreadPool::Delegate {
public:
typedef base::ThreadLocalPointer<ThreadLocalTesterBase> TLPType;
ThreadLocalTesterBase(TLPType* tlp, base::WaitableEvent* done)
: tlp_(tlp),
done_(done) {
}
virtual ~ThreadLocalTesterBase() {}
protected:
TLPType* tlp_;
base::WaitableEvent* done_;
};
class SetThreadLocal : public ThreadLocalTesterBase {
public:
SetThreadLocal(TLPType* tlp, base::WaitableEvent* done)
: ThreadLocalTesterBase(tlp, done),
val_(NULL) {
}
virtual ~SetThreadLocal() {}
void set_value(ThreadLocalTesterBase* val) { val_ = val; }
virtual void Run() OVERRIDE {
DCHECK(!done_->IsSignaled());
tlp_->Set(val_);
done_->Signal();
}
private:
ThreadLocalTesterBase* val_;
};
class GetThreadLocal : public ThreadLocalTesterBase {
public:
GetThreadLocal(TLPType* tlp, base::WaitableEvent* done)
: ThreadLocalTesterBase(tlp, done),
ptr_(NULL) {
}
virtual ~GetThreadLocal() {}
void set_ptr(ThreadLocalTesterBase** ptr) { ptr_ = ptr; }
virtual void Run() OVERRIDE {
DCHECK(!done_->IsSignaled());
*ptr_ = tlp_->Get();
done_->Signal();
}
private:
ThreadLocalTesterBase** ptr_;
};
} // namespace
// In this test, we start 2 threads which will access a ThreadLocalPointer. We
// make sure the default is NULL, and the pointers are unique to the threads.
TEST(ThreadLocalTest, Pointer) {
base::DelegateSimpleThreadPool tp1("ThreadLocalTest tp1", 1);
base::DelegateSimpleThreadPool tp2("ThreadLocalTest tp1", 1);
tp1.Start();
tp2.Start();
base::ThreadLocalPointer<ThreadLocalTesterBase> tlp;
static ThreadLocalTesterBase* const kBogusPointer =
reinterpret_cast<ThreadLocalTesterBase*>(0x1234);
ThreadLocalTesterBase* tls_val;
base::WaitableEvent done(true, false);
GetThreadLocal getter(&tlp, &done);
getter.set_ptr(&tls_val);
// Check that both threads defaulted to NULL.
tls_val = kBogusPointer;
done.Reset();
tp1.AddWork(&getter);
done.Wait();
EXPECT_EQ(static_cast<ThreadLocalTesterBase*>(NULL), tls_val);
tls_val = kBogusPointer;
done.Reset();
tp2.AddWork(&getter);
done.Wait();
EXPECT_EQ(static_cast<ThreadLocalTesterBase*>(NULL), tls_val);
SetThreadLocal setter(&tlp, &done);
setter.set_value(kBogusPointer);
// Have thread 1 set their pointer value to kBogusPointer.
done.Reset();
tp1.AddWork(&setter);
done.Wait();
tls_val = NULL;
done.Reset();
tp1.AddWork(&getter);
done.Wait();
EXPECT_EQ(kBogusPointer, tls_val);
// Make sure thread 2 is still NULL
tls_val = kBogusPointer;
done.Reset();
tp2.AddWork(&getter);
done.Wait();
EXPECT_EQ(static_cast<ThreadLocalTesterBase*>(NULL), tls_val);
// Set thread 2 to kBogusPointer + 1.
setter.set_value(kBogusPointer + 1);
done.Reset();
tp2.AddWork(&setter);
done.Wait();
tls_val = NULL;
done.Reset();
tp2.AddWork(&getter);
done.Wait();
EXPECT_EQ(kBogusPointer + 1, tls_val);
// Make sure thread 1 is still kBogusPointer.
tls_val = NULL;
done.Reset();
tp1.AddWork(&getter);
done.Wait();
EXPECT_EQ(kBogusPointer, tls_val);
tp1.JoinAll();
tp2.JoinAll();
}
TEST(ThreadLocalTest, Boolean) {
{
base::ThreadLocalBoolean tlb;
EXPECT_FALSE(tlb.Get());
tlb.Set(false);
EXPECT_FALSE(tlb.Get());
tlb.Set(true);
EXPECT_TRUE(tlb.Get());
}
// Our slot should have been freed, we're all reset.
{
base::ThreadLocalBoolean tlb;
EXPECT_FALSE(tlb.Get());
}
}
} // namespace base
// Copyright 2013 The Chromium Authors. All rights reserved.
// 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.
......@@ -9,13 +9,13 @@
#include <algorithm>
#include <vector>
#include "mojo/public/utility/lib/thread_local.h"
#include "mojo/public/utility/run_loop_handler.h"
#include "mojo/public/utility/thread_local.h"
namespace mojo {
namespace {
ThreadLocalPointer<RunLoop>* tls_run_loop = NULL;
internal::ThreadLocalPointer<RunLoop> current_run_loop;
const MojoTimeTicks kInvalidTimeTicks = static_cast<MojoTimeTicks>(0);
......@@ -37,34 +37,29 @@ struct RunLoop::RunState {
};
RunLoop::RunLoop() : run_state_(NULL), next_handler_id_(0) {
assert(tls_run_loop);
assert(!tls_run_loop->Get());
tls_run_loop->Set(this);
assert(!current());
current_run_loop.Set(this);
}
RunLoop::~RunLoop() {
assert(tls_run_loop->Get() == this);
tls_run_loop->Set(NULL);
assert(current() == this);
current_run_loop.Set(NULL);
}
// static
void RunLoop::SetUp() {
assert(!tls_run_loop);
tls_run_loop = new ThreadLocalPointer<RunLoop>;
current_run_loop.Allocate();
}
// static
void RunLoop::TearDown() {
assert(!current());
assert(tls_run_loop);
delete tls_run_loop;
tls_run_loop = NULL;
current_run_loop.Free();
}
// static
RunLoop* RunLoop::current() {
assert(tls_run_loop);
return tls_run_loop->Get();
return current_run_loop.Get();
}
void RunLoop::AddHandler(RunLoopHandler* handler,
......
// 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_UTILITY_LIB_THREAD_LOCAL_H_
#define MOJO_PUBLIC_UTILITY_LIB_THREAD_LOCAL_H_
#ifndef _WIN32
#include <pthread.h>
#endif
#include "mojo/public/system/macros.h"
namespace mojo {
namespace internal {
// Helper functions that abstract the cross-platform APIs.
struct ThreadLocalPlatform {
#ifdef _WIN32
typedef unsigned long SlotType;
#else
typedef pthread_key_t SlotType;
#endif
static void AllocateSlot(SlotType* slot);
static void FreeSlot(SlotType slot);
static void* GetValueFromSlot(SlotType slot);
static void SetValueInSlot(SlotType slot, void* value);
};
// This class is intended to be statically allocated.
template <typename P>
class ThreadLocalPointer {
public:
ThreadLocalPointer() : slot_() {
}
void Allocate() {
ThreadLocalPlatform::AllocateSlot(&slot_);
}
void Free() {
ThreadLocalPlatform::FreeSlot(slot_);
}
P* Get() {
return static_cast<P*>(ThreadLocalPlatform::GetValueFromSlot(slot_));
}
void Set(P* value) {
ThreadLocalPlatform::SetValueInSlot(slot_, value);
}
private:
ThreadLocalPlatform::SlotType slot_;
};
} // namespace internal
} // namespace mojo
#endif // MOJO_PUBLIC_UTILITY_LIB_THREAD_LOCAL_H_
// Copyright 2013 The Chromium Authors. All rights reserved.
// 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/utility/thread_local.h"
#include "mojo/public/utility/lib/thread_local.h"
#include <assert.h>
#include <pthread.h>
namespace mojo {
namespace internal {
......
// Copyright 2013 The Chromium Authors. All rights reserved.
// 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/utility/thread_local.h"
#include "mojo/public/utility/lib/thread_local.h"
#include <assert.h>
#include <windows.h>
......
// Copyright 2013 The Chromium Authors. All rights reserved.
// 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/utility/run_loop.h"
#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "mojo/public/system/core_cpp.h"
#include "mojo/public/tests/test_support.h"
#include "mojo/public/utility/run_loop_handler.h"
......@@ -32,10 +30,11 @@ class TestRunLoopHandler : public RunLoopHandler {
MojoResult last_error_result() const { return last_error_result_; }
// RunLoopHandler:
virtual void OnHandleReady(const Handle& handle) OVERRIDE {
virtual void OnHandleReady(const Handle& handle) MOJO_OVERRIDE {
ready_count_++;
}
virtual void OnHandleError(const Handle& handle, MojoResult result) OVERRIDE {
virtual void OnHandleError(const Handle& handle, MojoResult result)
MOJO_OVERRIDE {
error_count_++;
last_error_result_ = result;
}
......@@ -45,24 +44,24 @@ class TestRunLoopHandler : public RunLoopHandler {
int error_count_;
MojoResult last_error_result_;
DISALLOW_COPY_AND_ASSIGN(TestRunLoopHandler);
MOJO_DISALLOW_COPY_AND_ASSIGN(TestRunLoopHandler);
};
class RunLoopTest : public testing::Test {
public:
RunLoopTest() {}
virtual void SetUp() OVERRIDE {
virtual void SetUp() MOJO_OVERRIDE {
Test::SetUp();
RunLoop::SetUp();
}
virtual void TearDown() OVERRIDE {
virtual void TearDown() MOJO_OVERRIDE {
RunLoop::TearDown();
Test::TearDown();
}
private:
DISALLOW_COPY_AND_ASSIGN(RunLoopTest);
MOJO_DISALLOW_COPY_AND_ASSIGN(RunLoopTest);
};
// Trivial test to verify Run() with no added handles returns.
......@@ -80,7 +79,7 @@ class RemoveOnReadyRunLoopHandler : public TestRunLoopHandler {
void set_run_loop(RunLoop* run_loop) { run_loop_ = run_loop; }
// RunLoopHandler:
virtual void OnHandleReady(const Handle& handle) OVERRIDE {
virtual void OnHandleReady(const Handle& handle) MOJO_OVERRIDE {
run_loop_->RemoveHandler(handle);
TestRunLoopHandler::OnHandleReady(handle);
}
......@@ -88,7 +87,7 @@ class RemoveOnReadyRunLoopHandler : public TestRunLoopHandler {
private:
RunLoop* run_loop_;
DISALLOW_COPY_AND_ASSIGN(RemoveOnReadyRunLoopHandler);
MOJO_DISALLOW_COPY_AND_ASSIGN(RemoveOnReadyRunLoopHandler);
};
// Verifies RunLoop quits when no more handles (handle is removed when ready).
......@@ -116,7 +115,7 @@ class QuitOnReadyRunLoopHandler : public TestRunLoopHandler {
void set_run_loop(RunLoop* run_loop) { run_loop_ = run_loop; }
// RunLoopHandler:
virtual void OnHandleReady(const Handle& handle) OVERRIDE {
virtual void OnHandleReady(const Handle& handle) MOJO_OVERRIDE {
run_loop_->Quit();
TestRunLoopHandler::OnHandleReady(handle);
}
......@@ -124,7 +123,7 @@ class QuitOnReadyRunLoopHandler : public TestRunLoopHandler {
private:
RunLoop* run_loop_;
DISALLOW_COPY_AND_ASSIGN(QuitOnReadyRunLoopHandler);
MOJO_DISALLOW_COPY_AND_ASSIGN(QuitOnReadyRunLoopHandler);
};
// Verifies Quit() from OnHandleReady() quits the loop.
......@@ -152,7 +151,8 @@ class QuitOnErrorRunLoopHandler : public TestRunLoopHandler {
void set_run_loop(RunLoop* run_loop) { run_loop_ = run_loop; }
// RunLoopHandler:
virtual void OnHandleError(const Handle& handle, MojoResult result) OVERRIDE {
virtual void OnHandleError(const Handle& handle, MojoResult result)
MOJO_OVERRIDE {
run_loop_->Quit();
TestRunLoopHandler::OnHandleError(handle, result);
}
......@@ -160,7 +160,7 @@ class QuitOnErrorRunLoopHandler : public TestRunLoopHandler {
private:
RunLoop* run_loop_;
DISALLOW_COPY_AND_ASSIGN(QuitOnErrorRunLoopHandler);
MOJO_DISALLOW_COPY_AND_ASSIGN(QuitOnErrorRunLoopHandler);
};
// Verifies Quit() when the deadline is reached works.
......
// Copyright 2013 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.
// WARNING: Thread local storage is a bit tricky to get right. Please make
// sure that this is really the proper solution for what you're trying to
// achieve. Don't prematurely optimize, most likely you can just use a Lock.
//
// These classes implement a wrapper around the platform's TLS storage
// mechanism. On construction, they will allocate a TLS slot, and free the
// TLS slot on destruction. No memory management (creation or destruction) is
// handled. This means for uses of ThreadLocalPointer, you must correctly
// manage the memory yourself, these classes will not destroy the pointer for
// you. There are no at-thread-exit actions taken by these classes.
//
// ThreadLocalPointer<Type> wraps a Type*. It performs no creation or
// destruction, so memory management must be handled elsewhere. The first call
// to Get() on a thread will return NULL. You can update the pointer with a
// call to Set().
//
// ThreadLocalBoolean wraps a bool. It will default to false if it has never
// been set otherwise with Set().
//
// Thread Safety: An instance of ThreadLocalStorage is completely thread safe
// once it has been created. If you want to dynamically create an instance,
// you must of course properly deal with safety and race conditions. This
// means a function-level static initializer is generally inappropiate.
//
// Example usage:
// // My class is logically attached to a single thread. We cache a pointer
// // on the thread it was created on, so we can implement current().
// MyClass::MyClass() {
// DCHECK(Singleton<ThreadLocalPointer<MyClass> >::get()->Get() == NULL);
// Singleton<ThreadLocalPointer<MyClass> >::get()->Set(this);
// }
//
// MyClass::~MyClass() {
// DCHECK(Singleton<ThreadLocalPointer<MyClass> >::get()->Get() != NULL);
// Singleton<ThreadLocalPointer<MyClass> >::get()->Set(NULL);
// }
//
// // Return the current MyClass associated with the calling thread, can be
// // NULL if there isn't a MyClass associated.
// MyClass* MyClass::current() {
// return Singleton<ThreadLocalPointer<MyClass> >::get()->Get();
// }
#ifndef MOJO_PUBLIC_UTILITY_THREAD_LOCAL_H_
#define MOJO_PUBLIC_UTILITY_THREAD_LOCAL_H_
#ifndef _WIN32
#include <pthread.h>
#endif
#include "mojo/public/system/macros.h"
namespace mojo {
namespace internal {
// Helper functions that abstract the cross-platform APIs. Do not use directly.
struct ThreadLocalPlatform {
#ifdef _WIN32
typedef unsigned long SlotType;
#else
typedef pthread_key_t SlotType;
#endif
static void AllocateSlot(SlotType* slot);
static void FreeSlot(SlotType slot);
static void* GetValueFromSlot(SlotType slot);
static void SetValueInSlot(SlotType slot, void* value);
};
} // namespace internal
template <typename Type>
class ThreadLocalPointer {
public:
ThreadLocalPointer() : slot_() {
internal::ThreadLocalPlatform::AllocateSlot(&slot_);
}
~ThreadLocalPointer() {
internal::ThreadLocalPlatform::FreeSlot(slot_);
}
Type* Get() {
return static_cast<Type*>(
internal::ThreadLocalPlatform::GetValueFromSlot(slot_));
}
void Set(Type* ptr) {
internal::ThreadLocalPlatform::SetValueInSlot(
slot_, const_cast<void*>(static_cast<const void*>(ptr)));
}
private:
typedef internal::ThreadLocalPlatform::SlotType SlotType;
SlotType slot_;
MOJO_DISALLOW_COPY_AND_ASSIGN(ThreadLocalPointer<Type>);
};
class ThreadLocalBoolean {
public:
ThreadLocalBoolean() {}
~ThreadLocalBoolean() {}
bool Get() {
return tlp_.Get() != NULL;
}
void Set(bool val) {
tlp_.Set(val ? this : NULL);
}
private:
ThreadLocalPointer<void> tlp_;
MOJO_DISALLOW_COPY_AND_ASSIGN(ThreadLocalBoolean);
};
} // namespace mojo
#endif // MOJO_PUBLIC_UTILITY_THREAD_LOCAL_H_
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment