- Timestamp:
- Oct 21, 2010 10:46:46 AM (14 years ago)
- svn:sync-xref-src-repo-rev:
- 66863
- Location:
- trunk/src/VBox
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Frontends/VBoxShell/vboxshell.py
r33266 r33295 405 405 listener = console.eventSource.createListener() 406 406 registered = False 407 sources = [console.keyboard.eventSource, console.mouse.eventSource] 407 # we create an aggregated event source to listen for multiple event types 408 agg = console.eventSource.createAggregator([console.keyboard.eventSource, console.mouse.eventSource]) 408 409 demo = open(file, 'w') 409 410 header="VM="+console.machine.name+"\n" … … 413 414 dur = 100000 414 415 try: 415 for es in sources: 416 es.registerListener(listener, [ctx['global'].constants.VBoxEventType_Any], False) 416 agg.registerListener(listener, [ctx['global'].constants.VBoxEventType_Any], False) 417 417 registered = True 418 418 end = time.time() + dur 419 419 while time.time() < end: 420 for es in sources: 421 ev = es.getEvent(listener, 0) 422 if ev: 423 handleEventImpl(ev) 424 # keyboard/mouse events aren't waitable, so no need for eventProcessed 420 ev = agg.getEvent(listener, 0) 421 if ev: 422 handleEventImpl(ev) 423 # keyboard/mouse events aren't waitable, so no need for eventProcessed 425 424 # We need to catch all exceptions here, otherwise listener will never be unregistered 426 425 except: … … 429 428 demo.close() 430 429 if listener and registered: 431 for es in sources: 432 es.unregisterListener(listener) 430 agg.unregisterListener(listener) 433 431 434 432 -
trunk/src/VBox/Main/EventImpl.cpp
r33265 r33295 833 833 834 834 if (queueSize != 0 && mQueue.back() == aEvent) 835 /* if same event is being pushed multiple times - it's reusable event and 835 /* if same event is being pushed multiple times - it's reusable event and 836 836 we don't really need multiple instances of it in the queue */ 837 837 (void)aEvent; … … 851 851 AutoLockBase& aAlock) 852 852 { 853 AssertMsg(!mActive, ("must be passive\n")); 853 if (mActive) 854 return VBOX_E_INVALID_OBJECT_STATE; 854 855 855 856 // retain listener record … … 1101 1102 tr("Listener was never registered")); 1102 1103 1104 if (rc == VBOX_E_INVALID_OBJECT_STATE) 1105 return setError(rc, tr("Listener must be passive")); 1106 1103 1107 return rc; 1104 1108 } … … 1201 1205 }; 1202 1206 1207 /* Proxy listener class, used to aggregate multiple event sources into one */ 1208 class ATL_NO_VTABLE ProxyEventListener : 1209 public VirtualBoxBase, 1210 VBOX_SCRIPTABLE_IMPL(IEventListener) 1211 { 1212 ComPtr<IEventSource> mSource; 1213 public: 1214 1215 VIRTUALBOXBASE_ADD_ERRORINFO_SUPPORT(ProxyEventListener, IEventListener) 1216 1217 DECLARE_NOT_AGGREGATABLE(ProxyEventListener) 1218 1219 DECLARE_PROTECT_FINAL_CONSTRUCT() 1220 1221 BEGIN_COM_MAP(ProxyEventListener) 1222 COM_INTERFACE_ENTRY(ISupportErrorInfo) 1223 COM_INTERFACE_ENTRY(IEventListener) 1224 COM_INTERFACE_ENTRY(IDispatch) 1225 END_COM_MAP() 1226 1227 ProxyEventListener() 1228 {} 1229 ~ProxyEventListener() 1230 {} 1231 1232 HRESULT FinalConstruct() 1233 { 1234 return S_OK; 1235 } 1236 void FinalRelease() 1237 {} 1238 1239 HRESULT init(IEventSource* aSource) 1240 { 1241 mSource = aSource; 1242 return S_OK; 1243 } 1244 1245 // IEventListener methods 1246 STDMETHOD(HandleEvent)(IEvent * aEvent) 1247 { 1248 BOOL fProcessed = FALSE; 1249 if (mSource) 1250 return mSource->FireEvent(aEvent, 0, &fProcessed); 1251 else 1252 return S_OK; 1253 } 1254 }; 1255 1256 class ATL_NO_VTABLE EventSourceAggregator : 1257 public VirtualBoxBase, 1258 VBOX_SCRIPTABLE_IMPL(IEventSource) 1259 { 1260 typedef std::list <ComPtr<IEventSource> > EventSourceList; 1261 /* key is weak reference */ 1262 typedef std::map<IEventListener*, ComPtr<IEventListener> > ProxyListenerMap; 1263 1264 EventSourceList mEventSources; 1265 ProxyListenerMap mListenerProxies; 1266 ComObjPtr<EventSource> mSource; 1267 1268 public: 1269 1270 VIRTUALBOXBASE_ADD_ERRORINFO_SUPPORT(EventSourceAggregator, IEventSource) 1271 1272 DECLARE_NOT_AGGREGATABLE(EventSourceAggregator) 1273 1274 DECLARE_PROTECT_FINAL_CONSTRUCT() 1275 1276 BEGIN_COM_MAP(EventSourceAggregator) 1277 COM_INTERFACE_ENTRY(ISupportErrorInfo) 1278 COM_INTERFACE_ENTRY(IEventSource) 1279 COM_INTERFACE_ENTRY(IDispatch) 1280 END_COM_MAP() 1281 1282 EventSourceAggregator() 1283 {} 1284 ~EventSourceAggregator() 1285 {} 1286 1287 HRESULT FinalConstruct() 1288 { 1289 return S_OK; 1290 } 1291 void FinalRelease() 1292 { 1293 mEventSources.clear(); 1294 mListenerProxies.clear(); 1295 mSource->uninit(); 1296 } 1297 1298 // internal public 1299 HRESULT init(ComSafeArrayIn(IEventSource *, aSources)); 1300 1301 // IEventSource methods 1302 STDMETHOD(CreateListener)(IEventListener ** aListener); 1303 STDMETHOD(CreateAggregator)(ComSafeArrayIn(IEventSource*, aSubordinates), 1304 IEventSource ** aAggregator); 1305 STDMETHOD(RegisterListener)(IEventListener * aListener, 1306 ComSafeArrayIn(VBoxEventType_T, aInterested), 1307 BOOL aActive); 1308 STDMETHOD(UnregisterListener)(IEventListener * aListener); 1309 STDMETHOD(FireEvent)(IEvent * aEvent, 1310 LONG aTimeout, 1311 BOOL *aProcessed); 1312 STDMETHOD(GetEvent)(IEventListener * aListener, 1313 LONG aTimeout, 1314 IEvent * *aEvent); 1315 STDMETHOD(EventProcessed)(IEventListener * aListener, 1316 IEvent * aEvent); 1317 1318 protected: 1319 HRESULT createProxyListener(IEventListener * aListener, 1320 IEventListener * *aProxy); 1321 HRESULT getProxyListener (IEventListener * aListener, 1322 IEventListener * *aProxy); 1323 HRESULT removeProxyListener(IEventListener * aListener); 1324 }; 1325 1203 1326 #ifdef VBOX_WITH_XPCOM 1327 NS_DECL_CLASSINFO(ProxyEventListener) 1328 NS_IMPL_THREADSAFE_ISUPPORTS1_CI(ProxyEventListener, IEventListener) 1204 1329 NS_DECL_CLASSINFO(PassiveEventListener) 1205 1330 NS_IMPL_THREADSAFE_ISUPPORTS1_CI(PassiveEventListener, IEventListener) … … 1210 1335 NS_DECL_CLASSINFO(EventSource) 1211 1336 NS_IMPL_THREADSAFE_ISUPPORTS1_CI(EventSource, IEventSource) 1337 NS_DECL_CLASSINFO(EventSourceAggregator) 1338 NS_IMPL_THREADSAFE_ISUPPORTS1_CI(EventSourceAggregator, IEventSource) 1212 1339 #endif 1340 1213 1341 1214 1342 STDMETHODIMP EventSource::CreateListener(IEventListener ** aListener) … … 1227 1355 return S_OK; 1228 1356 } 1357 1358 1359 STDMETHODIMP EventSource::CreateAggregator(ComSafeArrayIn(IEventSource*, aSubordinates), 1360 IEventSource ** aResult) 1361 { 1362 CheckComArgOutPointerValid(aResult); 1363 1364 AutoCaller autoCaller(this); 1365 if (FAILED(autoCaller.rc())) return autoCaller.rc(); 1366 1367 ComObjPtr<EventSourceAggregator> agg; 1368 1369 HRESULT rc = agg.createObject(); 1370 ComAssertMsgRet(SUCCEEDED(rc), ("Could not create aggregator (%Rrc)", rc), 1371 E_FAIL); 1372 1373 rc = agg->init(ComSafeArrayInArg(aSubordinates)); 1374 if (FAILED(rc)) 1375 return rc; 1376 1377 1378 agg.queryInterfaceTo(aResult); 1379 return S_OK; 1380 } 1381 1382 HRESULT EventSourceAggregator::init(ComSafeArrayIn(IEventSource*, aSourcesIn)) 1383 { 1384 HRESULT rc; 1385 1386 AutoInitSpan autoInitSpan(this); 1387 AssertReturn(autoInitSpan.isOk(), E_FAIL); 1388 1389 rc = mSource.createObject(); 1390 ComAssertMsgRet(SUCCEEDED(rc), ("Could not create source (%Rrc)", rc), 1391 E_FAIL); 1392 rc = mSource->init((IEventSource*)this); 1393 ComAssertMsgRet(SUCCEEDED(rc), ("Could not init source (%Rrc)", rc), 1394 E_FAIL); 1395 1396 com::SafeIfaceArray<IEventSource> aSources(ComSafeArrayInArg (aSourcesIn)); 1397 1398 uint32_t cSize = aSources.size(); 1399 1400 for (uint32_t i=0; i<cSize; i++) 1401 { 1402 if (aSources[i] != NULL) 1403 mEventSources.push_back(aSources[i]); 1404 } 1405 1406 /* Confirm a successful initialization */ 1407 autoInitSpan.setSucceeded(); 1408 1409 return rc; 1410 } 1411 1412 STDMETHODIMP EventSourceAggregator::CreateListener(IEventListener ** aListener) 1413 { 1414 return mSource->CreateListener(aListener); 1415 } 1416 1417 STDMETHODIMP EventSourceAggregator::CreateAggregator(ComSafeArrayIn(IEventSource*, aSubordinates), 1418 IEventSource ** aResult) 1419 { 1420 return mSource->CreateAggregator(ComSafeArrayInArg(aSubordinates), aResult); 1421 } 1422 1423 STDMETHODIMP EventSourceAggregator::RegisterListener(IEventListener * aListener, 1424 ComSafeArrayIn(VBoxEventType_T, aInterested), 1425 BOOL aActive) 1426 { 1427 CheckComArgNotNull(aListener); 1428 CheckComArgSafeArrayNotNull(aInterested); 1429 1430 AutoCaller autoCaller(this); 1431 if (FAILED(autoCaller.rc())) return autoCaller.rc(); 1432 1433 HRESULT rc; 1434 1435 ComPtr<IEventListener> proxy; 1436 rc = createProxyListener(aListener, proxy.asOutParam()); 1437 if (FAILED(rc)) 1438 return rc; 1439 1440 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 1441 for (EventSourceList::const_iterator it = mEventSources.begin(); it != mEventSources.end(); 1442 ++it) 1443 { 1444 ComPtr<IEventSource> es = *it; 1445 /* Register active proxy listener on real event source */ 1446 rc = es->RegisterListener(proxy, ComSafeArrayInArg(aInterested), TRUE); 1447 } 1448 /* And add real listener on our event source */ 1449 rc = mSource->RegisterListener(aListener, ComSafeArrayInArg(aInterested), aActive); 1450 1451 rc = S_OK; 1452 1453 return rc; 1454 } 1455 1456 STDMETHODIMP EventSourceAggregator::UnregisterListener(IEventListener * aListener) 1457 { 1458 CheckComArgNotNull(aListener); 1459 1460 AutoCaller autoCaller(this); 1461 if (FAILED(autoCaller.rc())) return autoCaller.rc(); 1462 1463 HRESULT rc = S_OK; 1464 1465 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 1466 1467 ComPtr<IEventListener> proxy; 1468 rc = getProxyListener(aListener, proxy.asOutParam()); 1469 if (FAILED(rc)) 1470 return rc; 1471 1472 for (EventSourceList::const_iterator it = mEventSources.begin(); it != mEventSources.end(); 1473 ++it) 1474 { 1475 ComPtr<IEventSource> es = *it; 1476 rc = es->UnregisterListener(proxy); 1477 } 1478 rc = mSource->UnregisterListener(aListener); 1479 1480 return removeProxyListener(aListener); 1481 1482 } 1483 1484 STDMETHODIMP EventSourceAggregator::FireEvent(IEvent * aEvent, 1485 LONG aTimeout, 1486 BOOL *aProcessed) 1487 { 1488 CheckComArgNotNull(aEvent); 1489 CheckComArgOutPointerValid(aProcessed); 1490 1491 AutoCaller autoCaller(this); 1492 if (FAILED(autoCaller.rc())) return autoCaller.rc(); 1493 1494 HRESULT rc = S_OK; 1495 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 1496 /* Aggresgator event source shalln't have direct event firing, but we may 1497 wish to support aggregation chains */ 1498 for (EventSourceList::const_iterator it = mEventSources.begin(); it != mEventSources.end(); 1499 ++it) 1500 { 1501 ComPtr<IEventSource> es = *it; 1502 rc = es->FireEvent(aEvent, aTimeout, aProcessed); 1503 } 1504 1505 return S_OK; 1506 } 1507 1508 STDMETHODIMP EventSourceAggregator::GetEvent(IEventListener * aListener, 1509 LONG aTimeout, 1510 IEvent ** aEvent) 1511 { 1512 return mSource->GetEvent(aListener, aTimeout, aEvent); 1513 } 1514 1515 STDMETHODIMP EventSourceAggregator::EventProcessed(IEventListener * aListener, 1516 IEvent * aEvent) 1517 { 1518 return mSource->EventProcessed(aListener, aEvent); 1519 } 1520 1521 HRESULT EventSourceAggregator::createProxyListener(IEventListener * aListener, 1522 IEventListener * *aProxy) 1523 { 1524 ComObjPtr<ProxyEventListener> proxy; 1525 1526 HRESULT rc = proxy.createObject(); 1527 ComAssertMsgRet(SUCCEEDED(rc), ("Could not create proxy (%Rrc)", rc), 1528 E_FAIL); 1529 1530 rc = proxy->init(mSource); 1531 if (FAILED(rc)) 1532 return rc; 1533 1534 ProxyListenerMap::const_iterator it = mListenerProxies.find(aListener); 1535 if (it != mListenerProxies.end()) 1536 return setError(E_INVALIDARG, 1537 tr("This listener already registered")); 1538 1539 mListenerProxies.insert(ProxyListenerMap::value_type(aListener, proxy)); 1540 1541 proxy.queryInterfaceTo(aProxy); 1542 return S_OK; 1543 } 1544 1545 HRESULT EventSourceAggregator::getProxyListener(IEventListener * aListener, 1546 IEventListener * *aProxy) 1547 { 1548 ProxyListenerMap::const_iterator it = mListenerProxies.find(aListener); 1549 if (it == mListenerProxies.end()) 1550 return setError(E_INVALIDARG, 1551 tr("This listener never registered")); 1552 1553 (*it).second.queryInterfaceTo(aProxy); 1554 return S_OK; 1555 } 1556 1557 HRESULT EventSourceAggregator::removeProxyListener(IEventListener * aListener) 1558 { 1559 ProxyListenerMap::iterator it = mListenerProxies.find(aListener); 1560 if (it == mListenerProxies.end()) 1561 return setError(E_INVALIDARG, 1562 tr("This listener never registered")); 1563 1564 mListenerProxies.erase(it); 1565 return S_OK; 1566 } -
trunk/src/VBox/Main/idl/VirtualBox.xidl
r33294 r33295 14101 14101 <interface 14102 14102 name="IEventSource" extends="$unknown" 14103 uuid=" 3c670618-f727-4fe9-94d2-8243f489a033"14103 uuid="9b6e1aee-35f3-4f4d-b5bb-ed0ecefd8538" 14104 14104 wsmap="managed" 14105 14105 > … … 14121 14121 </method> 14122 14122 14123 <method name="createAggregator"> 14124 <desc> 14125 Creates a aggregator event source, collecting events from multiple source. 14126 This way single listener can collect events from multiple sources, using 14127 getEvent() of this aggregator. 14128 </desc> 14129 <param name="subordinates" type="IEventSource" dir="in" safearray="yes"> 14130 <desc> 14131 Subordinate event source this one aggregatres. 14132 </desc> 14133 </param> 14134 <param name="result" type="IEventSource" dir="return"/> 14135 </method> 14136 14123 14137 <method name="registerListener"> 14124 14138 <desc> … … 14128 14142 To avoid system overload, the VirtualBox server process checks if passive event 14129 14143 listeners call <link to="IEventSource::getEvent"/> frequently enough. In the 14130 current implementation, if more than 100 pending events are detected for a passive14144 current implementation, if more than 500 pending events are detected for a passive 14131 14145 event listener, it is forcefully unregistered by the system, and further 14132 14146 <link to="#getEvent" /> calls will return @c VBOX_E_OBJECT_NOT_FOUND.
Note:
See TracChangeset
for help on using the changeset viewer.