1b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Use of this source code is governed by a BSD-style license that can be 3b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// found in the LICENSE file. 4b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 5b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/mac/libdispatch_task_runner.h" 6b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 7cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko#include <stdint.h> 8cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko 9b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/callback.h" 10b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 11b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratnamespace base { 12b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratnamespace mac { 13b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 14b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratLibDispatchTaskRunner::LibDispatchTaskRunner(const char* name) 15b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat : queue_(dispatch_queue_create(name, NULL)), 16b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat queue_finalized_(false, false) { 17b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat dispatch_set_context(queue_, this); 18b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat dispatch_set_finalizer_f(queue_, &LibDispatchTaskRunner::Finalizer); 19b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 20b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 21b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratbool LibDispatchTaskRunner::PostDelayedTask( 223bf7081cf806cd9ebedb47b3eff76671794efa68Christopher Wiley const tracked_objects::Location& /* from_here */, 23b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat const Closure& task, 24b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat base::TimeDelta delay) { 25b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (!queue_) 26b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return false; 27b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 28b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // The block runtime would implicitly copy the reference, not the object 29b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // it's referencing. Copy the closure into block storage so it's available 30b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // to run. 31b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat __block const Closure task_copy = task; 32b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat void(^run_task)(void) = ^{ 33b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat task_copy.Run(); 34b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat }; 35b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 36cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko int64_t delay_nano = 37b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat delay.InMicroseconds() * base::Time::kNanosecondsPerMicrosecond; 38b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (delay_nano > 0) { 39b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, delay_nano); 40b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat dispatch_after(time, queue_, run_task); 41b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } else { 42b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat dispatch_async(queue_, run_task); 43b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 44b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return true; 45b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 46b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 47b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratbool LibDispatchTaskRunner::RunsTasksOnCurrentThread() const { 48b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return queue_ == dispatch_get_current_queue(); 49b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 50b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 51b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratbool LibDispatchTaskRunner::PostNonNestableDelayedTask( 52b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat const tracked_objects::Location& from_here, 53b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat const Closure& task, 54b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat base::TimeDelta delay) { 55b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return PostDelayedTask(from_here, task, delay); 56b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 57b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 58b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratvoid LibDispatchTaskRunner::Shutdown() { 59b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat dispatch_release(queue_); 60b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat queue_ = NULL; 61b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat queue_finalized_.Wait(); 62b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 63b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 64b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratdispatch_queue_t LibDispatchTaskRunner::GetDispatchQueue() const { 65b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return queue_; 66b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 67b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 68b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratLibDispatchTaskRunner::~LibDispatchTaskRunner() { 69b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (queue_) { 70b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat dispatch_set_context(queue_, NULL); 71b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat dispatch_set_finalizer_f(queue_, NULL); 72b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat dispatch_release(queue_); 73b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 74b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 75b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 76b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratvoid LibDispatchTaskRunner::Finalizer(void* context) { 77b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat LibDispatchTaskRunner* self = static_cast<LibDispatchTaskRunner*>(context); 78b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat self->queue_finalized_.Signal(); 79b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 80b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 81b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} // namespace mac 82b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} // namespace base 83