xref: /aosp_15_r20/external/cronet/base/apple/dispatch_source_mach.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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