VirtualBox

source: vbox/trunk/src/VBox/Main/glue/EventQueue.cpp@ 46652

Last change on this file since 46652 was 46652, checked in by vboxsync, 12 years ago

Main/glue/EventQueue: missing initialization and indentation

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 5.7 KB
Line 
1/* $Id: EventQueue.cpp 46652 2013-06-19 12:09:03Z vboxsync $ */
2/** @file
3 * Event queue class declaration.
4 */
5
6/*
7 * Copyright (C) 2013 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.215389.xyz. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18/** @todo Adapt / update documentation! */
19
20#include "VBox/com/EventQueue.h"
21
22#include <iprt/asm.h>
23#include <new> /* For bad_alloc. */
24
25#include <iprt/err.h>
26#include <iprt/semaphore.h>
27#include <iprt/time.h>
28#include <iprt/thread.h>
29#include <iprt/log.h>
30
31namespace com
32{
33
34// EventQueue class
35////////////////////////////////////////////////////////////////////////////////
36
37EventQueue::EventQueue(void)
38 : mShutdown(false)
39{
40 int rc = RTCritSectInit(&mCritSect);
41 AssertRC(rc);
42
43 rc = RTSemEventCreate(&mSemEvent);
44 AssertRC(rc);
45}
46
47EventQueue::~EventQueue(void)
48{
49 int rc = RTCritSectDelete(&mCritSect);
50 AssertRC(rc);
51
52 rc = RTSemEventDestroy(mSemEvent);
53 AssertRC(rc);
54
55 EventQueueListIterator it = mEvents.begin();
56 while (it != mEvents.end())
57 {
58 (*it)->Release();
59 it = mEvents.erase(it);
60 }
61}
62
63/**
64 * Process events pending on this event queue, and wait up to given timeout, if
65 * nothing is available.
66 *
67 * Must be called on same thread this event queue was created on.
68 *
69 * @param cMsTimeout The timeout specified as milliseconds. Use
70 * RT_INDEFINITE_WAIT to wait till an event is posted on the
71 * queue.
72 *
73 * @returns VBox status code
74 * @retval VINF_SUCCESS if one or more messages was processed.
75 * @retval VERR_TIMEOUT if cMsTimeout expired.
76 * @retval VERR_INVALID_CONTEXT if called on the wrong thread.
77 * @retval VERR_INTERRUPTED if interruptEventQueueProcessing was called.
78 * On Windows will also be returned when WM_QUIT is encountered.
79 * On Darwin this may also be returned when the native queue is
80 * stopped or destroyed/finished.
81 * @retval VINF_INTERRUPTED if the native system call was interrupted by a
82 * an asynchronous event delivery (signal) or just felt like returning
83 * out of bounds. On darwin it will also be returned if the queue is
84 * stopped.
85 */
86int EventQueue::processEventQueue(RTMSINTERVAL cMsTimeout)
87{
88 bool fWait;
89 int rc = RTCritSectEnter(&mCritSect);
90 if (RT_SUCCESS(rc))
91 {
92 fWait = mEvents.size() == 0;
93 if (!fWait)
94 {
95 int rc2 = RTCritSectLeave(&mCritSect);
96 AssertRC(rc2);
97 }
98 }
99 else
100 fWait = false;
101
102 if (fWait)
103 {
104 int rc2 = RTCritSectLeave(&mCritSect);
105 AssertRC(rc2);
106
107 rc = RTSemEventWaitNoResume(mSemEvent, cMsTimeout);
108 }
109
110 if (RT_SUCCESS(rc))
111 {
112 if (ASMAtomicReadBool(&mShutdown))
113 return VERR_INTERRUPTED;
114
115 if (fWait)
116 rc = RTCritSectEnter(&mCritSect);
117 if (RT_SUCCESS(rc))
118 {
119 EventQueueListIterator it = mEvents.begin();
120 if (it != mEvents.end())
121 {
122 Event *pEvent = *it;
123 AssertPtr(pEvent);
124
125 mEvents.erase(it);
126
127 int rc2 = RTCritSectLeave(&mCritSect);
128 if (RT_SUCCESS(rc))
129 rc = rc2;
130
131 pEvent->handler();
132 pEvent->Release();
133 }
134 else
135 {
136 int rc2 = RTCritSectLeave(&mCritSect);
137 if (RT_SUCCESS(rc))
138 rc = rc2;
139 }
140 }
141 }
142
143 Assert(rc != VERR_TIMEOUT || cMsTimeout != RT_INDEFINITE_WAIT);
144 return rc;
145}
146
147/**
148 * Interrupt thread waiting on event queue processing.
149 *
150 * Can be called on any thread.
151 *
152 * @returns VBox status code.
153 */
154int EventQueue::interruptEventQueueProcessing(void)
155{
156 ASMAtomicWriteBool(&mShutdown, true);
157
158 return RTSemEventSignal(mSemEvent);
159}
160
161/**
162 * Posts an event to this event loop asynchronously.
163 *
164 * @param event the event to post, must be allocated using |new|
165 * @return TRUE if successful and false otherwise
166 */
167BOOL EventQueue::postEvent(Event *pEvent)
168{
169 int rc = RTCritSectEnter(&mCritSect);
170 if (RT_SUCCESS(rc))
171 {
172 try
173 {
174 if (pEvent)
175 {
176 pEvent->AddRef();
177 mEvents.push_back(pEvent);
178 }
179 else /* No locking, since we're already in our crit sect. */
180 mShutdown = true;
181
182 size_t cEvents = mEvents.size();
183 if (cEvents > _1K) /** @todo Make value configurable? */
184 {
185 static int s_cBitchedAboutLotEvents = 0;
186 if (s_cBitchedAboutLotEvents < 10)
187 LogRel(("Warning: Event queue received lots of events (%zu), expect delayed event handling (%d/10)\n",
188 cEvents, ++s_cBitchedAboutLotEvents));
189 }
190
191 /* Leave critical section before signalling event. */
192 rc = RTCritSectLeave(&mCritSect);
193 if (RT_SUCCESS(rc))
194 {
195 int rc2 = RTSemEventSignal(mSemEvent);
196 AssertRC(rc2);
197 }
198 }
199 catch (std::bad_alloc &ba)
200 {
201 NOREF(ba);
202 rc = VERR_NO_MEMORY;
203 }
204
205 if (RT_FAILURE(rc))
206 {
207 int rc2 = RTCritSectLeave(&mCritSect);
208 AssertRC(rc2);
209 }
210 }
211
212 return RT_SUCCESS(rc) ? TRUE : FALSE;
213}
214
215}
216/* namespace com */
Note: See TracBrowser for help on using the repository browser.

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