12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright 2012 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
57d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/message_loop/message_pump_io_ios.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace base {
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)MessagePumpIOSForIO::FileDescriptorWatcher::FileDescriptorWatcher()
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : is_persistent_(false),
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      fdref_(NULL),
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      callback_types_(0),
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      fd_source_(NULL),
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      watcher_(NULL) {
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)MessagePumpIOSForIO::FileDescriptorWatcher::~FileDescriptorWatcher() {
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  StopWatchingFileDescriptor();
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool MessagePumpIOSForIO::FileDescriptorWatcher::StopWatchingFileDescriptor() {
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (fdref_ == NULL)
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return true;
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CFFileDescriptorDisableCallBacks(fdref_, callback_types_);
26ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  if (pump_)
27ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    pump_->RemoveRunLoopSource(fd_source_);
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  fd_source_.reset();
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  fdref_.reset();
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  callback_types_ = 0;
31ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  pump_.reset();
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  watcher_ = NULL;
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MessagePumpIOSForIO::FileDescriptorWatcher::Init(
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CFFileDescriptorRef fdref,
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CFOptionFlags callback_types,
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CFRunLoopSourceRef fd_source,
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool is_persistent) {
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(fdref);
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!fdref_);
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  is_persistent_ = is_persistent;
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  fdref_.reset(fdref);
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  callback_types_ = callback_types;
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  fd_source_.reset(fd_source);
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MessagePumpIOSForIO::FileDescriptorWatcher::OnFileCanReadWithoutBlocking(
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int fd,
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    MessagePumpIOSForIO* pump) {
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(callback_types_ & kCFFileDescriptorReadCallBack);
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  pump->WillProcessIOEvent();
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  watcher_->OnFileCanReadWithoutBlocking(fd);
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  pump->DidProcessIOEvent();
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MessagePumpIOSForIO::FileDescriptorWatcher::OnFileCanWriteWithoutBlocking(
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int fd,
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    MessagePumpIOSForIO* pump) {
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(callback_types_ & kCFFileDescriptorWriteCallBack);
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  pump->WillProcessIOEvent();
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  watcher_->OnFileCanWriteWithoutBlocking(fd);
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  pump->DidProcessIOEvent();
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
68ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochMessagePumpIOSForIO::MessagePumpIOSForIO() : weak_factory_(this) {
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)MessagePumpIOSForIO::~MessagePumpIOSForIO() {
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool MessagePumpIOSForIO::WatchFileDescriptor(
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int fd,
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool persistent,
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int mode,
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    FileDescriptorWatcher *controller,
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Watcher *delegate) {
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_GE(fd, 0);
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(controller);
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(delegate);
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(mode == WATCH_READ || mode == WATCH_WRITE || mode == WATCH_READ_WRITE);
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // WatchFileDescriptor should be called on the pump thread. It is not
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // threadsafe, and your watcher may never be registered.
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(watch_file_descriptor_caller_checker_.CalledOnValidThread());
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CFFileDescriptorContext source_context = {0};
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  source_context.info = controller;
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CFOptionFlags callback_types = 0;
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (mode & WATCH_READ) {
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    callback_types |= kCFFileDescriptorReadCallBack;
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (mode & WATCH_WRITE) {
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    callback_types |= kCFFileDescriptorWriteCallBack;
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CFFileDescriptorRef fdref = controller->fdref_;
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (fdref == NULL) {
102eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    base::ScopedCFTypeRef<CFFileDescriptorRef> scoped_fdref(
103eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        CFFileDescriptorCreate(
104eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            kCFAllocatorDefault, fd, false, HandleFdIOEvent, &source_context));
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (scoped_fdref == NULL) {
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      NOTREACHED() << "CFFileDescriptorCreate failed";
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return false;
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CFFileDescriptorEnableCallBacks(scoped_fdref, callback_types);
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // TODO(wtc): what should the 'order' argument be?
113eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    base::ScopedCFTypeRef<CFRunLoopSourceRef> scoped_fd_source(
114eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        CFFileDescriptorCreateRunLoopSource(
115eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            kCFAllocatorDefault, scoped_fdref, 0));
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (scoped_fd_source == NULL) {
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      NOTREACHED() << "CFFileDescriptorCreateRunLoopSource failed";
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return false;
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CFRunLoopAddSource(run_loop(), scoped_fd_source, kCFRunLoopCommonModes);
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Transfer ownership of scoped_fdref and fd_source to controller.
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    controller->Init(scoped_fdref.release(), callback_types,
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     scoped_fd_source.release(), persistent);
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // It's illegal to use this function to listen on 2 separate fds with the
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // same |controller|.
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (CFFileDescriptorGetNativeDescriptor(fdref) != fd) {
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      NOTREACHED() << "FDs don't match: "
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   << CFFileDescriptorGetNativeDescriptor(fdref)
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   << " != " << fd;
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return false;
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (persistent != controller->is_persistent_) {
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      NOTREACHED() << "persistent doesn't match";
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return false;
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Combine old/new event masks.
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CFFileDescriptorDisableCallBacks(fdref, controller->callback_types_);
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    controller->callback_types_ |= callback_types;
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CFFileDescriptorEnableCallBacks(fdref, controller->callback_types_);
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  controller->set_watcher(delegate);
146ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  controller->set_pump(weak_factory_.GetWeakPtr());
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MessagePumpIOSForIO::RemoveRunLoopSource(CFRunLoopSourceRef source) {
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CFRunLoopRemoveSource(run_loop(), source, kCFRunLoopCommonModes);
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MessagePumpIOSForIO::AddIOObserver(IOObserver *obs) {
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  io_observers_.AddObserver(obs);
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MessagePumpIOSForIO::RemoveIOObserver(IOObserver *obs) {
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  io_observers_.RemoveObserver(obs);
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MessagePumpIOSForIO::WillProcessIOEvent() {
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  FOR_EACH_OBSERVER(IOObserver, io_observers_, WillProcessIOEvent());
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MessagePumpIOSForIO::DidProcessIOEvent() {
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  FOR_EACH_OBSERVER(IOObserver, io_observers_, DidProcessIOEvent());
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MessagePumpIOSForIO::HandleFdIOEvent(CFFileDescriptorRef fdref,
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                          CFOptionFlags callback_types,
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                          void* context) {
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  FileDescriptorWatcher* controller =
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      static_cast<FileDescriptorWatcher*>(context);
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_EQ(fdref, controller->fdref_);
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Ensure that |fdref| will remain live for the duration of this function
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // call even if |controller| is deleted or |StopWatchingFileDescriptor()| is
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // called, either of which will cause |fdref| to be released.
182eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedCFTypeRef<CFFileDescriptorRef> scoped_fdref(
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      fdref, base::scoped_policy::RETAIN);
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int fd = CFFileDescriptorGetNativeDescriptor(fdref);
186ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  MessagePumpIOSForIO* pump = controller->pump().get();
187ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  DCHECK(pump);
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (callback_types & kCFFileDescriptorWriteCallBack)
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    controller->OnFileCanWriteWithoutBlocking(fd, pump);
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Perform the read callback only if the file descriptor has not been
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // invalidated in the write callback. As |FileDescriptorWatcher| invalidates
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // its file descriptor on destruction, the file descriptor being valid also
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // guarantees that |controller| has not been deleted.
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (callback_types & kCFFileDescriptorReadCallBack &&
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CFFileDescriptorIsValid(fdref)) {
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK_EQ(fdref, controller->fdref_);
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    controller->OnFileCanReadWithoutBlocking(fd, pump);
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Re-enable callbacks after the read/write if the file descriptor is still
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // valid and the controller is persistent.
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (CFFileDescriptorIsValid(fdref) && controller->is_persistent_) {
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK_EQ(fdref, controller->fdref_);
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CFFileDescriptorEnableCallBacks(fdref, callback_types);
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace base
210