VirtualBox

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

Last change on this file since 78352 was 76553, checked in by vboxsync, 6 years ago

scm --update-copyright-year

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