1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
  127
  128
  129
  130
  131
  132
  133
  134
  135
  136
  137
  138
  139
  140
  141

base / message_loop / io_watcher.h [blame]

// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef BASE_MESSAGE_LOOP_IO_WATCHER_H_
#define BASE_MESSAGE_LOOP_IO_WATCHER_H_

#include <memory>

#include "base/base_export.h"
#include "base/location.h"
#include "base/message_loop/message_pump_for_io.h"
#include "base/types/pass_key.h"
#include "build/build_config.h"

#if defined(IS_WINDOWS)
#include "base/win/windows_types.h"
#endif

#if BUILDFLAG(IS_MAC) || (BUILDFLAG(IS_IOS) && !BUILDFLAG(CRONET_BUILD))
#include <mach/mach.h>
#endif

namespace base {

// An object which can be used to register asynchronous IO handlers to wake the
// calling thread directly on interesting events. This is guaranteed to be
// usable on any MessagePumpType::IO thread, but it may also be usable on other
// thread types if the MessagePump implementation supports it.
class BASE_EXPORT IOWatcher {
 public:
  virtual ~IOWatcher() = default;

  // Returns a valid IOWatcher instance iff it's usable from the calling thread.
  // Returns null otherwise.
  static IOWatcher* Get();

#if !BUILDFLAG(IS_NACL)
#if BUILDFLAG(IS_WIN)
  // Please see MessagePumpWin for definitions of these methods.
  [[nodiscard]] bool RegisterIOHandler(HANDLE file,
                                       MessagePumpForIO::IOHandler* handler);
  bool RegisterJobObject(HANDLE job, MessagePumpForIO::IOHandler* handler);
#elif BUILDFLAG(IS_POSIX)
  class FdWatcher {
   public:
    virtual void OnFdReadable(int fd) = 0;
    virtual void OnFdWritable(int fd) = 0;

   protected:
    virtual ~FdWatcher() = default;
  };

  // Effectively controls the lifetime of a single active FD watch started by
  // WatchFileDescriptor() below.
  class FdWatch {
   public:
    // FdWatch destruction immediately ceases watching the corresponding FD.
    // Must be called on the same thread that made the original call to
    // WatchFileDescriptor().
    virtual ~FdWatch() = default;
  };

  // Asynchronously watches `fd` for IO. If successful, this returns a valid
  // FdWatch object and the FD remains watched until the FdWatch object is
  // destroyed OR a watched event occurs (for a non-persistent watch only);
  // whichever occurs first. While the watch is active, `fd_watcher` will be
  // invoked on the calling thread whenever an interesting IO event happens.
  //
  // The returned FdWatch MUST be destroyed on the calling thread, and
  // `fd_watcher` MUST outlive it.
  enum class FdWatchDuration {
    kOneShot,
    kPersistent,
  };
  enum class FdWatchMode {
    kRead,
    kWrite,
    kReadWrite,
  };
  std::unique_ptr<FdWatch> WatchFileDescriptor(
      int fd,
      FdWatchDuration duration,
      FdWatchMode mode,
      FdWatcher& fd_watcher,
      const Location& location = Location::Current());
#endif

#if BUILDFLAG(IS_MAC) || (BUILDFLAG(IS_IOS) && !BUILDFLAG(CRONET_BUILD))
  bool WatchMachReceivePort(
      mach_port_t port,
      MessagePumpForIO::MachPortWatchController* controller,
      MessagePumpForIO::MachPortWatcher* delegate);
#elif BUILDFLAG(IS_FUCHSIA)
  // Additional watch API for native platform resources.
  bool WatchZxHandle(zx_handle_t handle,
                     bool persistent,
                     zx_signals_t signals,
                     MessagePumpForIO::ZxHandleWatchController* controller,
                     MessagePumpForIO::ZxHandleWatcher* delegate);
#endif  // BUILDFLAG(IS_FUCHSIA)
#endif  // !BUILDFLAG(IS_NACL)

 protected:
  IOWatcher();

  // IOWatcher implementations must implement these methods for any applicable
  // platform(s).
#if !BUILDFLAG(IS_NACL)
#if BUILDFLAG(IS_WIN)
  virtual bool RegisterIOHandlerImpl(HANDLE file,
                                     MessagePumpForIO::IOHandler* handler) = 0;
  virtual bool RegisterJobObjectImpl(HANDLE job,
                                     MessagePumpForIO::IOHandler* handler) = 0;
#elif BUILDFLAG(IS_POSIX)
  virtual std::unique_ptr<FdWatch> WatchFileDescriptorImpl(
      int fd,
      FdWatchDuration duration,
      FdWatchMode mode,
      FdWatcher& fd_watcher,
      const Location& location) = 0;
#endif
#if BUILDFLAG(IS_MAC) || (BUILDFLAG(IS_IOS) && !BUILDFLAG(CRONET_BUILD))
  virtual bool WatchMachReceivePortImpl(
      mach_port_t port,
      MessagePumpForIO::MachPortWatchController* controller,
      MessagePumpForIO::MachPortWatcher* delegate) = 0;
#elif BUILDFLAG(IS_FUCHSIA)
  virtual bool WatchZxHandleImpl(
      zx_handle_t handle,
      bool persistent,
      zx_signals_t signals,
      MessagePumpForIO::ZxHandleWatchController* controller,
      MessagePumpForIO::ZxHandleWatcher* delegate) = 0;
#endif  // BUILDFLAG(IS_FUCHSIA)
#endif  // !BUILDFLAG(IS_NACL)
};

}  // namespace base

#endif  // BASE_MESSAGE_LOOP_IO_WATCHER_H_