12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file. 42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/mac/libdispatch_task_runner.h" 62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/callback.h" 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace base { 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace mac { 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)LibDispatchTaskRunner::LibDispatchTaskRunner(const char* name) 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : queue_(dispatch_queue_create(name, NULL)), 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) queue_finalized_(false, false) { 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) dispatch_set_context(queue_, this); 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) dispatch_set_finalizer_f(queue_, &LibDispatchTaskRunner::Finalizer); 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool LibDispatchTaskRunner::PostDelayedTask( 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const tracked_objects::Location& from_here, 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const Closure& task, 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::TimeDelta delay) { 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!queue_) 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The block runtime would implicitly copy the reference, not the object 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // it's referencing. Copy the closure into block storage so it's available 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // to run. 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) __block const Closure task_copy = task; 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void(^run_task)(void) = ^{ 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) task_copy.Run(); 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) }; 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int64 delay_nano = 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) delay.InMicroseconds() * base::Time::kNanosecondsPerMicrosecond; 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (delay_nano > 0) { 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, delay_nano); 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) dispatch_after(time, queue_, run_task); 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) dispatch_async(queue_, run_task); 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool LibDispatchTaskRunner::RunsTasksOnCurrentThread() const { 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return queue_ == dispatch_get_current_queue(); 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool LibDispatchTaskRunner::PostNonNestableDelayedTask( 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const tracked_objects::Location& from_here, 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const Closure& task, 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::TimeDelta delay) { 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return PostDelayedTask(from_here, task, delay); 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void LibDispatchTaskRunner::Shutdown() { 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) dispatch_release(queue_); 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) queue_ = NULL; 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) queue_finalized_.Wait(); 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)dispatch_queue_t LibDispatchTaskRunner::GetDispatchQueue() const { 632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return queue_; 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)LibDispatchTaskRunner::~LibDispatchTaskRunner() { 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (queue_) { 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) dispatch_set_context(queue_, NULL); 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) dispatch_set_finalizer_f(queue_, NULL); 702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) dispatch_release(queue_); 712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void LibDispatchTaskRunner::Finalizer(void* context) { 752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LibDispatchTaskRunner* self = static_cast<LibDispatchTaskRunner*>(context); 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self->queue_finalized_.Signal(); 772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace mac 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace base 81