1 // Copyright 2016 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 #ifndef BASE_FILES_FILE_DESCRIPTOR_WATCHER_POSIX_H_ 6 #define BASE_FILES_FILE_DESCRIPTOR_WATCHER_POSIX_H_ 7 8 #include <memory> 9 10 #include "base/base_export.h" 11 #include "base/callback.h" 12 #include "base/macros.h" 13 #include "base/memory/ref_counted.h" 14 #include "base/memory/weak_ptr.h" 15 #include "base/message_loop/message_loop.h" 16 #include "base/message_loop/message_pump_for_io.h" 17 #include "base/sequence_checker.h" 18 19 namespace base { 20 21 class SingleThreadTaskRunner; 22 23 // The FileDescriptorWatcher API allows callbacks to be invoked when file 24 // descriptors are readable or writable without blocking. 25 // 26 // To enable this API in unit tests, use a ScopedTaskEnvironment with 27 // MainThreadType::IO. 28 // 29 // Note: Prefer FileDescriptorWatcher to MessageLoopForIO::WatchFileDescriptor() 30 // for non-critical IO. FileDescriptorWatcher works on threads/sequences without 31 // MessagePumps but involves going through the task queue after being notified 32 // by the OS (a desirablable property for non-critical IO that shouldn't preempt 33 // the main queue). 34 class BASE_EXPORT FileDescriptorWatcher { 35 public: 36 // Instantiated and returned by WatchReadable() or WatchWritable(). The 37 // constructor registers a callback to be invoked when a file descriptor is 38 // readable or writable without blocking and the destructor unregisters it. 39 class Controller { 40 public: 41 // Unregisters the callback registered by the constructor. 42 ~Controller(); 43 44 private: 45 friend class FileDescriptorWatcher; 46 class Watcher; 47 48 // Registers |callback| to be invoked when |fd| is readable or writable 49 // without blocking (depending on |mode|). 50 Controller(MessagePumpForIO::Mode mode, int fd, const Closure& callback); 51 52 // Starts watching the file descriptor. 53 void StartWatching(); 54 55 // Runs |callback_|. 56 void RunCallback(); 57 58 // The callback to run when the watched file descriptor is readable or 59 // writable without blocking. 60 Closure callback_; 61 62 // TaskRunner associated with the MessageLoopForIO that watches the file 63 // descriptor. 64 const scoped_refptr<SingleThreadTaskRunner> 65 message_loop_for_io_task_runner_; 66 67 // Notified by the MessageLoopForIO associated with 68 // |message_loop_for_io_task_runner_| when the watched file descriptor is 69 // readable or writable without blocking. Posts a task to run RunCallback() 70 // on the sequence on which the Controller was instantiated. When the 71 // Controller is deleted, ownership of |watcher_| is transfered to a delete 72 // task posted to the MessageLoopForIO. This ensures that |watcher_| isn't 73 // deleted while it is being used by the MessageLoopForIO. 74 std::unique_ptr<Watcher> watcher_; 75 76 // Validates that the Controller is used on the sequence on which it was 77 // instantiated. 78 SequenceChecker sequence_checker_; 79 80 WeakPtrFactory<Controller> weak_factory_; 81 82 DISALLOW_COPY_AND_ASSIGN(Controller); 83 }; 84 85 // Registers |message_loop_for_io| to watch file descriptors for which 86 // callbacks are registered from the current thread via WatchReadable() or 87 // WatchWritable(). |message_loop_for_io| may run on another thread. The 88 // constructed FileDescriptorWatcher must not outlive |message_loop_for_io|. 89 FileDescriptorWatcher(MessageLoopForIO* message_loop_for_io); 90 ~FileDescriptorWatcher(); 91 92 // Registers |callback| to be posted on the current sequence when |fd| is 93 // readable or writable without blocking. |callback| is unregistered when the 94 // returned Controller is deleted (deletion must happen on the current 95 // sequence). To call these methods, a FileDescriptorWatcher must have been 96 // instantiated on the current thread and SequencedTaskRunnerHandle::IsSet() 97 // must return true (these conditions are met at least on all TaskScheduler 98 // threads as well as on threads backed by a MessageLoopForIO). 99 static std::unique_ptr<Controller> WatchReadable(int fd, 100 const Closure& callback); 101 static std::unique_ptr<Controller> WatchWritable(int fd, 102 const Closure& callback); 103 104 private: 105 DISALLOW_COPY_AND_ASSIGN(FileDescriptorWatcher); 106 }; 107 108 } // namespace base 109 110 #endif // BASE_FILES_FILE_DESCRIPTOR_WATCHER_POSIX_H_ 111