// Copyright 2014 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "base/apple/dispatch_source_mach.h" #include "base/apple/scoped_dispatch_object.h" namespace base::apple { struct DispatchSourceMach::Storage { // The dispatch queue used to service the source_. ScopedDispatchObject queue; // A MACH_RECV dispatch source. ScopedDispatchObject source; // Semaphore used to wait on the |source_|'s cancellation in the destructor. ScopedDispatchObject source_canceled; }; DispatchSourceMach::DispatchSourceMach(const char* name, mach_port_t port, void (^event_handler)()) : DispatchSourceMach(dispatch_queue_create(name, DISPATCH_QUEUE_SERIAL), port, event_handler) { // Since the queue was created above in the delegated constructor, and it was // subsequently retained, release it here. dispatch_release(storage_->queue.get()); } DispatchSourceMach::DispatchSourceMach(dispatch_queue_t queue, mach_port_t port, void (^event_handler)()) : storage_(std::make_unique()) { storage_->queue.reset(queue, base::scoped_policy::RETAIN); storage_->source.reset(dispatch_source_create( DISPATCH_SOURCE_TYPE_MACH_RECV, port, 0, storage_->queue.get())); storage_->source_canceled.reset(dispatch_semaphore_create(0)); dispatch_source_set_event_handler(storage_->source.get(), event_handler); dispatch_source_set_cancel_handler(storage_->source.get(), ^{ dispatch_semaphore_signal(storage_->source_canceled.get()); }); } DispatchSourceMach::~DispatchSourceMach() { // Cancel the source and wait for the semaphore to be signaled. This will // ensure the source managed by this class is not used after it is freed. dispatch_source_cancel(storage_->source.get()); storage_->source.reset(); dispatch_semaphore_wait(storage_->source_canceled.get(), DISPATCH_TIME_FOREVER); } void DispatchSourceMach::Resume() { dispatch_resume(storage_->source.get()); } dispatch_queue_t DispatchSourceMach::Queue() const { return storage_->queue.get(); } } // namespace base::apple