Kaido Kert | da45c04 | 2022-05-09 11:08:54 -0700 | [diff] [blame] | 1 | // Copyright 2017 The Cobalt Authors. All Rights Reserved. |
| 2 | // |
| 3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | // you may not use this file except in compliance with the License. |
| 5 | // You may obtain a copy of the License at |
| 6 | // |
| 7 | // http://www.apache.org/licenses/LICENSE-2.0 |
| 8 | // |
| 9 | // Unless required by applicable law or agreed to in writing, software |
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, |
| 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 | // See the License for the specific language governing permissions and |
| 13 | // limitations under the License. |
| 14 | |
| 15 | #ifndef STARBOARD_SHARED_WIN32_SOCKET_WAITER_INTERNAL_H_ |
| 16 | #define STARBOARD_SHARED_WIN32_SOCKET_WAITER_INTERNAL_H_ |
| 17 | |
| 18 | #include <windows.h> |
| 19 | #include <winsock2.h> |
| 20 | |
| 21 | #include <deque> |
| 22 | #include <memory> |
| 23 | #include <unordered_map> |
| 24 | #include <vector> |
| 25 | |
| 26 | #include "starboard/common/mutex.h" |
| 27 | #include "starboard/common/optional.h" |
| 28 | #include "starboard/common/socket.h" |
| 29 | #include "starboard/shared/internal_only.h" |
| 30 | #include "starboard/shared/win32/auto_event_handle.h" |
| 31 | #include "starboard/shared/win32/socket_internal.h" |
| 32 | #include "starboard/socket_waiter.h" |
| 33 | #include "starboard/thread.h" |
| 34 | #include "starboard/types.h" |
| 35 | |
| 36 | namespace sbwin32 = starboard::shared::win32; |
| 37 | |
| 38 | #pragma warning(push) |
| 39 | |
| 40 | // SbSocketWaiterPrivate is defined as a struct, but for windows implementation |
| 41 | // enough functionality has been added so that it warrants being a class |
| 42 | // per Google's C++ style guide. This mismatch causes the Microsoft's compiler |
| 43 | // to generate a warning. |
| 44 | #pragma warning(disable : 4099) |
| 45 | class SbSocketWaiterPrivate { |
| 46 | public: |
| 47 | SbSocketWaiterPrivate(); |
| 48 | ~SbSocketWaiterPrivate(); |
| 49 | |
| 50 | // These methods implement the SbSocketWaiter API defined in socket_waiter.h. |
| 51 | bool Add(SbSocket socket, |
| 52 | void* context, |
| 53 | SbSocketWaiterCallback callback, |
| 54 | int interests, |
| 55 | bool persistent); |
| 56 | bool Remove(SbSocket socket); |
| 57 | void Wait(); |
Kaido Kert | b108943 | 2024-03-18 19:46:49 -0700 | [diff] [blame] | 58 | SbSocketWaiterResult WaitTimed(int64_t duration_usec); |
Kaido Kert | da45c04 | 2022-05-09 11:08:54 -0700 | [diff] [blame] | 59 | void WakeUp(); |
| 60 | void HandleWakeUpRead(); |
| 61 | |
| 62 | private: |
| 63 | // A registration of a socket with a socket waiter. |
| 64 | struct Waitee { |
| 65 | Waitee(SbSocketWaiter waiter, |
| 66 | SbSocket socket, |
| 67 | void* context, |
| 68 | SbSocketWaiterCallback callback, |
| 69 | int interests, |
| 70 | bool persistent) |
| 71 | : waiter(waiter), |
| 72 | socket(socket), |
| 73 | context(context), |
| 74 | callback(callback), |
| 75 | interests(interests), |
| 76 | persistent(persistent) {} |
| 77 | // The waiter this event is registered with. |
| 78 | SbSocketWaiter waiter; |
| 79 | |
| 80 | // The socket registered with the waiter. |
| 81 | SbSocket socket; |
| 82 | |
| 83 | // A context value that will be passed to the callback. |
| 84 | void* context; |
| 85 | |
| 86 | // The callback to call when one or more registered interests become ready. |
| 87 | SbSocketWaiterCallback callback; |
| 88 | |
| 89 | // The set of interests registered with the waiter. |
| 90 | int interests; |
| 91 | |
| 92 | // Whether this Waitee should stay registered after the next callback. |
| 93 | bool persistent; |
| 94 | }; |
| 95 | |
| 96 | class WaiteeRegistry { |
| 97 | public: |
| 98 | typedef int64_t LookupToken; |
| 99 | typedef std::deque<std::unique_ptr<Waitee>> Waitees; |
| 100 | typedef std::unordered_map<SbSocket, std::size_t> SocketToIndex; |
| 101 | |
| 102 | WSAEVENT* GetHandleArray() { return socket_events_.data(); } |
| 103 | std::size_t GetHandleArraySize() { return socket_events_.size(); } |
| 104 | const Waitees& GetWaitees() const { return waitees_; } |
| 105 | |
| 106 | // Gets the Waitee associated with the given socket, or nullptr. |
| 107 | Waitee* GetWaitee(SbSocket socket); |
| 108 | |
| 109 | // Gets the index by socket |
| 110 | starboard::optional<int64_t> GetIndex(SbSocket socket); |
| 111 | |
| 112 | // Gets the Waitee by index. |
| 113 | Waitee* GetWaiteeByIndex(LookupToken socket_index); |
| 114 | |
| 115 | // Returns the index of the event. |
| 116 | LookupToken AddSocketEventAndWaitee(WSAEVENT socket_event, |
| 117 | std::unique_ptr<Waitee> waitee); |
| 118 | // Returns true if socket was found, and removed. |
| 119 | bool RemoveSocket(SbSocket socket); |
| 120 | |
| 121 | private: |
| 122 | SocketToIndex socket_to_index_map_; |
| 123 | std::vector<WSAEVENT> socket_events_; |
| 124 | std::deque<std::unique_ptr<Waitee>> waitees_; |
| 125 | }; |
| 126 | |
| 127 | void SignalWakeupEvent(); |
| 128 | void ResetWakeupEvent(); |
| 129 | |
| 130 | bool CheckSocketWaiterIsThis(SbSocket socket); |
| 131 | |
| 132 | // The thread this waiter was created on. Immutable, so accessible from any |
| 133 | // thread. |
Kaido Kert | 25902c6 | 2024-06-17 17:10:28 -0700 | [diff] [blame^] | 134 | const pthread_t thread_; |
Kaido Kert | da45c04 | 2022-05-09 11:08:54 -0700 | [diff] [blame] | 135 | |
| 136 | // The registry of currently registered Waitees. |
| 137 | WaiteeRegistry waitees_; |
| 138 | WaiteeRegistry::LookupToken wakeup_event_token_; |
| 139 | |
| 140 | // This mutex covers the next two variables. |
| 141 | starboard::Mutex unhandled_wakeup_count_mutex_; |
| 142 | // Number of times wake up has been called, and not handled. |
| 143 | std::int32_t unhandled_wakeup_count_; |
| 144 | // The WSAEvent that is set by Wakeup(); |
| 145 | sbwin32::AutoEventHandle wakeup_event_; |
| 146 | }; |
| 147 | #pragma warning(pop) |
| 148 | |
| 149 | #endif // STARBOARD_SHARED_WIN32_SOCKET_WAITER_INTERNAL_H_ |