1*6777b538SAndroid Build Coastguard Worker // Copyright 2014 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker
5*6777b538SAndroid Build Coastguard Worker #include "base/apple/dispatch_source_mach.h"
6*6777b538SAndroid Build Coastguard Worker
7*6777b538SAndroid Build Coastguard Worker #include "base/apple/scoped_dispatch_object.h"
8*6777b538SAndroid Build Coastguard Worker
9*6777b538SAndroid Build Coastguard Worker namespace base::apple {
10*6777b538SAndroid Build Coastguard Worker
11*6777b538SAndroid Build Coastguard Worker struct DispatchSourceMach::Storage {
12*6777b538SAndroid Build Coastguard Worker // The dispatch queue used to service the source_.
13*6777b538SAndroid Build Coastguard Worker ScopedDispatchObject<dispatch_queue_t> queue;
14*6777b538SAndroid Build Coastguard Worker
15*6777b538SAndroid Build Coastguard Worker // A MACH_RECV dispatch source.
16*6777b538SAndroid Build Coastguard Worker ScopedDispatchObject<dispatch_source_t> source;
17*6777b538SAndroid Build Coastguard Worker
18*6777b538SAndroid Build Coastguard Worker // Semaphore used to wait on the |source_|'s cancellation in the destructor.
19*6777b538SAndroid Build Coastguard Worker ScopedDispatchObject<dispatch_semaphore_t> source_canceled;
20*6777b538SAndroid Build Coastguard Worker };
21*6777b538SAndroid Build Coastguard Worker
22*6777b538SAndroid Build Coastguard Worker DispatchSourceMach::DispatchSourceMach(const char* name,
23*6777b538SAndroid Build Coastguard Worker mach_port_t port,
24*6777b538SAndroid Build Coastguard Worker void (^event_handler)())
25*6777b538SAndroid Build Coastguard Worker : DispatchSourceMach(dispatch_queue_create(name, DISPATCH_QUEUE_SERIAL),
26*6777b538SAndroid Build Coastguard Worker port,
27*6777b538SAndroid Build Coastguard Worker event_handler) {
28*6777b538SAndroid Build Coastguard Worker // Since the queue was created above in the delegated constructor, and it was
29*6777b538SAndroid Build Coastguard Worker // subsequently retained, release it here.
30*6777b538SAndroid Build Coastguard Worker dispatch_release(storage_->queue.get());
31*6777b538SAndroid Build Coastguard Worker }
32*6777b538SAndroid Build Coastguard Worker
33*6777b538SAndroid Build Coastguard Worker DispatchSourceMach::DispatchSourceMach(dispatch_queue_t queue,
34*6777b538SAndroid Build Coastguard Worker mach_port_t port,
35*6777b538SAndroid Build Coastguard Worker void (^event_handler)())
36*6777b538SAndroid Build Coastguard Worker : storage_(std::make_unique<Storage>()) {
37*6777b538SAndroid Build Coastguard Worker storage_->queue.reset(queue, base::scoped_policy::RETAIN);
38*6777b538SAndroid Build Coastguard Worker storage_->source.reset(dispatch_source_create(
39*6777b538SAndroid Build Coastguard Worker DISPATCH_SOURCE_TYPE_MACH_RECV, port, 0, storage_->queue.get()));
40*6777b538SAndroid Build Coastguard Worker storage_->source_canceled.reset(dispatch_semaphore_create(0));
41*6777b538SAndroid Build Coastguard Worker
42*6777b538SAndroid Build Coastguard Worker dispatch_source_set_event_handler(storage_->source.get(), event_handler);
43*6777b538SAndroid Build Coastguard Worker dispatch_source_set_cancel_handler(storage_->source.get(), ^{
44*6777b538SAndroid Build Coastguard Worker dispatch_semaphore_signal(storage_->source_canceled.get());
45*6777b538SAndroid Build Coastguard Worker });
46*6777b538SAndroid Build Coastguard Worker }
47*6777b538SAndroid Build Coastguard Worker
~DispatchSourceMach()48*6777b538SAndroid Build Coastguard Worker DispatchSourceMach::~DispatchSourceMach() {
49*6777b538SAndroid Build Coastguard Worker // Cancel the source and wait for the semaphore to be signaled. This will
50*6777b538SAndroid Build Coastguard Worker // ensure the source managed by this class is not used after it is freed.
51*6777b538SAndroid Build Coastguard Worker dispatch_source_cancel(storage_->source.get());
52*6777b538SAndroid Build Coastguard Worker storage_->source.reset();
53*6777b538SAndroid Build Coastguard Worker
54*6777b538SAndroid Build Coastguard Worker dispatch_semaphore_wait(storage_->source_canceled.get(),
55*6777b538SAndroid Build Coastguard Worker DISPATCH_TIME_FOREVER);
56*6777b538SAndroid Build Coastguard Worker }
57*6777b538SAndroid Build Coastguard Worker
Resume()58*6777b538SAndroid Build Coastguard Worker void DispatchSourceMach::Resume() {
59*6777b538SAndroid Build Coastguard Worker dispatch_resume(storage_->source.get());
60*6777b538SAndroid Build Coastguard Worker }
61*6777b538SAndroid Build Coastguard Worker
Queue() const62*6777b538SAndroid Build Coastguard Worker dispatch_queue_t DispatchSourceMach::Queue() const {
63*6777b538SAndroid Build Coastguard Worker return storage_->queue.get();
64*6777b538SAndroid Build Coastguard Worker }
65*6777b538SAndroid Build Coastguard Worker
66*6777b538SAndroid Build Coastguard Worker } // namespace base::apple
67