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" 8e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "base/lazy_instance.h" 990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/location.h" 1090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/message_loop/message_loop_proxy.h" 1190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/task_runner.h" 12e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "base/time/time.h" 1390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 1490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)using base::TaskRunner; 1590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 1690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)namespace extensions { 1790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 1890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)struct OneShotEvent::TaskInfo { 1990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) TaskInfo() {} 2090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) TaskInfo(const tracked_objects::Location& from_here, 2190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const scoped_refptr<TaskRunner>& runner, 22e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch const base::Closure& task, 23e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch const base::TimeDelta& delay) 24e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch : from_here(from_here), runner(runner), task(task), delay(delay) { 25868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) CHECK(runner.get()); // Detect mistakes with a decent stack frame. 2690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 2790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) tracked_objects::Location from_here; 2890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) scoped_refptr<TaskRunner> runner; 2990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::Closure task; 30e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch base::TimeDelta delay; 3190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}; 3290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 3390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)OneShotEvent::OneShotEvent() : signaled_(false) { 3490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // It's acceptable to construct the OneShotEvent on one thread, but 3590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // immediately move it to another thread. 3690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) thread_checker_.DetachFromThread(); 3790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)OneShotEvent::OneShotEvent(bool signaled) : signaled_(signaled) { 395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) thread_checker_.DetachFromThread(); 405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 4190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)OneShotEvent::~OneShotEvent() {} 4290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 4390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void OneShotEvent::Post(const tracked_objects::Location& from_here, 4490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const base::Closure& task) const { 45e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch PostImpl( 46e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch from_here, task, base::MessageLoopProxy::current(), base::TimeDelta()); 4790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 4890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 4990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void OneShotEvent::Post(const tracked_objects::Location& from_here, 5090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const base::Closure& task, 5190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const scoped_refptr<TaskRunner>& runner) const { 52e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch PostImpl(from_here, task, runner, base::TimeDelta()); 53e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch} 5490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 55e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochvoid OneShotEvent::PostDelayed(const tracked_objects::Location& from_here, 56e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch const base::Closure& task, 57e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch const base::TimeDelta& delay) const { 58e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch PostImpl(from_here, task, base::MessageLoopProxy::current(), delay); 5990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 6090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 6190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void OneShotEvent::Signal() { 6290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 6390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 6490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) CHECK(!signaled_) << "Only call Signal once."; 6590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 6690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) signaled_ = true; 6790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // After this point, a call to Post() from one of the queued tasks 6890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // could proceed immediately, but the fact that this object is 6990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // single-threaded prevents that from being relevant. 7090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 7190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // We could randomize tasks_ in debug mode in order to check that 7290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // the order doesn't matter... 7390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) for (size_t i = 0; i < tasks_.size(); ++i) { 74e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch const TaskInfo& task = tasks_[i]; 75e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch if (task.delay != base::TimeDelta()) 76e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch task.runner->PostDelayedTask(task.from_here, task.task, task.delay); 77e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch else 78e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch task.runner->PostTask(task.from_here, task.task); 79e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch } 80e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch} 81e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 82e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochvoid OneShotEvent::PostImpl(const tracked_objects::Location& from_here, 83e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch const base::Closure& task, 84e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch const scoped_refptr<TaskRunner>& runner, 85e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch const base::TimeDelta& delay) const { 86e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch DCHECK(thread_checker_.CalledOnValidThread()); 87e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 88e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch if (is_signaled()) { 89e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch if (delay != base::TimeDelta()) 90e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch runner->PostDelayedTask(from_here, task, delay); 91e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch else 92e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch runner->PostTask(from_here, task); 93e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch } else { 94e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch tasks_.push_back(TaskInfo(from_here, runner, task, delay)); 9590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 9690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 9790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 9890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} // namespace extensions 99