| // Copyright 2018 Google Inc. All Rights Reserved. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| #ifndef BASE_MESSAGE_PUMP_IO_STARBOARD_H_ |
| #define BASE_MESSAGE_PUMP_IO_STARBOARD_H_ |
| |
| #include "base/compiler_specific.h" |
| #include "base/memory/weak_ptr.h" |
| #include "base/message_loop/message_pump.h" |
| #include "base/observer_list.h" |
| #include "base/threading/thread_checker.h" |
| #include "base/time/time.h" |
| #include "starboard/common/socket.h" |
| #include "starboard/socket_waiter.h" |
| |
| namespace base { |
| |
| // Class to monitor sockets and issue callbacks when sockets are ready for I/O. |
| class BASE_EXPORT MessagePumpIOStarboard : public MessagePump { |
| public: |
| class IOObserver : public CheckedObserver { |
| public: |
| IOObserver() {} |
| virtual ~IOObserver() {} |
| |
| // An IOObserver is an object that receives IO notifications from the |
| // MessagePump. |
| // |
| // NOTE: An IOObserver should not do much work, it should return extremely |
| // quickly! |
| virtual void WillProcessIOEvent() = 0; |
| virtual void DidProcessIOEvent() = 0; |
| }; |
| |
| // Used with WatchFileDescriptor to asynchronously monitor the I/O readiness |
| // of a file descriptor. |
| class Watcher { |
| public: |
| // These methods are called from MessageLoop::Run when a socket can be |
| // interacted with without blocking. |
| virtual void OnSocketReadyToRead(SbSocket socket) {} |
| virtual void OnSocketReadyToWrite(SbSocket socket) {} |
| |
| protected: |
| virtual ~Watcher() {} |
| }; |
| |
| // Object returned by WatchSocket to manage further watching. |
| class SocketWatcher { |
| public: |
| SocketWatcher(); |
| ~SocketWatcher(); // Implicitly calls StopWatchingSocket. |
| |
| // NOTE: These methods aren't called StartWatching()/StopWatching() to avoid |
| // confusion with the win32 ObjectWatcher class. |
| |
| // Stops watching the socket, always safe to call. No-op if there's nothing |
| // to do. |
| bool StopWatchingSocket(); |
| |
| bool persistent() const { return persistent_; } |
| |
| private: |
| friend class MessagePumpIOStarboard; |
| friend class MessagePumpIOStarboardTest; |
| |
| // Called by MessagePumpIOStarboard. |
| void Init(SbSocket socket, bool persistent); |
| SbSocket Release(); |
| |
| int interests() const { return interests_; } |
| void set_interests(int interests) { interests_ = interests; } |
| |
| void set_pump(MessagePumpIOStarboard* pump) { pump_ = pump; } |
| MessagePumpIOStarboard* pump() const { return pump_; } |
| |
| void set_watcher(Watcher* watcher) { watcher_ = watcher; } |
| |
| void OnSocketReadyToRead(SbSocket socket, MessagePumpIOStarboard* pump); |
| void OnSocketReadyToWrite(SbSocket socket, MessagePumpIOStarboard* pump); |
| |
| int interests_; |
| SbSocket socket_; |
| bool persistent_; |
| MessagePumpIOStarboard* pump_; |
| Watcher* watcher_; |
| base::WeakPtrFactory<SocketWatcher> weak_factory_; |
| |
| DISALLOW_COPY_AND_ASSIGN(SocketWatcher); |
| }; |
| |
| enum Mode { |
| WATCH_READ = 1 << 0, |
| WATCH_WRITE = 1 << 1, |
| WATCH_READ_WRITE = WATCH_READ | WATCH_WRITE |
| }; |
| |
| MessagePumpIOStarboard(); |
| |
| // Have the current thread's message loop watch for a a situation in which |
| // reading/writing to the socket can be performed without blocking. Callers |
| // must provide a preallocated SocketWatcher object which can later be used to |
| // manage the lifetime of this event. If a SocketWatcher is passed in which |
| // is already attached to a socket, then the effect is cumulative i.e. after |
| // the call |controller| will watch both the previous event and the new one. |
| // If an error occurs while calling this method in a cumulative fashion, the |
| // event previously attached to |controller| is aborted. Returns true on |
| // success. Must be called on the same thread the message_pump is running on. |
| bool Watch(SbSocket socket, |
| bool persistent, |
| int mode, |
| SocketWatcher* controller, |
| Watcher* delegate); |
| |
| // Stops watching the socket. |
| bool StopWatching(SbSocket socket); |
| |
| void AddIOObserver(IOObserver* obs); |
| void RemoveIOObserver(IOObserver* obs); |
| |
| // MessagePump methods: |
| virtual void Run(Delegate* delegate) override; |
| virtual void Quit() override; |
| virtual void ScheduleWork() override; |
| virtual void ScheduleDelayedWork(const TimeTicks& delayed_work_time) override; |
| |
| protected: |
| virtual ~MessagePumpIOStarboard(); |
| |
| private: |
| friend class MessagePumpIOStarboardTest; |
| |
| void WillProcessIOEvent(); |
| void DidProcessIOEvent(); |
| |
| // Called by SbSocketWaiter to tell us a registered socket can be read and/or |
| // written to. |
| static void OnSocketWaiterNotification(SbSocketWaiter waiter, |
| SbSocket socket, |
| void* context, |
| int ready_interests); |
| |
| // This flag is set to false when Run should return. |
| bool keep_running_; |
| |
| // This flag is set when inside Run. |
| bool in_run_; |
| |
| // This flag is set if the Socket Waiter has processed I/O events. |
| bool processed_io_events_; |
| |
| // The time at which we should call DoDelayedWork. |
| TimeTicks delayed_work_time_; |
| |
| // Starboard socket waiter dispatcher. Waits for all sockets registered with |
| // it, and sends readiness callbacks when a socket is ready for I/O. |
| SbSocketWaiter waiter_; |
| |
| ObserverList<IOObserver> io_observers_; |
| THREAD_CHECKER(watch_socket_caller_checker_); |
| DISALLOW_COPY_AND_ASSIGN(MessagePumpIOStarboard); |
| }; |
| |
| using MessagePumpForIO = MessagePumpIOStarboard; |
| |
| } // namespace base |
| |
| #endif // BASE_MESSAGE_PUMP_IO_STARBOARD_H_ |