| // Copyright 2017 The Cobalt Authors. 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 STARBOARD_SHARED_WIN32_SOCKET_WAITER_INTERNAL_H_ |
| #define STARBOARD_SHARED_WIN32_SOCKET_WAITER_INTERNAL_H_ |
| |
| #include <windows.h> |
| #include <winsock2.h> |
| |
| #include <deque> |
| #include <memory> |
| #include <unordered_map> |
| #include <vector> |
| |
| #include "starboard/common/mutex.h" |
| #include "starboard/common/optional.h" |
| #include "starboard/common/socket.h" |
| #include "starboard/shared/internal_only.h" |
| #include "starboard/shared/win32/auto_event_handle.h" |
| #include "starboard/shared/win32/socket_internal.h" |
| #include "starboard/socket_waiter.h" |
| #include "starboard/thread.h" |
| #include "starboard/types.h" |
| |
| namespace sbwin32 = starboard::shared::win32; |
| |
| #pragma warning(push) |
| |
| // SbSocketWaiterPrivate is defined as a struct, but for windows implementation |
| // enough functionality has been added so that it warrants being a class |
| // per Google's C++ style guide. This mismatch causes the Microsoft's compiler |
| // to generate a warning. |
| #pragma warning(disable : 4099) |
| class SbSocketWaiterPrivate { |
| public: |
| SbSocketWaiterPrivate(); |
| ~SbSocketWaiterPrivate(); |
| |
| // These methods implement the SbSocketWaiter API defined in socket_waiter.h. |
| bool Add(SbSocket socket, |
| void* context, |
| SbSocketWaiterCallback callback, |
| int interests, |
| bool persistent); |
| bool Remove(SbSocket socket); |
| void Wait(); |
| SbSocketWaiterResult WaitTimed(int64_t duration_usec); |
| void WakeUp(); |
| void HandleWakeUpRead(); |
| |
| private: |
| // A registration of a socket with a socket waiter. |
| struct Waitee { |
| Waitee(SbSocketWaiter waiter, |
| SbSocket socket, |
| void* context, |
| SbSocketWaiterCallback callback, |
| int interests, |
| bool persistent) |
| : waiter(waiter), |
| socket(socket), |
| context(context), |
| callback(callback), |
| interests(interests), |
| persistent(persistent) {} |
| // The waiter this event is registered with. |
| SbSocketWaiter waiter; |
| |
| // The socket registered with the waiter. |
| SbSocket socket; |
| |
| // A context value that will be passed to the callback. |
| void* context; |
| |
| // The callback to call when one or more registered interests become ready. |
| SbSocketWaiterCallback callback; |
| |
| // The set of interests registered with the waiter. |
| int interests; |
| |
| // Whether this Waitee should stay registered after the next callback. |
| bool persistent; |
| }; |
| |
| class WaiteeRegistry { |
| public: |
| typedef int64_t LookupToken; |
| typedef std::deque<std::unique_ptr<Waitee>> Waitees; |
| typedef std::unordered_map<SbSocket, std::size_t> SocketToIndex; |
| |
| WSAEVENT* GetHandleArray() { return socket_events_.data(); } |
| std::size_t GetHandleArraySize() { return socket_events_.size(); } |
| const Waitees& GetWaitees() const { return waitees_; } |
| |
| // Gets the Waitee associated with the given socket, or nullptr. |
| Waitee* GetWaitee(SbSocket socket); |
| |
| // Gets the index by socket |
| starboard::optional<int64_t> GetIndex(SbSocket socket); |
| |
| // Gets the Waitee by index. |
| Waitee* GetWaiteeByIndex(LookupToken socket_index); |
| |
| // Returns the index of the event. |
| LookupToken AddSocketEventAndWaitee(WSAEVENT socket_event, |
| std::unique_ptr<Waitee> waitee); |
| // Returns true if socket was found, and removed. |
| bool RemoveSocket(SbSocket socket); |
| |
| private: |
| SocketToIndex socket_to_index_map_; |
| std::vector<WSAEVENT> socket_events_; |
| std::deque<std::unique_ptr<Waitee>> waitees_; |
| }; |
| |
| void SignalWakeupEvent(); |
| void ResetWakeupEvent(); |
| |
| bool CheckSocketWaiterIsThis(SbSocket socket); |
| |
| // The thread this waiter was created on. Immutable, so accessible from any |
| // thread. |
| const SbThread thread_; |
| |
| // The registry of currently registered Waitees. |
| WaiteeRegistry waitees_; |
| WaiteeRegistry::LookupToken wakeup_event_token_; |
| |
| // This mutex covers the next two variables. |
| starboard::Mutex unhandled_wakeup_count_mutex_; |
| // Number of times wake up has been called, and not handled. |
| std::int32_t unhandled_wakeup_count_; |
| // The WSAEvent that is set by Wakeup(); |
| sbwin32::AutoEventHandle wakeup_event_; |
| }; |
| #pragma warning(pop) |
| |
| #endif // STARBOARD_SHARED_WIN32_SOCKET_WAITER_INTERNAL_H_ |