Changeset 46649 in vbox
- Timestamp:
- Jun 19, 2013 11:47:32 AM (12 years ago)
- Location:
- trunk
- Files:
-
- 2 added
- 20 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk
- Property svn:mergeinfo changed
/branches/VBox-4.1 merged: 82579,85941 /branches/VBox-4.2 merged: 86229-86230,86234,86529 /branches/andy/guestctrl20 (added) merged: 78916,78930
- Property svn:mergeinfo changed
-
trunk/include/VBox/com/EventQueue.h
r45125 r46649 1 /* $Id$ */ 1 2 /** @file 2 * MS COM / XPCOM Abstraction Layer - Event and EventQueue class declaration.3 * Event queue class declaration. 3 4 */ 4 5 5 6 /* 6 * Copyright (C) 20 06-2012Oracle Corporation7 * Copyright (C) 2013 Oracle Corporation 7 8 * 8 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 27 28 #define ___VBox_com_EventQueue_h 28 29 29 #ifndef VBOX_WITH_XPCOM 30 # include <Windows.h> 31 #else // VBOX_WITH_XPCOM 32 # include <nsEventQueueUtils.h> 33 #endif // VBOX_WITH_XPCOM 30 #include <list> 31 32 #include <iprt/asm.h> 33 #include <iprt/critsect.h> 34 34 35 35 #include <VBox/com/defs.h> … … 52 52 public: 53 53 54 Event() {} 55 virtual ~Event() {}; 54 Event(void) : 55 mRefCount(0) { } 56 virtual ~Event(void) { AssertMsg(!mRefCount, 57 ("Reference count of event=%p not 0 on destruction (is %RU32)\n", 58 this, mRefCount)); } 59 public: 60 61 uint32_t AddRef(void) { return ASMAtomicIncU32(&mRefCount); } 62 void Release(void) 63 { 64 Assert(mRefCount); 65 uint32_t cRefs = ASMAtomicDecU32(&mRefCount); 66 if (!cRefs) 67 delete this; 68 } 56 69 57 70 protected: … … 63 76 * @return reserved, should be NULL. 64 77 */ 65 virtual void *handler( ) { return NULL; }78 virtual void *handler(void) { return NULL; } 66 79 67 80 friend class EventQueue; 81 82 protected: 83 84 /** The event's reference count. */ 85 uint32_t mRefCount; 68 86 }; 87 88 typedef std::list< Event* > EventQueueList; 89 typedef std::list< Event* >::iterator EventQueueListIterator; 90 typedef std::list< Event* >::const_iterator EventQueueListIteratorConst; 69 91 70 92 /** 71 93 * Simple event queue. 72 *73 * When using XPCOM, this will map onto the default XPCOM queue for the thread.74 * So, if a queue is created on the main thread, it automatically processes75 * XPCOM/IPC events while waiting.76 *77 * When using Windows, Darwin and OS/2, this will map onto the native thread78 * queue/runloop. So, windows messages and what not will be processed while79 * waiting for events.80 *81 * @note It is intentional that there is no way to retrieve arbitrary82 * events and controlling their processing. There is no use case which83 * warrants introducing the complexity of platform independent events.84 94 */ 85 95 class EventQueue … … 87 97 public: 88 98 89 EventQueue(); 90 ~EventQueue(); /** @todo r=andy Why not virtual? */ 99 EventQueue(void); 100 virtual ~EventQueue(void); 101 102 public: 91 103 92 104 BOOL postEvent(Event *event); 93 105 int processEventQueue(RTMSINTERVAL cMsTimeout); 94 106 int interruptEventQueueProcessing(); 95 int getSelectFD();96 static int init();97 static int uninit();98 static EventQueue *getMainEventQueue();99 100 #ifdef VBOX_WITH_XPCOM101 already_AddRefed<nsIEventQueue> getIEventQueue()102 {103 return mEventQ.get();104 }105 #else106 static int dispatchMessageOnWindows(MSG const *pMsg, int rc);107 #endif108 107 109 108 private: 110 static EventQueue *sMainQueue;111 109 112 #ifndef VBOX_WITH_XPCOM 113 114 /** The thread which the queue belongs to. */ 115 DWORD mThreadId; 116 /** Duplicated thread handle for MsgWaitForMultipleObjects. */ 117 HANDLE mhThread; 118 119 #else // VBOX_WITH_XPCOM 120 121 /** Whether it was created (and thus needs destroying) or if a queue already 122 * associated with the thread was used. */ 123 bool mEQCreated; 124 125 /** Whether event processing should be interrupted. */ 126 bool mInterrupted; 127 128 nsCOMPtr <nsIEventQueue> mEventQ; 129 nsCOMPtr <nsIEventQueueService> mEventQService; 130 131 static void *PR_CALLBACK plEventHandler(PLEvent *self); 132 static void PR_CALLBACK plEventDestructor(PLEvent *self); 133 134 #endif // VBOX_WITH_XPCOM 110 /** Critical section for serializing access to this 111 * event queue. */ 112 RTCRITSECT mCritSect; 113 /** Event semaphore for getting notified on new 114 * events being handled. */ 115 RTSEMEVENT mSemEvent; 116 /** The actual event queue, implemented as a list. */ 117 EventQueueList mEvents; 118 /** Shutdown indicator. */ 119 bool mShutdown; 135 120 }; 136 121 -
trunk/src/VBox
- Property svn:mergeinfo changed
/branches/VBox-4.1/src/VBox merged: 85941 /branches/VBox-4.2/src/VBox merged: 86529
- Property svn:mergeinfo changed
-
trunk/src/VBox/Frontends
- Property svn:mergeinfo changed
/branches/VBox-4.1/src/VBox/Frontends merged: 85941 /branches/VBox-4.2/src/VBox/Frontends (added) merged: 86529
- Property svn:mergeinfo changed
-
trunk/src/VBox/Frontends/VBoxAutostart/VBoxAutostart-posix.cpp
r43967 r46649 5 5 6 6 /* 7 * Copyright (C) 2012 Oracle Corporation7 * Copyright (C) 2012-2013 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 27 27 #include <VBox/com/errorprint.h> 28 28 29 #include <VBox/com/ EventQueue.h>29 #include <VBox/com/NativeEventQueue.h> 30 30 #include <VBox/com/listeners.h> 31 31 #include <VBox/com/VirtualBox.h> … … 136 136 Bstr bstrOperationDescription; 137 137 138 EventQueue::getMainEventQueue()->processEventQueue(0);138 NativeEventQueue::getMainEventQueue()->processEventQueue(0); 139 139 140 140 ULONG cOperations = 1; … … 205 205 progress->WaitForCompletion(100); 206 206 207 EventQueue::getMainEventQueue()->processEventQueue(0);207 NativeEventQueue::getMainEventQueue()->processEventQueue(0); 208 208 hrc = progress->COMGETTER(Completed(&fCompleted)); 209 209 } … … 560 560 561 561 autostartConfigAstDestroy(pCfgAst); 562 EventQueue::getMainEventQueue()->processEventQueue(0);562 NativeEventQueue::getMainEventQueue()->processEventQueue(0); 563 563 564 564 autostartShutdown(); -
trunk/src/VBox/Frontends/VBoxAutostart/VBoxAutostart-win.cpp
r44528 r46649 5 5 6 6 /* 7 * Copyright (C) 2012 Oracle Corporation7 * Copyright (C) 2012-2013 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 28 28 #include <VBox/com/errorprint.h> 29 29 30 #include <VBox/com/ EventQueue.h>30 #include <VBox/com/NativeEventQueue.h> 31 31 #include <VBox/com/listeners.h> 32 32 #include <VBox/com/VirtualBox.h> … … 93 93 Bstr bstrOperationDescription; 94 94 95 EventQueue::getMainEventQueue()->processEventQueue(0);95 NativeEventQueue::getMainEventQueue()->processEventQueue(0); 96 96 97 97 ULONG cOperations = 1; … … 126 126 progress->WaitForCompletion(100); 127 127 128 EventQueue::getMainEventQueue()->processEventQueue(0);128 NativeEventQueue::getMainEventQueue()->processEventQueue(0); 129 129 hrc = progress->COMGETTER(Completed(&fCompleted)); 130 130 } -
trunk/src/VBox/Frontends/VBoxBalloonCtrl/VBoxWatchdog.cpp
r46138 r46649 5 5 6 6 /* 7 * Copyright (C) 2011-201 2Oracle Corporation7 * Copyright (C) 2011-2013 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 28 28 # include <VBox/com/errorprint.h> 29 29 30 # include <VBox/com/ EventQueue.h>30 # include <VBox/com/NativeEventQueue.h> 31 31 # include <VBox/com/listeners.h> 32 32 # include <VBox/com/VirtualBox.h> … … 132 132 static ComPtr<IEventSource> g_pEventSourceClient = NULL; 133 133 static ComPtr<IEventListener> g_pVBoxEventListener = NULL; 134 static EventQueue*g_pEventQ = NULL;134 static NativeEventQueue *g_pEventQ = NULL; 135 135 136 136 /* Prototypes. */ … … 685 685 { 686 686 /* Initialize global weak references. */ 687 g_pEventQ = com:: EventQueue::getMainEventQueue();687 g_pEventQ = com::NativeEventQueue::getMainEventQueue(); 688 688 689 689 /* … … 1148 1148 RTEXITCODE rcExit = watchdogMain(&handlerArg); 1149 1149 1150 EventQueue::getMainEventQueue()->processEventQueue(0);1150 NativeEventQueue::getMainEventQueue()->processEventQueue(0); 1151 1151 1152 1152 watchdogShutdown(); -
trunk/src/VBox/Frontends/VBoxHeadless
- Property svn:mergeinfo changed
/branches/VBox-4.1/src/VBox/Frontends/VBoxHeadless merged: 85941 /branches/VBox-4.2/src/VBox/Frontends/VBoxHeadless (added) merged: 86529
- Property svn:mergeinfo changed
-
trunk/src/VBox/Frontends/VBoxHeadless/VBoxHeadless.cpp
r45373 r46649 22 22 #include <VBox/com/ErrorInfo.h> 23 23 #include <VBox/com/errorprint.h> 24 #include <VBox/com/ EventQueue.h>24 #include <VBox/com/NativeEventQueue.h> 25 25 26 26 #include <VBox/com/VirtualBox.h> … … 74 74 /* global weak references (for event handlers) */ 75 75 static IConsole *gConsole = NULL; 76 static EventQueue *gEventQ = NULL;76 static NativeEventQueue *gEventQ = NULL; 77 77 78 78 /* flag whether frontend should terminate */ … … 194 194 AssertComRC(hrc); 195 195 196 Bstr strValue; 197 hrc = pChangedEvent->COMGETTER(Value)(strValue.asOutParam()); 198 AssertComRC(hrc); 199 196 200 Utf8Str utf8Key = strKey; 197 LogRelFlow(("Guest property \"%s\" has been changed\n", utf8Key.c_str())); 201 Utf8Str utf8Value = strValue; 202 LogRelFlow(("Guest property \"%s\" has been changed to \"%s\"\n", 203 utf8Key.c_str(), utf8Value.c_str())); 198 204 199 205 if (utf8Key.equals("/VirtualBox/GuestInfo/OS/NoLoggedInUsers")) 200 206 { 201 Bstr strValue;202 pChangedEvent->COMGETTER(Value)(strValue.asOutParam());203 Utf8Str utf8Value = strValue;204 205 207 LogRelFlow(("Guest indicates that there %s logged in users\n", 206 208 utf8Value.equals("true") ? "are no" : "are")); … … 1103 1105 /* initialize global references */ 1104 1106 gConsole = console; 1105 gEventQ = com:: EventQueue::getMainEventQueue();1107 gEventQ = com::NativeEventQueue::getMainEventQueue(); 1106 1108 1107 1109 /* VirtualBoxClient events registration. */ -
trunk/src/VBox/Frontends/VBoxManage/VBoxManage.cpp
r45356 r46649 27 27 # include <VBox/com/ErrorInfo.h> 28 28 # include <VBox/com/errorprint.h> 29 # include <VBox/com/ EventQueue.h>29 # include <VBox/com/NativeEventQueue.h> 30 30 31 31 # include <VBox/com/VirtualBox.h> … … 91 91 Bstr bstrOperationDescription; 92 92 93 EventQueue::getMainEventQueue()->processEventQueue(0);93 NativeEventQueue::getMainEventQueue()->processEventQueue(0); 94 94 95 95 ULONG cOperations = 1; … … 199 199 progress->WaitForCompletion(100); 200 200 201 EventQueue::getMainEventQueue()->processEventQueue(0);201 NativeEventQueue::getMainEventQueue()->processEventQueue(0); 202 202 hrc = progress->COMGETTER(Completed(&fCompleted)); 203 203 } … … 585 585 session->UnlockMachine(); 586 586 587 EventQueue::getMainEventQueue()->processEventQueue(0);587 NativeEventQueue::getMainEventQueue()->processEventQueue(0); 588 588 589 589 // end "all-stuff" scope -
trunk/src/VBox/Frontends/VBoxManage/VBoxManageGuestCtrl.cpp
r46524 r46649 5 5 6 6 /* 7 * Copyright (C) 2010-201 2Oracle Corporation7 * Copyright (C) 2010-2013 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 30 30 #include <VBox/com/errorprint.h> 31 31 #include <VBox/com/VirtualBox.h> 32 #include <VBox/com/ EventQueue.h>32 #include <VBox/com/NativeEventQueue.h> 33 33 34 34 #include <VBox/err.h> … … 958 958 break; 959 959 960 /* Did we run out of time? */ 961 if ( cMsTimeout 962 && RTTimeMilliTS() - u64StartMS > cMsTimeout) 963 break; 964 965 NativeEventQueue::getMainEventQueue()->processEventQueue(0); 966 960 967 } /* while */ 961 968 -
trunk/src/VBox/Frontends/VBoxSDL/VBoxSDL.cpp
r44970 r46649 28 28 #include <VBox/com/errorprint.h> 29 29 30 #include <VBox/com/ EventQueue.h>30 #include <VBox/com/NativeEventQueue.h> 31 31 #include <VBox/com/VirtualBox.h> 32 32 … … 1378 1378 ComPtr<ISession> pSession; 1379 1379 bool sessionOpened = false; 1380 EventQueue* eventQ = com::EventQueue::getMainEventQueue();1380 NativeEventQueue* eventQ = com::NativeEventQueue::getMainEventQueue(); 1381 1381 1382 1382 ComPtr<IMachine> pMachine; -
trunk/src/VBox/Main/Makefile.kmk
r46474 r46649 736 736 glue/AutoLock.cpp \ 737 737 glue/EventQueue.cpp \ 738 glue/NativeEventQueue.cpp \ 738 739 glue/ErrorInfo.cpp \ 739 740 glue/errorprint.cpp -
trunk/src/VBox/Main/glue/EventQueue.cpp
r43944 r46649 1 1 /* $Id$ */ 2 2 /** @file 3 * MS COM / XPCOM Abstraction Layer: 4 * Event and EventQueue class declaration 3 * Event queue class declaration. 5 4 */ 6 5 7 6 /* 8 * Copyright (C) 20 06-2012Oracle Corporation7 * Copyright (C) 2013 Oracle Corporation 9 8 * 10 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 17 16 */ 18 17 18 /** @todo Adapt / update documentation! */ 19 19 20 #include "VBox/com/EventQueue.h" 20 21 21 #ifdef RT_OS_DARWIN 22 # include <CoreFoundation/CFRunLoop.h> 23 #endif 24 25 #if defined(VBOX_WITH_XPCOM) && !defined(RT_OS_DARWIN) && !defined(RT_OS_OS2) 26 # define USE_XPCOM_QUEUE 27 #endif 28 22 #include <iprt/asm.h> 29 23 #include <new> /* For bad_alloc. */ 30 24 31 25 #include <iprt/err.h> 26 #include <iprt/semaphore.h> 32 27 #include <iprt/time.h> 33 28 #include <iprt/thread.h> 34 29 #include <iprt/log.h> 35 #ifdef USE_XPCOM_QUEUE36 # include <errno.h>37 #endif38 30 39 31 namespace com … … 43 35 //////////////////////////////////////////////////////////////////////////////// 44 36 45 #ifndef VBOX_WITH_XPCOM 46 47 # define CHECK_THREAD_RET(ret) \ 48 do { \ 49 AssertMsg(GetCurrentThreadId() == mThreadId, ("Must be on event queue thread!")); \ 50 if (GetCurrentThreadId() != mThreadId) \ 51 return ret; \ 52 } while (0) 53 54 /** Magic LPARAM value for the WM_USER messages that we're posting. 55 * @remarks This magic value is duplicated in 56 * vboxapi/PlatformMSCOM::interruptWaitEvents(). */ 57 #define EVENTQUEUE_WIN_LPARAM_MAGIC UINT32_C(0xf241b819) 58 59 60 #else // VBOX_WITH_XPCOM 61 62 # define CHECK_THREAD_RET(ret) \ 63 do { \ 64 if (!mEventQ) \ 65 return ret; \ 66 BOOL isOnCurrentThread = FALSE; \ 67 mEventQ->IsOnCurrentThread(&isOnCurrentThread); \ 68 AssertMsg(isOnCurrentThread, ("Must be on event queue thread!")); \ 69 if (!isOnCurrentThread) \ 70 return ret; \ 71 } while (0) 72 73 #endif // VBOX_WITH_XPCOM 74 75 /** Pointer to the main event queue. */ 76 EventQueue *EventQueue::sMainQueue = NULL; 77 78 79 #ifdef VBOX_WITH_XPCOM 80 81 struct MyPLEvent : public PLEvent 82 { 83 MyPLEvent(Event *e) : event(e) {} 84 Event *event; 85 }; 86 87 /* static */ 88 void *PR_CALLBACK com::EventQueue::plEventHandler(PLEvent *self) 89 { 90 Event *ev = ((MyPLEvent *)self)->event; 91 if (ev) 92 ev->handler(); 93 else 94 { 95 EventQueue *eq = (EventQueue *)self->owner; 96 Assert(eq); 97 eq->mInterrupted = true; 98 } 99 return NULL; 100 } 101 102 /* static */ 103 void PR_CALLBACK com::EventQueue::plEventDestructor(PLEvent *self) 104 { 105 Event *ev = ((MyPLEvent *)self)->event; 106 if (ev) 107 delete ev; 108 delete self; 109 } 110 111 #endif // VBOX_WITH_XPCOM 112 113 /** 114 * Constructs an event queue for the current thread. 115 * 116 * Currently, there can be only one event queue per thread, so if an event 117 * queue for the current thread already exists, this object is simply attached 118 * to the existing event queue. 119 */ 120 EventQueue::EventQueue() 121 { 122 /** @todo r=andy This constructor does way too much. In case of failure 123 * it's up to the caller to verify all sorts of stuff. Why 124 * isn't this done in init() and moving the main queue 125 * creation/deletion stuff to a dedicated function? */ 126 #ifndef VBOX_WITH_XPCOM 127 128 mThreadId = GetCurrentThreadId(); 129 // force the system to create the message queue for the current thread 130 MSG msg; 131 PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE); 132 133 if (!DuplicateHandle(GetCurrentProcess(), 134 GetCurrentThread(), 135 GetCurrentProcess(), 136 &mhThread, 137 0 /*dwDesiredAccess*/, 138 FALSE /*bInheritHandle*/, 139 DUPLICATE_SAME_ACCESS)) 140 mhThread = INVALID_HANDLE_VALUE; 141 142 #else // VBOX_WITH_XPCOM 143 144 mEQCreated = false; 145 mInterrupted = false; 146 147 // Here we reference the global nsIEventQueueService instance and hold it 148 // until we're destroyed. This is necessary to keep NS_ShutdownXPCOM() away 149 // from calling StopAcceptingEvents() on all event queues upon destruction of 150 // nsIEventQueueService, and makes sense when, for some reason, this happens 151 // *before* we're able to send a NULL event to stop our event handler thread 152 // when doing unexpected cleanup caused indirectly by NS_ShutdownXPCOM() 153 // that is performing a global cleanup of everything. A good example of such 154 // situation is when NS_ShutdownXPCOM() is called while the VirtualBox component 155 // is still alive (because it is still referenced): eventually, it results in 156 // a VirtualBox::uninit() call from where it is already not possible to post 157 // NULL to the event thread (because it stopped accepting events). 158 159 nsresult rc = NS_GetEventQueueService(getter_AddRefs(mEventQService)); 160 161 if (NS_SUCCEEDED(rc)) 162 { 163 rc = mEventQService->GetThreadEventQueue(NS_CURRENT_THREAD, 164 getter_AddRefs(mEventQ)); 165 if (rc == NS_ERROR_NOT_AVAILABLE) 166 { 167 rc = mEventQService->CreateThreadEventQueue(); 168 if (NS_SUCCEEDED(rc)) 169 { 170 mEQCreated = true; 171 rc = mEventQService->GetThreadEventQueue(NS_CURRENT_THREAD, 172 getter_AddRefs(mEventQ)); 173 } 174 } 175 } 176 AssertComRC(rc); 177 178 #endif // VBOX_WITH_XPCOM 179 } 180 181 EventQueue::~EventQueue() 182 { 183 #ifndef VBOX_WITH_XPCOM 184 if (mhThread != INVALID_HANDLE_VALUE) 185 { 186 CloseHandle(mhThread); 187 mhThread = INVALID_HANDLE_VALUE; 188 } 189 #else // VBOX_WITH_XPCOM 190 // process all pending events before destruction 191 if (mEventQ) 192 { 193 if (mEQCreated) 194 { 195 mEventQ->StopAcceptingEvents(); 196 mEventQ->ProcessPendingEvents(); 197 mEventQService->DestroyThreadEventQueue(); 198 } 199 mEventQ = nsnull; 200 mEventQService = nsnull; 201 } 202 #endif // VBOX_WITH_XPCOM 203 } 204 205 /** 206 * Initializes the main event queue instance. 207 * @returns VBox status code. 208 * 209 * @remarks If you're using the rest of the COM/XPCOM glue library, 210 * com::Initialize() will take care of initializing and uninitializing 211 * the EventQueue class. If you don't call com::Initialize, you must 212 * make sure to call this method on the same thread that did the 213 * XPCOM initialization or we'll end up using the wrong main queue. 214 */ 215 /* static */ 216 int EventQueue::init() 217 { 218 Assert(sMainQueue == NULL); 219 Assert(RTThreadIsMain(RTThreadSelf())); 220 221 try 222 { 223 sMainQueue = new EventQueue(); 224 225 #ifdef VBOX_WITH_XPCOM 226 /* Check that it actually is the main event queue, i.e. that 227 we're called on the right thread. */ 228 nsCOMPtr<nsIEventQueue> q; 229 nsresult rv = NS_GetMainEventQ(getter_AddRefs(q)); 230 Assert(NS_SUCCEEDED(rv)); 231 Assert(q == sMainQueue->mEventQ); 232 233 /* Check that it's a native queue. */ 234 PRBool fIsNative = PR_FALSE; 235 rv = sMainQueue->mEventQ->IsQueueNative(&fIsNative); 236 Assert(NS_SUCCEEDED(rv) && fIsNative); 237 #endif // VBOX_WITH_XPCOM 238 } 239 catch (std::bad_alloc &) 240 { 241 return VERR_NO_MEMORY; 242 } 243 244 return VINF_SUCCESS; 245 } 246 247 /** 248 * Uninitialize the global resources (i.e. the main event queue instance). 249 * @returns VINF_SUCCESS 250 */ 251 /* static */ 252 int EventQueue::uninit() 253 { 254 if (sMainQueue) 255 { 256 /* Must process all events to make sure that no NULL event is left 257 * after this point. It would need to modify the state of sMainQueue. */ 258 #ifdef RT_OS_DARWIN /* Do not process the native runloop, the toolkit may not be ready for it. */ 259 sMainQueue->mEventQ->ProcessPendingEvents(); 260 #else 261 sMainQueue->processEventQueue(0); 262 #endif 263 delete sMainQueue; 264 sMainQueue = NULL; 265 } 266 return VINF_SUCCESS; 267 } 268 269 /** 270 * Get main event queue instance. 271 * 272 * Depends on init() being called first. 273 */ 274 /* static */ 275 EventQueue* EventQueue::getMainEventQueue() 276 { 277 return sMainQueue; 278 } 279 280 #ifdef VBOX_WITH_XPCOM 281 # ifdef RT_OS_DARWIN 282 /** 283 * Wait for events and process them (Darwin). 284 * 285 * @retval VINF_SUCCESS 286 * @retval VERR_TIMEOUT 287 * @retval VERR_INTERRUPTED 288 * 289 * @param cMsTimeout How long to wait, or RT_INDEFINITE_WAIT. 290 */ 291 static int waitForEventsOnDarwin(RTMSINTERVAL cMsTimeout) 292 { 293 /* 294 * Wait for the requested time, if we get a hit we do a poll to process 295 * any other pending messages. 296 * 297 * Note! About 1.0e10: According to the sources anything above 3.1556952e+9 298 * means indefinite wait and 1.0e10 is what CFRunLoopRun() uses. 299 */ 300 CFTimeInterval rdTimeout = cMsTimeout == RT_INDEFINITE_WAIT ? 1e10 : (double)cMsTimeout / 1000; 301 OSStatus orc = CFRunLoopRunInMode(kCFRunLoopDefaultMode, rdTimeout, true /*returnAfterSourceHandled*/); 302 if (orc == kCFRunLoopRunHandledSource) 303 { 304 OSStatus orc2 = CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.0, false /*returnAfterSourceHandled*/); 305 if ( orc2 == kCFRunLoopRunStopped 306 || orc2 == kCFRunLoopRunFinished) 307 orc = orc2; 308 } 309 if ( orc == 0 /*???*/ 310 || orc == kCFRunLoopRunHandledSource) 311 return VINF_SUCCESS; 312 if ( orc == kCFRunLoopRunStopped 313 || orc == kCFRunLoopRunFinished) 314 return VERR_INTERRUPTED; 315 AssertMsg(orc == kCFRunLoopRunTimedOut, ("Unexpected status code from CFRunLoopRunInMode: %#x", orc)); 316 return VERR_TIMEOUT; 317 } 318 # else // !RT_OS_DARWIN 319 320 /** 321 * Wait for events (generic XPCOM). 322 * 323 * @retval VINF_SUCCESS 324 * @retval VERR_TIMEOUT 325 * @retval VINF_INTERRUPTED 326 * @retval VERR_INTERNAL_ERROR_4 327 * 328 * @param pQueue The queue to wait on. 329 * @param cMsTimeout How long to wait, or RT_INDEFINITE_WAIT. 330 */ 331 static int waitForEventsOnXPCOM(nsIEventQueue *pQueue, RTMSINTERVAL cMsTimeout) 332 { 333 int fd = pQueue->GetEventQueueSelectFD(); 334 fd_set fdsetR; 335 FD_ZERO(&fdsetR); 336 FD_SET(fd, &fdsetR); 337 338 fd_set fdsetE = fdsetR; 339 340 struct timeval tv = {0,0}; 341 struct timeval *ptv; 342 if (cMsTimeout == RT_INDEFINITE_WAIT) 343 ptv = NULL; 344 else 345 { 346 tv.tv_sec = cMsTimeout / 1000; 347 tv.tv_usec = (cMsTimeout % 1000) * 1000; 348 ptv = &tv; 349 } 350 351 int rc = select(fd + 1, &fdsetR, NULL, &fdsetE, ptv); 352 if (rc > 0) 353 rc = VINF_SUCCESS; 354 else if (rc == 0) 355 rc = VERR_TIMEOUT; 356 else if (errno == EINTR) 357 rc = VINF_INTERRUPTED; 358 else 359 { 360 static uint32_t s_ErrorCount = 0; 361 if (s_ErrorCount < 500) 362 { 363 LogRel(("waitForEventsOnXPCOM rc=%d errno=%d\n", rc, errno)); 364 ++s_ErrorCount; 365 } 366 367 AssertMsgFailed(("rc=%d errno=%d\n", rc, errno)); 368 rc = VERR_INTERNAL_ERROR_4; 369 } 370 return rc; 371 } 372 373 # endif // !RT_OS_DARWIN 374 #endif // VBOX_WITH_XPCOM 375 376 #ifndef VBOX_WITH_XPCOM 377 378 /** 379 * Dispatch a message on Windows. 380 * 381 * This will pick out our events and handle them specially. 382 * 383 * @returns @a rc or VERR_INTERRUPTED (WM_QUIT or NULL msg). 384 * @param pMsg The message to dispatch. 385 * @param rc The current status code. 386 */ 387 /*static*/ 388 int EventQueue::dispatchMessageOnWindows(MSG const *pMsg, int rc) 389 { 390 /* 391 * Check for and dispatch our events. 392 */ 393 if ( pMsg->hwnd == NULL 394 && pMsg->message == WM_USER) 395 { 396 if (pMsg->lParam == EVENTQUEUE_WIN_LPARAM_MAGIC) 397 { 398 Event *pEvent = (Event *)pMsg->wParam; 399 if (pEvent) 400 { 401 pEvent->handler(); 402 delete pEvent; 403 } 404 else 405 rc = VERR_INTERRUPTED; 406 return rc; 407 } 408 AssertMsgFailed(("lParam=%p wParam=%p\n", pMsg->lParam, pMsg->wParam)); 409 } 410 411 /* 412 * Check for the quit message and dispatch the message the normal way. 413 */ 414 if (pMsg->message == WM_QUIT) 415 rc = VERR_INTERRUPTED; 416 TranslateMessage(pMsg); 417 DispatchMessage(pMsg); 418 419 return rc; 420 } 421 422 423 /** 424 * Process pending events (Windows). 425 * 426 * @retval VINF_SUCCESS 427 * @retval VERR_TIMEOUT 428 * @retval VERR_INTERRUPTED. 429 */ 430 static int processPendingEvents(void) 431 { 432 int rc = VERR_TIMEOUT; 433 MSG Msg; 434 if (PeekMessage(&Msg, NULL /*hWnd*/, 0 /*wMsgFilterMin*/, 0 /*wMsgFilterMax*/, PM_REMOVE)) 435 { 436 rc = VINF_SUCCESS; 437 do 438 rc = EventQueue::dispatchMessageOnWindows(&Msg, rc); 439 while (PeekMessage(&Msg, NULL /*hWnd*/, 0 /*wMsgFilterMin*/, 0 /*wMsgFilterMax*/, PM_REMOVE)); 440 } 441 return rc; 442 } 443 444 #else // VBOX_WITH_XPCOM 445 446 /** 447 * Process pending XPCOM events. 448 * @param pQueue The queue to process events on. 449 * @retval VINF_SUCCESS 450 * @retval VERR_TIMEOUT 451 * @retval VERR_INTERRUPTED (darwin only) 452 * @retval VERR_INTERNAL_ERROR_2 453 */ 454 static int processPendingEvents(nsIEventQueue *pQueue) 455 { 456 /* ProcessPendingEvents doesn't report back what it did, so check here. */ 457 PRBool fHasEvents = PR_FALSE; 458 nsresult hr = pQueue->PendingEvents(&fHasEvents); 459 if (NS_FAILED(hr)) 460 return VERR_INTERNAL_ERROR_2; 461 462 /* Process pending events. */ 463 int rc = VINF_SUCCESS; 464 if (fHasEvents) 465 pQueue->ProcessPendingEvents(); 466 else 467 rc = VERR_TIMEOUT; 468 469 # ifdef RT_OS_DARWIN 470 /* Process pending native events. */ 471 int rc2 = waitForEventsOnDarwin(0); 472 if (rc == VERR_TIMEOUT || rc2 == VERR_INTERRUPTED) 473 rc = rc2; 474 # endif 475 476 return rc; 477 } 478 479 #endif // VBOX_WITH_XPCOM 37 EventQueue::EventQueue(void) 38 : mShutdown(false) 39 { 40 int rc = RTCritSectInit(&mCritSect); 41 AssertRC(rc); 42 43 rc = RTSemEventCreate(&mSemEvent); 44 AssertRC(rc); 45 } 46 47 EventQueue::~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 } 480 62 481 63 /** … … 504 86 int EventQueue::processEventQueue(RTMSINTERVAL cMsTimeout) 505 87 { 506 int rc; 507 CHECK_THREAD_RET(VERR_INVALID_CONTEXT); 508 509 #ifdef VBOX_WITH_XPCOM 510 /* 511 * Process pending events, if none are available and we're not in a 512 * poll call, wait for some to appear. (We have to be a little bit 513 * careful after waiting for the events since Darwin will process 514 * them as part of the wait, while the XPCOM case will not.) 515 * 516 * Note! Unfortunately, WaitForEvent isn't interruptible with Ctrl-C, 517 * while select() is. So we cannot use it for indefinite waits. 518 */ 519 rc = processPendingEvents(mEventQ); 520 if ( rc == VERR_TIMEOUT 521 && cMsTimeout > 0) 522 { 523 # ifdef RT_OS_DARWIN 524 /** @todo check how Ctrl-C works on Darwin. */ 525 rc = waitForEventsOnDarwin(cMsTimeout); 526 if (rc == VERR_TIMEOUT) 527 rc = processPendingEvents(mEventQ); 528 # else // !RT_OS_DARWIN 529 rc = waitForEventsOnXPCOM(mEventQ, cMsTimeout); 530 if ( RT_SUCCESS(rc) 531 || rc == VERR_TIMEOUT) 532 rc = processPendingEvents(mEventQ); 533 # endif // !RT_OS_DARWIN 534 } 535 536 if ( ( RT_SUCCESS(rc) 537 || rc == VERR_INTERRUPTED 538 || rc == VERR_TIMEOUT) 539 && mInterrupted) 540 { 541 mInterrupted = false; 542 rc = VERR_INTERRUPTED; 543 } 544 545 #else // !VBOX_WITH_XPCOM 546 if (cMsTimeout == RT_INDEFINITE_WAIT) 547 { 548 BOOL fRet; 549 MSG Msg; 550 rc = VINF_SUCCESS; 551 while ( rc != VERR_INTERRUPTED 552 && (fRet = GetMessage(&Msg, NULL /*hWnd*/, WM_USER, WM_USER)) 553 && fRet != -1) 554 rc = EventQueue::dispatchMessageOnWindows(&Msg, rc); 555 if (fRet == 0) 556 rc = VERR_INTERRUPTED; 557 else if (fRet == -1) 558 rc = RTErrConvertFromWin32(GetLastError()); 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 100 if (fWait) 101 { 102 int rc2 = RTCritSectLeave(&mCritSect); 103 AssertRC(rc2); 104 105 rc = RTSemEventWaitNoResume(mSemEvent, cMsTimeout); 106 } 107 108 if (RT_SUCCESS(rc)) 109 { 110 if (ASMAtomicReadBool(&mShutdown)) 111 return VERR_INTERRUPTED; 112 113 if (fWait) 114 rc = RTCritSectEnter(&mCritSect); 115 if (RT_SUCCESS(rc)) 116 { 117 EventQueueListIterator it = mEvents.begin(); 118 if (it != mEvents.end()) 119 { 120 Event *pEvent = *it; 121 AssertPtr(pEvent); 122 123 mEvents.erase(it); 124 125 int rc2 = RTCritSectLeave(&mCritSect); 126 if (RT_SUCCESS(rc)) 127 rc = rc2; 128 129 pEvent->handler(); 130 pEvent->Release(); 559 131 } 560 132 else 561 133 { 562 rc = processPendingEvents(); 563 if ( rc == VERR_TIMEOUT 564 && cMsTimeout != 0) 565 { 566 DWORD rcW = MsgWaitForMultipleObjects(1, 567 &mhThread, 568 TRUE /*fWaitAll*/, 569 cMsTimeout, 570 QS_ALLINPUT); 571 AssertMsgReturn(rcW == WAIT_TIMEOUT || rcW == WAIT_OBJECT_0, 572 ("%d\n", rcW), 573 VERR_INTERNAL_ERROR_4); 574 rc = processPendingEvents(); 575 } 576 } 577 #endif // !VBOX_WITH_XPCOM 134 int rc2 = RTCritSectLeave(&mCritSect); 135 if (RT_SUCCESS(rc)) 136 rc = rc2; 137 } 138 } 139 } 578 140 579 141 Assert(rc != VERR_TIMEOUT || cMsTimeout != RT_INDEFINITE_WAIT); … … 588 150 * @returns VBox status code. 589 151 */ 590 int EventQueue::interruptEventQueueProcessing() 591 { 592 /* Send a NULL event. This event will be picked up and handled specially 593 * both for XPCOM and Windows. It is the responsibility of the caller to 594 * take care of not running the loop again in a way which will hang. */ 595 postEvent(NULL); 596 return VINF_SUCCESS; 152 int EventQueue::interruptEventQueueProcessing(void) 153 { 154 ASMAtomicWriteBool(&mShutdown, true); 155 156 return RTSemEventSignal(mSemEvent); 597 157 } 598 158 … … 605 165 BOOL EventQueue::postEvent(Event *pEvent) 606 166 { 607 #ifndef VBOX_WITH_XPCOM 608 /* Note! The event == NULL case is duplicated in vboxapi/PlatformMSCOM::interruptWaitEvents(). */ 609 return PostThreadMessage(mThreadId, WM_USER, (WPARAM)pEvent, EVENTQUEUE_WIN_LPARAM_MAGIC); 610 611 #else // VBOX_WITH_XPCOM 612 613 if (!mEventQ) 614 return FALSE; 615 616 try 617 { 618 MyPLEvent *pMyEvent = new MyPLEvent(pEvent); 619 mEventQ->InitEvent(pMyEvent, this, com::EventQueue::plEventHandler, 620 com::EventQueue::plEventDestructor); 621 HRESULT rc = mEventQ->PostEvent(pMyEvent); 622 return NS_SUCCEEDED(rc); 623 } 624 catch (std::bad_alloc &ba) 625 { 626 AssertMsgFailed(("Out of memory while allocating memory for event=%p: %s\n", 627 pEvent, ba.what())); 628 } 629 630 return FALSE; 631 #endif // VBOX_WITH_XPCOM 632 } 633 634 635 /** 636 * Get select()'able selector for this event queue. 637 * This will return -1 on platforms and queue variants not supporting such 638 * functionality. 639 */ 640 int EventQueue::getSelectFD() 641 { 642 #ifdef VBOX_WITH_XPCOM 643 return mEventQ->GetEventQueueSelectFD(); 644 #else 645 return -1; 646 #endif 167 int rc = RTCritSectEnter(&mCritSect); 168 if (RT_SUCCESS(rc)) 169 { 170 try 171 { 172 if (pEvent) 173 { 174 pEvent->AddRef(); 175 mEvents.push_back(pEvent); 176 } 177 else /* No locking, since we're already in our crit sect. */ 178 mShutdown = true; 179 180 size_t cEvents = mEvents.size(); 181 if (cEvents > _1K) /** @todo Make value configurable? */ 182 { 183 static int s_cBitchedAboutLotEvents = 0; 184 if (s_cBitchedAboutLotEvents < 10) 185 LogRel(("Warning: Event queue received lots of events (%zu), expect delayed event handling (%d/10)\n", 186 cEvents, ++s_cBitchedAboutLotEvents)); 187 } 188 189 /* Leave critical section before signalling event. */ 190 rc = RTCritSectLeave(&mCritSect); 191 if (RT_SUCCESS(rc)) 192 { 193 int rc2 = RTSemEventSignal(mSemEvent); 194 AssertRC(rc2); 195 } 196 } 197 catch (std::bad_alloc &ba) 198 { 199 NOREF(ba); 200 rc = VERR_NO_MEMORY; 201 } 202 203 if (RT_FAILURE(rc)) 204 { 205 int rc2 = RTCritSectLeave(&mCritSect); 206 AssertRC(rc2); 207 } 208 } 209 210 return RT_SUCCESS(rc) ? TRUE : FALSE; 647 211 } 648 212 -
trunk/src/VBox/Main/glue/initterm.cpp
r44528 r46649 6 6 7 7 /* 8 * Copyright (C) 2006-201 2Oracle Corporation8 * Copyright (C) 2006-2013 Oracle Corporation 9 9 * 10 10 * This file is part of VirtualBox Open Source Edition (OSE), as … … 49 49 #include "VBox/com/com.h" 50 50 #include "VBox/com/assert.h" 51 #include "VBox/com/ EventQueue.h"51 #include "VBox/com/NativeEventQueue.h" 52 52 #include "VBox/com/AutoLock.h" 53 53 … … 499 499 */ 500 500 if (SUCCEEDED(rc)) 501 EventQueue::init();501 NativeEventQueue::init(); 502 502 503 503 return rc; … … 517 517 if (-- gCOMMainInitCount == 0) 518 518 { 519 EventQueue::uninit();519 NativeEventQueue::uninit(); 520 520 ASMAtomicWriteHandle(&gCOMMainThread, NIL_RTTHREAD); 521 521 } … … 556 556 if (--gXPCOMInitCount == 0) 557 557 { 558 EventQueue::uninit();558 MainEventQueue::uninit(); 559 559 rc = NS_ShutdownXPCOM(nsnull); 560 560 -
trunk/src/VBox/Main/src-server/VirtualBoxImpl.cpp
r45356 r46649 5356 5356 AssertReturn(pvUser, VERR_INVALID_POINTER); 5357 5357 5358 com::Initialize(); 5359 5360 // create an event queue for the current thread 5361 EventQueue *eventQ = new EventQueue(); 5362 AssertReturn(eventQ, VERR_NO_MEMORY); 5363 5364 // return the queue to the one who created this thread 5365 *(static_cast <EventQueue **>(pvUser)) = eventQ; 5366 // signal that we're ready 5367 RTThreadUserSignal(thread); 5368 5369 /* 5370 * In case of spurious wakeups causing VERR_TIMEOUTs and/or other return codes 5371 * we must not stop processing events and delete the "eventQ" object. This must 5372 * be done ONLY when we stop this loop via interruptEventQueueProcessing(). 5373 * See @bugref{5724}. 5374 */ 5375 while (eventQ->processEventQueue(RT_INDEFINITE_WAIT) != VERR_INTERRUPTED) 5376 /* nothing */ ; 5377 5378 delete eventQ; 5358 HRESULT hr = com::Initialize(); 5359 if (FAILED(hr)) 5360 return VERR_COM_UNEXPECTED; 5361 5362 int rc = VINF_SUCCESS; 5363 5364 try 5365 { 5366 /* Create an event queue for the current thread. */ 5367 EventQueue *pEventQueue = new EventQueue(); 5368 AssertPtr(pEventQueue); 5369 5370 /* Return the queue to the one who created this thread. */ 5371 *(static_cast <EventQueue **>(pvUser)) = pEventQueue; 5372 5373 /* signal that we're ready. */ 5374 RTThreadUserSignal(thread); 5375 5376 /* 5377 * In case of spurious wakeups causing VERR_TIMEOUTs and/or other return codes 5378 * we must not stop processing events and delete the pEventQueue object. This must 5379 * be done ONLY when we stop this loop via interruptEventQueueProcessing(). 5380 * See @bugref{5724}. 5381 */ 5382 while (pEventQueue->processEventQueue(RT_INDEFINITE_WAIT) != VERR_INTERRUPTED) 5383 /* nothing */ ; 5384 5385 delete pEventQueue; 5386 } 5387 catch (std::bad_alloc &ba) 5388 { 5389 rc = VERR_NO_MEMORY; 5390 NOREF(ba); 5391 } 5379 5392 5380 5393 com::Shutdown(); 5381 5394 5382 5383 LogFlowFuncLeave(); 5384 5385 return 0; 5395 LogFlowFuncLeaveRC(rc); 5396 return rc; 5386 5397 } 5387 5398 -
trunk/src/libs/xpcom18a4
-
Property svn:mergeinfo
set to (toggle deleted branches)
/branches/VBox-3.0/src/libs/xpcom18a4 58652,70973 /branches/VBox-3.2/src/libs/xpcom18a4 66309,66318 /branches/VBox-4.0/src/libs/xpcom18a4 70873 /branches/VBox-4.1/src/libs/xpcom18a4 74233,78414,78691,82579,85941 /branches/VBox-4.2/src/libs/xpcom18a4 82653,86229-86230,86234,86529,86532-86533 /branches/andy/guestctrl20/src/libs/xpcom18a4 78916,78930 /branches/dsen/gui/src/libs/xpcom18a4 79076-79078,79089,79109-79110,79112-79113,79127-79130,79134,79141,79151,79155,79157-79159,79193,79197 /branches/dsen/gui2/src/libs/xpcom18a4 79224,79228,79233,79235,79258,79262-79263,79273,79341,79345,79354,79357,79387-79388,79559-79569,79572-79573,79578,79581-79582,79590-79591,79598-79599,79602-79603,79605-79606,79632,79635,79637,79644 /branches/dsen/gui3/src/libs/xpcom18a4 79645-79692
-
Property svn:mergeinfo
set to (toggle deleted branches)
-
trunk/src/libs/xpcom18a4/java/src/nsJavaInterfaces.cpp
r46593 r46649 355 355 356 356 #ifdef VBOX 357 # include <VBox/com/ EventQueue.h>357 # include <VBox/com/NativeEventQueue.h> 358 358 # include <iprt/err.h> 359 359 … … 361 361 XPCOM_NATIVE2(waitForEvents) (JNIEnv *env, jobject, jlong aTimeout) 362 362 { 363 com:: EventQueue* aEventQ = com::EventQueue::getMainEventQueue();363 com::NativeEventQueue* aEventQ = com::NativeEventQueue::getMainEventQueue(); 364 364 NS_WARN_IF_FALSE(aEventQ != nsnull, "Null main event queue"); 365 365 if (!aEventQ) -
trunk/src/libs/xpcom18a4/java/src/nsThreadUtils.h
r29140 r46649 51 51 } 52 52 53 #include "VBox/com/ EventQueue.h"53 #include "VBox/com/NativeEventQueue.h" 54 54 55 55 inline already_AddRefed<nsIEventQueue> do_GetMainThreadQueue() 56 56 { 57 com:: EventQueue* eq = com::EventQueue::getMainEventQueue();57 com::NativeEventQueue* eq = com::NativeEventQueue::getMainEventQueue(); 58 58 NS_ASSERTION(eq != nsnull, "Must be valid"); 59 59 return eq->getIEventQueue(); -
trunk/src/libs/xpcom18a4/python/src/module/_xpcom.cpp
r46593 r46649 511 511 #ifdef VBOX 512 512 513 # include <VBox/com/ EventQueue.h>513 # include <VBox/com/NativeEventQueue.h> 514 514 # include <iprt/err.h> 515 515 … … 522 522 523 523 int rc; 524 com:: EventQueue* aEventQ = com::EventQueue::getMainEventQueue();524 com::NativeEventQueue* aEventQ = com::NativeEventQueue::getMainEventQueue(); 525 525 NS_WARN_IF_FALSE(aEventQ != nsnull, "Null main event queue"); 526 526 if (!aEventQ) … … 557 557 PyXPCOMMethod_InterruptWait(PyObject *self, PyObject *args) 558 558 { 559 com:: EventQueue* aEventQ = com::EventQueue::getMainEventQueue();559 com::NativeEventQueue* aEventQ = com::NativeEventQueue::getMainEventQueue(); 560 560 NS_WARN_IF_FALSE(aEventQ != nsnull, "Null main event queue"); 561 561 if (!aEventQ)
Note:
See TracChangeset
for help on using the changeset viewer.