one_shot_event.cc revision 868fa2fe829687343ffae624259930155e16dbd8
190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// found in the LICENSE file.
490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "extensions/common/one_shot_event.h"
690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/callback.h"
890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/location.h"
990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/message_loop/message_loop_proxy.h"
1090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/task_runner.h"
1190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)using base::TaskRunner;
1390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)namespace extensions {
1590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)struct OneShotEvent::TaskInfo {
1790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  TaskInfo() {}
1890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  TaskInfo(const tracked_objects::Location& from_here,
1990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)           const scoped_refptr<TaskRunner>& runner,
2090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)           const base::Closure& task)
2190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      : from_here(from_here), runner(runner), task(task) {
22868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    CHECK(runner.get());  // Detect mistakes with a decent stack frame.
2390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
2490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  tracked_objects::Location from_here;
2590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_refptr<TaskRunner> runner;
2690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::Closure task;
2790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)};
2890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
2990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)OneShotEvent::OneShotEvent() : signaled_(false) {
3090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // It's acceptable to construct the OneShotEvent on one thread, but
3190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // immediately move it to another thread.
3290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  thread_checker_.DetachFromThread();
3390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
3490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)OneShotEvent::~OneShotEvent() {}
3590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
3690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void OneShotEvent::Post(const tracked_objects::Location& from_here,
3790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                        const base::Closure& task) const {
3890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  Post(from_here, task, base::MessageLoopProxy::current());
3990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
4090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
4190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void OneShotEvent::Post(const tracked_objects::Location& from_here,
4290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                        const base::Closure& task,
4390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                        const scoped_refptr<TaskRunner>& runner) const {
4490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
4590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
4690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (is_signaled()) {
4790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    runner->PostTask(from_here, task);
4890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  } else {
4990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    tasks_.push_back(TaskInfo(from_here, runner, task));
5090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
5190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
5290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
5390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void OneShotEvent::Signal() {
5490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
5590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
5690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  CHECK(!signaled_) << "Only call Signal once.";
5790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
5890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  signaled_ = true;
5990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // After this point, a call to Post() from one of the queued tasks
6090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // could proceed immediately, but the fact that this object is
6190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // single-threaded prevents that from being relevant.
6290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
6390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // We could randomize tasks_ in debug mode in order to check that
6490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // the order doesn't matter...
6590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  for (size_t i = 0; i < tasks_.size(); ++i) {
6690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    tasks_[i].runner->PostTask(tasks_[i].from_here, tasks_[i].task);
6790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
6890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
6990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
7090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}  // namespace extensions
71