Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(220)

Side by Side Diff: base/message_pump_io_ios.mm

Issue 11412101: Provide an iOS message pump for IO implementation. (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Formatting nit Created 8 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2012 The Chromium Authors. All rights reserved.
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/message_pump_io_ios.h"
6
7 namespace base {
8
9 MessagePumpIOSForIO::FileDescriptorWatcher::FileDescriptorWatcher()
10 : is_persistent_(false),
11 fdref_(NULL),
12 callback_types_(0),
13 fd_source_(NULL),
14 pump_(NULL),
15 watcher_(NULL) {
16 }
17
18 MessagePumpIOSForIO::FileDescriptorWatcher::~FileDescriptorWatcher() {
19 StopWatchingFileDescriptor();
20 }
21
22 bool
Mark Mentovai 2012/11/20 14:47:58 This doesn’t need to be on its own line. Same on l
blundell 2012/11/20 20:38:54 Done.
23 MessagePumpIOSForIO::FileDescriptorWatcher::StopWatchingFileDescriptor() {
24 if (fdref_ == NULL)
25 return true;
Mark Mentovai 2012/11/20 14:47:58 Does this ever return false?
blundell 2012/11/20 20:38:54 No. The only reason that this was not void was for
blundell 2012/11/20 20:57:00 I spoke too soon; when I change this signature, co
26
27 CFFileDescriptorDisableCallBacks(fdref_, callback_types_);
28 pump_->RemoveRunLoopSource(fd_source_);
29 fd_source_.reset();
30 fdref_.reset();
31 callback_types_ = 0;
32 pump_ = NULL;
33 watcher_ = NULL;
34 return true;
35 }
36
37 void MessagePumpIOSForIO::FileDescriptorWatcher::Init(
38 CFFileDescriptorRef fdref,
39 CFOptionFlags callback_types,
40 CFRunLoopSourceRef fd_source,
41 bool is_persistent) {
42 DCHECK(fdref);
43 DCHECK(!fdref_);
44
45 is_persistent_ = is_persistent;
46 fdref_.reset(fdref);
47 callback_types_ = callback_types;
48 fd_source_.reset(fd_source);
49 }
50
51 void
52 MessagePumpIOSForIO::FileDescriptorWatcher::OnFileCanReadWithoutBlocking(
53 int fd,
54 MessagePumpIOSForIO* pump) {
55 pump->WillProcessIOEvent();
56 watcher_->OnFileCanReadWithoutBlocking(fd);
57 pump->DidProcessIOEvent();
58 }
59
60 void
61 MessagePumpIOSForIO::FileDescriptorWatcher::OnFileCanWriteWithoutBlocking(
62 int fd,
63 MessagePumpIOSForIO* pump) {
64 pump->WillProcessIOEvent();
65 watcher_->OnFileCanWriteWithoutBlocking(fd);
66 pump->DidProcessIOEvent();
67 }
68
69 MessagePumpIOSForIO::MessagePumpIOSForIO() {
70 }
71
72 MessagePumpIOSForIO::~MessagePumpIOSForIO() {
73 }
74
75 bool MessagePumpIOSForIO::WatchFileDescriptor(
76 int fd,
77 bool persistent,
78 Mode mode,
79 FileDescriptorWatcher *controller,
80 Watcher *delegate) {
81 DCHECK_GE(fd, 0);
82 DCHECK(controller);
83 DCHECK(delegate);
84 DCHECK(mode == WATCH_READ || mode == WATCH_WRITE || mode == WATCH_READ_WRITE);
85
86 // WatchFileDescriptor should be called on the pump thread. It is not
87 // threadsafe, and your watcher may never be registered.
88 DCHECK(watch_file_descriptor_caller_checker_.CalledOnValidThread());
89
90 CFFileDescriptorContext source_context = {0};
91 source_context.info = controller;
92
93 CFOptionFlags callback_types = 0;
94 if ((mode & WATCH_READ) != 0) {
95 callback_types |= kCFFileDescriptorReadCallBack;
96 }
97 if ((mode & WATCH_WRITE) != 0) {
98 callback_types |= kCFFileDescriptorWriteCallBack;
99 }
100
101 CFFileDescriptorRef fdref = controller->fdref_;
102 if (fdref == NULL) {
103 base::mac::ScopedCFTypeRef<CFFileDescriptorRef> scoped_fdref(
104 CFFileDescriptorCreate(kCFAllocatorDefault, fd, false, HandleFdIOEvent,
105 &source_context));
106 if (scoped_fdref == NULL) {
107 NOTREACHED() << "CFFileDescriptorCreate failed";
108 return false;
109 }
110
111 CFFileDescriptorEnableCallBacks(scoped_fdref, callback_types);
112
113 // TODO(wtc): what should the 'order' argument be?
114 base::mac::ScopedCFTypeRef<CFRunLoopSourceRef> scoped_fd_source(
115 CFFileDescriptorCreateRunLoopSource(kCFAllocatorDefault,
116 scoped_fdref,
117 0));
118 if (scoped_fd_source == NULL) {
119 NOTREACHED() << "CFFileDescriptorCreateRunLoopSource failed";
120 return false;
121 }
122 CFRunLoopAddSource(run_loop(), scoped_fd_source, kCFRunLoopCommonModes);
123
124 // Transfer ownership of scoped_fdref and fd_source to controller.
125 controller->Init(scoped_fdref.release(), callback_types,
126 scoped_fd_source.release(), persistent);
127 } else {
128 // It's illegal to use this function to listen on 2 separate fds with the
129 // same |controller|.
130 if (CFFileDescriptorGetNativeDescriptor(fdref) != fd) {
131 NOTREACHED() << "FDs don't match: "
132 << CFFileDescriptorGetNativeDescriptor(fdref)
133 << " != " << fd;
134 return false;
135 }
136 if (persistent != controller->is_persistent_) {
137 NOTREACHED() << "persistent doesn't match";
138 return false;
139 }
140
141 // Combine old/new event masks.
142 CFFileDescriptorDisableCallBacks(fdref, controller->callback_types_);
143 controller->callback_types_ |= callback_types;
144 CFFileDescriptorEnableCallBacks(fdref, controller->callback_types_);
145 }
146
147 controller->set_watcher(delegate);
148 controller->set_pump(this);
149
150 return true;
151 }
152
153 void MessagePumpIOSForIO::RemoveRunLoopSource(CFRunLoopSourceRef source) {
154 CFRunLoopRemoveSource(run_loop(), source, kCFRunLoopCommonModes);
155 }
156
157 void MessagePumpIOSForIO::AddIOObserver(IOObserver *obs) {
158 io_observers_.AddObserver(obs);
159 }
160
161 void MessagePumpIOSForIO::RemoveIOObserver(IOObserver *obs) {
162 io_observers_.RemoveObserver(obs);
163 }
164
165 void MessagePumpIOSForIO::WillProcessIOEvent() {
166 FOR_EACH_OBSERVER(IOObserver, io_observers_, WillProcessIOEvent());
167 }
168
169 void MessagePumpIOSForIO::DidProcessIOEvent() {
170 FOR_EACH_OBSERVER(IOObserver, io_observers_, DidProcessIOEvent());
171 }
172
173 // static
174 void MessagePumpIOSForIO::HandleFdIOEvent(CFFileDescriptorRef fdref,
175 CFOptionFlags callback_types,
176 void* info) {
177 int fd = CFFileDescriptorGetNativeDescriptor(fdref);
178
179 FileDescriptorWatcher* controller =
180 static_cast<FileDescriptorWatcher*>(info);
181
182 CHECK_EQ(fdref, controller->fdref_);
183 bool persistent = controller->is_persistent_;
184
185 MessagePumpIOSForIO* pump = controller->pump();
186 if (callback_types & kCFFileDescriptorWriteCallBack) {
187 controller->OnFileCanWriteWithoutBlocking(fd, pump);
188 }
189 if (callback_types & kCFFileDescriptorReadCallBack) {
190 controller->OnFileCanReadWithoutBlocking(fd, pump);
191 }
192
193 // Must read/write from the fd before re-enabling the callbacks.
194 // |controller| may have been deleted, so we test a copy of
195 // controller->persistent. |fdref| may have been invalidated.
196 CHECK_GT(CFGetRetainCount(fdref), 0);
197 if (CFFileDescriptorIsValid(fdref) && persistent)
198 CFFileDescriptorEnableCallBacks(fdref, callback_types);
199 }
200
201 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698