mirror of
https://gitlab.uni-freiburg.de/opensourcevdi/spice
synced 2025-12-26 06:32:44 +00:00
210 lines
4.8 KiB
C++
210 lines
4.8 KiB
C++
/*
|
|
Copyright (C) 2009 Red Hat, Inc.
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU Lesser General Public
|
|
License as published by the Free Software Foundation; either
|
|
version 2.1 of the License, or (at your option) any later version.
|
|
|
|
This library is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Lesser General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Lesser General Public
|
|
License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "common.h"
|
|
#include "event_sources.h"
|
|
#include "debug.h"
|
|
#include "utils.h"
|
|
|
|
bool EventSources_p::process_system_events()
|
|
{
|
|
MSG msg;
|
|
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
|
|
|
|
if (msg.message == WM_QUIT) {
|
|
return true;
|
|
}
|
|
TranslateMessage(&msg);
|
|
DispatchMessage(&msg);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void EventSources_p::add_event(HANDLE event, EventSource* source)
|
|
{
|
|
int size = _events.size();
|
|
_events.resize(size + 1);
|
|
_handles.resize(size + 1);
|
|
_events[size] = source;
|
|
_handles[size] = event;
|
|
}
|
|
|
|
void EventSources_p::remove_event(EventSource* source)
|
|
{
|
|
int size = _events.size();
|
|
for (int i = 0; i < size; i++) {
|
|
if (_events[i] == source) {
|
|
for (i++; i < size; i++) {
|
|
_events[i - 1] = _events[i];
|
|
_handles[i - 1] = _handles[i];
|
|
}
|
|
_events.resize(size - 1);
|
|
_handles.resize(size - 1);
|
|
return;
|
|
}
|
|
}
|
|
THROW("event not found");
|
|
}
|
|
|
|
EventSources::EventSources()
|
|
{
|
|
}
|
|
|
|
EventSources::~EventSources()
|
|
{
|
|
}
|
|
|
|
bool EventSources::wait_events(int timeout_ms)
|
|
{
|
|
if (_handles.empty()) {
|
|
if (WaitMessage()) {
|
|
return process_system_events();
|
|
} else {
|
|
THROW("wait failed %d", GetLastError());
|
|
}
|
|
}
|
|
|
|
DWORD wait_res = MsgWaitForMultipleObjectsEx(_handles.size(), &_handles[0], timeout_ms,
|
|
QS_ALLINPUT, 0);
|
|
if (wait_res == WAIT_TIMEOUT) {
|
|
return false;
|
|
}
|
|
|
|
if (wait_res == WAIT_FAILED) {
|
|
THROW("wait failed %d", GetLastError());
|
|
}
|
|
|
|
int event_index = wait_res - WAIT_OBJECT_0;
|
|
if (event_index == _handles.size()) {
|
|
return process_system_events();
|
|
} else if ((event_index >= 0) && (event_index < (int)_handles.size())) {
|
|
_events[event_index]->action();
|
|
return false;
|
|
} else {
|
|
THROW("invalid event id");
|
|
}
|
|
}
|
|
|
|
void EventSources::add_socket(Socket& socket)
|
|
{
|
|
HANDLE event = CreateEvent(NULL, FALSE, FALSE, NULL);
|
|
if (!event) {
|
|
THROW("create event failed");
|
|
}
|
|
if (WSAEventSelect(socket.get_socket(), event,
|
|
FD_READ | FD_WRITE | FD_CLOSE) == SOCKET_ERROR) {
|
|
CloseHandle(event);
|
|
THROW("event select failed");
|
|
}
|
|
add_event(event, &socket);
|
|
}
|
|
|
|
void EventSources::remove_socket(Socket& socket)
|
|
{
|
|
int size = _events.size();
|
|
for (int i = 0; i < size; i++) {
|
|
if (_events[i] == &socket) {
|
|
if (WSAEventSelect(socket.get_socket(), NULL, 0) == SOCKET_ERROR) {
|
|
THROW("event select failed");
|
|
}
|
|
u_long arg = 0;
|
|
if (ioctlsocket(socket.get_socket(), FIONBIO, &arg) == SOCKET_ERROR) {
|
|
THROW("set blocking mode failed");
|
|
}
|
|
CloseHandle(_handles[i]);
|
|
for (i++; i < size; i++) {
|
|
_events[i - 1] = _events[i];
|
|
_handles[i - 1] = _handles[i];
|
|
}
|
|
_events.resize(size - 1);
|
|
_handles.resize(size - 1);
|
|
return;
|
|
}
|
|
}
|
|
THROW("socket not found");
|
|
}
|
|
|
|
void EventSources::add_handle(Handle& handle)
|
|
{
|
|
add_event(handle.get_handle(), &handle);
|
|
}
|
|
|
|
void EventSources::remove_handle(Handle& handle)
|
|
{
|
|
remove_event(&handle);
|
|
}
|
|
|
|
Handle_p::Handle_p()
|
|
{
|
|
if (!(_event = CreateEvent(NULL, FALSE, FALSE, NULL))) {
|
|
THROW("create event failed");
|
|
}
|
|
}
|
|
|
|
Handle_p::~Handle_p()
|
|
{
|
|
CloseHandle(_event);
|
|
}
|
|
|
|
void EventSources::add_trigger(Trigger& trigger)
|
|
{
|
|
add_event(trigger.get_handle(), &trigger);
|
|
}
|
|
|
|
void EventSources::remove_trigger(Trigger& trigger)
|
|
{
|
|
remove_event(&trigger);
|
|
}
|
|
|
|
|
|
EventSources::Trigger::Trigger()
|
|
{
|
|
}
|
|
|
|
EventSources::Trigger::~Trigger()
|
|
{
|
|
}
|
|
|
|
|
|
void EventSources::Trigger::trigger()
|
|
{
|
|
if (!SetEvent(_event)) {
|
|
THROW("set event failed");
|
|
}
|
|
}
|
|
|
|
void EventSources::Trigger::reset()
|
|
{
|
|
if (!ResetEvent(_event)) {
|
|
THROW("set event failed");
|
|
}
|
|
}
|
|
|
|
void EventSources::Trigger::action()
|
|
{
|
|
on_event();
|
|
}
|
|
|
|
void EventSources::add_file(File& file)
|
|
{
|
|
}
|
|
|
|
void EventSources::remove_file(File& file)
|
|
{
|
|
}
|
|
|