VirtualBox

source: vbox/trunk/src/VBox/Frontends/VBoxSDL/Helper.cpp@ 103914

Last change on this file since 103914 was 98103, checked in by vboxsync, 23 months ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 5.1 KB
Line 
1/* $Id: Helper.cpp 98103 2023-01-17 14:15:46Z vboxsync $ */
2/** @file
3 *
4 * VBox frontends: VBoxSDL (simple frontend based on SDL):
5 * Miscellaneous helpers
6 */
7
8/*
9 * Copyright (C) 2006-2023 Oracle and/or its affiliates.
10 *
11 * This file is part of VirtualBox base platform packages, as
12 * available from https://www.virtualbox.org.
13 *
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation, in version 3 of the
17 * License.
18 *
19 * This program is distributed in the hope that it will be useful, but
20 * WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 * General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, see <https://www.gnu.org/licenses>.
26 *
27 * SPDX-License-Identifier: GPL-3.0-only
28 */
29
30#define LOG_GROUP LOG_GROUP_GUI
31#include <iprt/errcore.h>
32#include <VBox/log.h>
33#include <iprt/asm.h>
34#include <iprt/assert.h>
35#include <iprt/thread.h>
36#include <iprt/semaphore.h>
37#include "VBoxSDL.h"
38#include "Helper.h"
39
40
41/**
42 * Globals
43 */
44
45
46#ifdef USE_XPCOM_QUEUE_THREAD
47
48/** global flag indicating that the event queue thread should terminate */
49static bool volatile g_fTerminateXPCOMQueueThread = false;
50
51/** How many XPCOM user events are on air. Only allow one pending event to
52 * prevent an overflow of the SDL event queue. */
53static volatile int32_t g_s32XPCOMEventsPending;
54
55/** Semaphore the XPCOM event thread will sleep on while it waits for the main thread to process pending requests. */
56RTSEMEVENT g_EventSemXPCOMQueueThread = NULL;
57
58/**
59 * Thread method to wait for XPCOM events and notify the SDL thread.
60 *
61 * @returns Error code
62 * @param thread Thread ID
63 * @param pvUser User specific parameter, the file descriptor
64 * of the event queue socket
65 */
66DECLCALLBACK(int) xpcomEventThread(RTTHREAD hThreadSelf, void *pvUser)
67{
68 RT_NOREF(hThreadSelf);
69 int eqFD = (intptr_t)pvUser;
70 unsigned cErrors = 0;
71 int rc;
72
73 /* Wait with the processing till the main thread needs it. */
74 RTSemEventWait(g_EventSemXPCOMQueueThread, 2500);
75
76 do
77 {
78 fd_set fdset;
79 FD_ZERO(&fdset);
80 FD_SET(eqFD, &fdset);
81 int n = select(eqFD + 1, &fdset, NULL, NULL, NULL);
82
83 /* are there any events to process? */
84 if ((n > 0) && !g_fTerminateXPCOMQueueThread)
85 {
86 /*
87 * Wait until all XPCOM events are processed. 1s just for sanity.
88 */
89 int iWait = 1000;
90 /*
91 * Don't post an event if there is a pending XPCOM event to prevent an
92 * overflow of the SDL event queue.
93 */
94 if (g_s32XPCOMEventsPending < 1)
95 {
96 /*
97 * Post the event and wait for it to be processed. If we don't wait,
98 * we'll flood the queue on SMP systems and when the main thread is busy.
99 * In the event of a push error, we'll yield the timeslice and retry.
100 */
101 SDL_Event event = {0};
102 event.type = SDL_USEREVENT;
103 event.user.type = SDL_USER_EVENT_XPCOM_EVENTQUEUE;
104 rc = SDL_PushEvent(&event);
105 if (!rc)
106 {
107 /* success */
108 ASMAtomicIncS32(&g_s32XPCOMEventsPending);
109 cErrors = 0;
110 }
111 else
112 {
113 /* failure */
114 cErrors++;
115 if (!RTThreadYield())
116 RTThreadSleep(2);
117 iWait = (cErrors >= 10) ? RT_MIN(cErrors - 8, 50) : 0;
118 }
119 }
120 else
121 Log2(("not enqueueing SDL XPCOM event (%d)\n", g_s32XPCOMEventsPending));
122
123 if (iWait)
124 RTSemEventWait(g_EventSemXPCOMQueueThread, iWait);
125 }
126 } while (!g_fTerminateXPCOMQueueThread);
127 return VINF_SUCCESS;
128}
129
130/**
131 * Creates the XPCOM event thread
132 *
133 * @returns VBOX status code
134 * @param eqFD XPCOM event queue file descriptor
135 */
136int startXPCOMEventQueueThread(int eqFD)
137{
138 int rc = RTSemEventCreate(&g_EventSemXPCOMQueueThread);
139 if (RT_SUCCESS(rc))
140 {
141 RTTHREAD Thread;
142 rc = RTThreadCreate(&Thread, xpcomEventThread, (void *)(intptr_t)eqFD,
143 0, RTTHREADTYPE_MSG_PUMP, 0, "XPCOMEvent");
144 }
145 AssertRC(rc);
146 return rc;
147}
148
149/**
150 * Notify the XPCOM thread that we consumed an XPCOM event.
151 */
152void consumedXPCOMUserEvent(void)
153{
154 ASMAtomicDecS32(&g_s32XPCOMEventsPending);
155}
156
157/**
158 * Signal to the XPCOM even queue thread that it should select for more events.
159 */
160void signalXPCOMEventQueueThread(void)
161{
162 int rc = RTSemEventSignal(g_EventSemXPCOMQueueThread);
163 AssertRC(rc);
164}
165
166/**
167 * Indicates to the XPCOM thread that it should terminate now.
168 */
169void terminateXPCOMQueueThread(void)
170{
171 g_fTerminateXPCOMQueueThread = true;
172 if (g_EventSemXPCOMQueueThread)
173 {
174 RTSemEventSignal(g_EventSemXPCOMQueueThread);
175 RTThreadYield();
176 }
177}
178
179#endif /* USE_XPCOM_QUEUE_THREAD */
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette