blob: d8455ee950c27d6ba991a719159c8ca8d7b3bc85 [file] [log] [blame]
// Copyright 2015 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 "ipc/mojo/async_handle_waiter.h"
#include "base/bind.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/message_loop/message_loop.h"
#include "mojo/edk/embedder/embedder.h"
namespace IPC {
namespace internal {
// The thread-safe part of |AsyncHandleWaiter|.
// As |AsyncWait()| invokes the given callback from an arbitrary thread,
// |HandleIsReady()| and the bound |this| have to be thread-safe.
class AsyncHandleWaiter::Context
: public base::RefCountedThreadSafe<AsyncHandleWaiter::Context> {
public:
Context(scoped_refptr<base::TaskRunner> runner,
base::WeakPtr<AsyncHandleWaiter> waiter)
: waiter_(waiter), runner_(runner), last_result_(MOJO_RESULT_INTERNAL) {}
void HandleIsReady(MojoResult result) {
last_result_ = result;
runner_->PostTask(FROM_HERE,
base::Bind(&Context::InvokeWaiterCallback, this));
}
private:
friend class base::RefCountedThreadSafe<Context>;
virtual ~Context() {}
// Called from |runner_| thus safe to touch |waiter_|.
void InvokeWaiterCallback() {
MojoResult result = last_result_;
last_result_ = MOJO_RESULT_INTERNAL;
if (waiter_)
waiter_->InvokeCallback(result);
}
// A weak reference. Note that |waiter_| must be touched only from the
// original thread.
const base::WeakPtr<AsyncHandleWaiter> waiter_;
const scoped_refptr<base::TaskRunner> runner_;
MojoResult last_result_;
DISALLOW_COPY_AND_ASSIGN(Context);
};
AsyncHandleWaiter::AsyncHandleWaiter(base::Callback<void(MojoResult)> callback)
: weak_factory_(this),
context_(new Context(base::MessageLoop::current()->task_runner(),
weak_factory_.GetWeakPtr())),
callback_(callback) {
}
AsyncHandleWaiter::~AsyncHandleWaiter() {
}
MojoResult AsyncHandleWaiter::Wait(MojoHandle handle,
MojoHandleSignals signals) {
return mojo::embedder::AsyncWait(
handle, signals, base::Bind(&Context::HandleIsReady, context_));
}
void AsyncHandleWaiter::InvokeCallback(MojoResult result) {
callback_.Run(result);
}
} // namespace internal
} // namespace IPC