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