blob: 193361b77735a3ded9b28d4c3dc3d61b68898aa9 [file] [log] [blame]
// Copyright 2017 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 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/mutex.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.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(SbTime duration);
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 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_;
// Number of times wake up has been called, and not handled.
starboard::Mutex unhandled_wakeup_count_mutex_;
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_