| Index: chrome/browser/sync/weak_handle.cc
|
| diff --git a/chrome/browser/sync/weak_handle.cc b/chrome/browser/sync/weak_handle.cc
|
| index 34eaab89f6cfdf8a9c4bb97c79ef174fedb64e52..1c78307f9fab45f584cbe1264932c4cca8a99d2c 100644
|
| --- a/chrome/browser/sync/weak_handle.cc
|
| +++ b/chrome/browser/sync/weak_handle.cc
|
| @@ -4,24 +4,100 @@
|
|
|
| #include "chrome/browser/sync/weak_handle.h"
|
|
|
| +#include <sstream>
|
| +
|
| +#include "base/message_loop_proxy.h"
|
| +#include "base/tracked.h"
|
| +
|
| namespace browser_sync {
|
|
|
| namespace internal {
|
|
|
| WeakHandleCoreBase::WeakHandleCoreBase()
|
| - : message_loop_proxy_(
|
| - base::MessageLoopProxy::CreateForCurrentThread()) {}
|
| -
|
| -WeakHandleCoreBase::~WeakHandleCoreBase() {}
|
| + : owner_loop_(MessageLoop::current()),
|
| + owner_loop_proxy_(base::MessageLoopProxy::CreateForCurrentThread()),
|
| + destroyed_on_owner_thread_(false) {
|
| + owner_loop_->AddDestructionObserver(this);
|
| +}
|
|
|
| bool WeakHandleCoreBase::IsOnOwnerThread() const {
|
| - return message_loop_proxy_->BelongsToCurrentThread();
|
| + // We can't use |owner_loop_proxy_->BelongsToCurrentThread()| as
|
| + // it may not work from within a MessageLoop::DestructionObserver
|
| + // callback.
|
| + return MessageLoop::current() == owner_loop_;
|
| +}
|
| +
|
| +void WeakHandleCoreBase::WillDestroyCurrentMessageLoop() {
|
| + CHECK(IsOnOwnerThread());
|
| + CHECK(!destroyed_on_owner_thread_);
|
| + // NOTE: This function dispatches to
|
| + // WeakHandle<T>::CleanupOnOwnerThread() (i.e., not just
|
| + // WeakHandleCoreBase::CleanupOnOwnerThread() is run).
|
| + CleanupOnOwnerThread();
|
| + CHECK(destroyed_on_owner_thread_);
|
| +}
|
| +
|
| +WeakHandleCoreBase::~WeakHandleCoreBase() {
|
| + // It is safe to read |destroyed_on_owner_thread_| here even if
|
| + // we're not on the owner thread (see comments on
|
| + // base::AtomicRefCountDecN()).
|
| + CHECK(destroyed_on_owner_thread_);
|
| +}
|
| +
|
| +void WeakHandleCoreBase::CleanupOnOwnerThread() {
|
| + CHECK(IsOnOwnerThread());
|
| + CHECK(!destroyed_on_owner_thread_);
|
| + owner_loop_->RemoveDestructionObserver(this);
|
| + destroyed_on_owner_thread_ = true;
|
| }
|
|
|
| -void WeakHandleCoreBase::PostOnOwnerThread(
|
| +namespace {
|
| +
|
| +// TODO(akalin): Merge with similar function in
|
| +// js_transaction_observer.cc.
|
| +std::string GetLocationString(const tracked_objects::Location& location) {
|
| + std::ostringstream oss;
|
| + oss << location.function_name() << "@"
|
| + << location.file_name() << ":" << location.line_number();
|
| + return oss.str();
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +void WeakHandleCoreBase::PostToOwnerThread(
|
| const tracked_objects::Location& from_here,
|
| const base::Closure& fn) const {
|
| - ignore_result(message_loop_proxy_->PostTask(from_here, fn));
|
| + if (!owner_loop_proxy_->PostTask(from_here, fn)) {
|
| + VLOG(1) << "Could not post task from " << GetLocationString(from_here);
|
| + }
|
| +}
|
| +
|
| +void WeakHandleCoreBase::Destroy() {
|
| + if (IsOnOwnerThread()) {
|
| + CHECK(!destroyed_on_owner_thread_);
|
| + CleanupAndDestroyOnOwnerThread();
|
| + } else if (!owner_loop_proxy_->PostTask(
|
| + FROM_HERE,
|
| + base::Bind(&WeakHandleCoreBase::CleanupAndDestroyOnOwnerThread,
|
| + base::Unretained(this)))) {
|
| + // If the post fails, that means that the owner loop is gone and
|
| + // therefore CleanupOnOwnerThread() should have already been
|
| + // called via WillDestroyCurrentMessageLoop(). Therefore, the
|
| + // only thing left is to self-destruct.
|
| + delete this;
|
| + }
|
| +}
|
| +
|
| +void WeakHandleCoreBase::CleanupAndDestroyOnOwnerThread() {
|
| + CHECK(IsOnOwnerThread());
|
| + CHECK(!destroyed_on_owner_thread_);
|
| + CleanupOnOwnerThread();
|
| + CHECK(destroyed_on_owner_thread_);
|
| + delete this;
|
| +}
|
| +
|
| +void WeakHandleCoreBaseTraits::Destruct(const WeakHandleCoreBase* core_base) {
|
| + const_cast<WeakHandleCoreBase*>(core_base)->Destroy();
|
| }
|
|
|
| } // namespace internal
|
|
|