summaryrefslogtreecommitdiff
path: root/src/VBox/Main/src-all/EventImpl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/VBox/Main/src-all/EventImpl.cpp')
-rw-r--r--src/VBox/Main/src-all/EventImpl.cpp420
1 files changed, 243 insertions, 177 deletions
diff --git a/src/VBox/Main/src-all/EventImpl.cpp b/src/VBox/Main/src-all/EventImpl.cpp
index 0d19c3bdb..820f84b93 100644
--- a/src/VBox/Main/src-all/EventImpl.cpp
+++ b/src/VBox/Main/src-all/EventImpl.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2010-2012 Oracle Corporation
+ * Copyright (C) 2010-2014 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -120,7 +120,7 @@ HRESULT VBoxEvent::init(IEventSource *aSource, VBoxEventType_T aType, BOOL aWait
if (RT_FAILURE(vrc))
{
- AssertFailed ();
+ AssertFailed();
return setError(E_FAIL,
tr("Internal error (%Rrc)"), vrc);
}
@@ -155,19 +155,21 @@ STDMETHODIMP VBoxEvent::COMGETTER(Type)(VBoxEventType_T *aType)
CheckComArgNotNull(aType);
AutoCaller autoCaller(this);
- if (FAILED(autoCaller.rc())) return autoCaller.rc();
+ if (FAILED(autoCaller.rc()))
+ return autoCaller.rc();
- // never changes till event alive, no locking?
+ // never changes while event alive, no locking
*aType = m->mType;
return S_OK;
}
-STDMETHODIMP VBoxEvent::COMGETTER(Source)(IEventSource* *aSource)
+STDMETHODIMP VBoxEvent::COMGETTER(Source)(IEventSource **aSource)
{
CheckComArgOutPointerValid(aSource);
AutoCaller autoCaller(this);
- if (FAILED(autoCaller.rc())) return autoCaller.rc();
+ if (FAILED(autoCaller.rc()))
+ return autoCaller.rc();
m->mSource.queryInterfaceTo(aSource);
return S_OK;
@@ -178,9 +180,10 @@ STDMETHODIMP VBoxEvent::COMGETTER(Waitable)(BOOL *aWaitable)
CheckComArgNotNull(aWaitable);
AutoCaller autoCaller(this);
- if (FAILED(autoCaller.rc())) return autoCaller.rc();
+ if (FAILED(autoCaller.rc()))
+ return autoCaller.rc();
- // never changes till event alive, no locking?
+ // never changes while event alive, no locking
*aWaitable = m->mWaitable;
return S_OK;
}
@@ -189,7 +192,8 @@ STDMETHODIMP VBoxEvent::COMGETTER(Waitable)(BOOL *aWaitable)
STDMETHODIMP VBoxEvent::SetProcessed()
{
AutoCaller autoCaller(this);
- if (FAILED(autoCaller.rc())) return autoCaller.rc();
+ if (FAILED(autoCaller.rc()))
+ return autoCaller.rc();
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
@@ -209,7 +213,8 @@ STDMETHODIMP VBoxEvent::WaitProcessed(LONG aTimeout, BOOL *aResult)
CheckComArgNotNull(aResult);
AutoCaller autoCaller(this);
- if (FAILED(autoCaller.rc())) return autoCaller.rc();
+ if (FAILED(autoCaller.rc()))
+ return autoCaller.rc();
{
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
@@ -249,8 +254,7 @@ STDMETHODIMP VBoxEvent::WaitProcessed(LONG aTimeout, BOOL *aResult)
typedef std::list<Bstr> VetoList;
struct VBoxVetoEvent::Data
{
- Data()
- :
+ Data() :
mVetoed(FALSE)
{}
BOOL mVetoed;
@@ -281,7 +285,8 @@ HRESULT VBoxVetoEvent::init(IEventSource *aSource, VBoxEventType_T aType)
HRESULT rc = S_OK;
// all veto events are waitable
rc = VBoxEvent::init(aSource, aType, TRUE);
- if (FAILED(rc)) return rc;
+ if (FAILED(rc))
+ return rc;
m->mVetoed = FALSE;
m->mVetoList.clear();
@@ -300,7 +305,8 @@ void VBoxVetoEvent::uninit()
STDMETHODIMP VBoxVetoEvent::AddVeto(IN_BSTR aVeto)
{
AutoCaller autoCaller(this);
- if (FAILED(autoCaller.rc())) return autoCaller.rc();
+ if (FAILED(autoCaller.rc()))
+ return autoCaller.rc();
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
@@ -312,12 +318,13 @@ STDMETHODIMP VBoxVetoEvent::AddVeto(IN_BSTR aVeto)
return S_OK;
}
-STDMETHODIMP VBoxVetoEvent::IsVetoed(BOOL * aResult)
+STDMETHODIMP VBoxVetoEvent::IsVetoed(BOOL *aResult)
{
CheckComArgOutPointerValid(aResult);
AutoCaller autoCaller(this);
- if (FAILED(autoCaller.rc())) return autoCaller.rc();
+ if (FAILED(autoCaller.rc()))
+ return autoCaller.rc();
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
@@ -326,13 +333,14 @@ STDMETHODIMP VBoxVetoEvent::IsVetoed(BOOL * aResult)
return S_OK;
}
-STDMETHODIMP VBoxVetoEvent::GetVetos(ComSafeArrayOut(BSTR, aVetos))
+STDMETHODIMP VBoxVetoEvent::GetVetos(ComSafeArrayOut(BSTR, aVetos))
{
if (ComSafeArrayOutIsNull(aVetos))
return E_POINTER;
AutoCaller autoCaller(this);
- if (FAILED(autoCaller.rc())) return autoCaller.rc();
+ if (FAILED(autoCaller.rc()))
+ return autoCaller.rc();
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
com::SafeArray<BSTR> vetos(m->mVetoList.size());
@@ -351,8 +359,8 @@ STDMETHODIMP VBoxVetoEvent::GetVetos(ComSafeArrayOut(BSTR, aVetos))
}
static const int FirstEvent = (int)VBoxEventType_LastWildcard + 1;
-static const int LastEvent = (int)VBoxEventType_Last;
-static const int NumEvents = LastEvent - FirstEvent;
+static const int LastEvent = (int)VBoxEventType_Last;
+static const int NumEvents = LastEvent - FirstEvent;
/**
* Class replacing std::list and able to provide required stability
@@ -367,24 +375,19 @@ public:
* We have to be double linked, as structural modifications in list are delayed
* till element removed, so we have to know our previous one to update its next
*/
- EventMapRecord* mNext;
+ EventMapRecord *mNext;
bool mAlive;
private:
- EventMapRecord* mPrev;
- ListenerRecord* mRef; /* must be weak reference */
+ EventMapRecord *mPrev;
+ ListenerRecord *mRef; /* must be weak reference */
int32_t mRefCnt;
public:
- EventMapRecord(ListenerRecord* aRef)
- :
- mNext(0),
- mAlive(true),
- mPrev(0),
- mRef(aRef),
- mRefCnt(1)
+ EventMapRecord(ListenerRecord *aRef) :
+ mNext(0), mAlive(true), mPrev(0), mRef(aRef), mRefCnt(1)
{}
- EventMapRecord(EventMapRecord& aOther)
+ EventMapRecord(EventMapRecord &aOther)
{
mNext = aOther.mNext;
mPrev = aOther.mPrev;
@@ -408,7 +411,8 @@ public:
void release()
{
- if (ASMAtomicDecS32(&mRefCnt) <= 0) delete this;
+ if (ASMAtomicDecS32(&mRefCnt) <= 0)
+ delete this;
}
// Called when an element is no longer needed
@@ -418,7 +422,7 @@ public:
release();
}
- ListenerRecord* ref()
+ ListenerRecord *ref()
{
return mAlive ? mRef : 0;
}
@@ -473,7 +477,7 @@ public:
EventMapRecord *pCur = mHead;
while (pCur)
{
- EventMapRecord* aNext = pCur->mNext;
+ EventMapRecord *aNext = pCur->mNext;
if (pCur->ref() == aRec)
{
if (pCur == mHead)
@@ -495,13 +499,13 @@ public:
{
EventMapRecord *mCur;
- iterator()
- : mCur(0)
+ iterator() :
+ mCur(0)
{}
explicit
- iterator(EventMapRecord *aCur)
- : mCur(aCur)
+ iterator(EventMapRecord *aCur) :
+ mCur(aCur)
{
// Prevent element removal, till we're at it
if (mCur)
@@ -539,13 +543,13 @@ public:
}
bool
- operator==(const EventMapList::iterator& aOther) const
+ operator==(const EventMapList::iterator &aOther) const
{
return mCur == aOther.mCur;
}
bool
- operator!=(const EventMapList::iterator& aOther) const
+ operator!=(const EventMapList::iterator &aOther) const
{
return mCur != aOther.mCur;
}
@@ -563,7 +567,7 @@ public:
};
typedef EventMapList EventMap[NumEvents];
-typedef std::map<IEvent*, int32_t> PendingEventsMap;
+typedef std::map<IEvent *, int32_t> PendingEventsMap;
typedef std::deque<ComPtr<IEvent> > PassiveQueue;
class ListenerRecord
@@ -571,7 +575,7 @@ class ListenerRecord
private:
ComPtr<IEventListener> mListener;
BOOL mActive;
- EventSource* mOwner;
+ EventSource *mOwner;
RTSEMEVENT mQEvent;
RTCRITSECT mcsQLock;
@@ -580,24 +584,29 @@ private:
uint64_t mLastRead;
public:
- ListenerRecord(IEventListener* aListener,
- com::SafeArray<VBoxEventType_T>& aInterested,
- BOOL aActive,
- EventSource* aOwner);
+ ListenerRecord(IEventListener *aListener,
+ com::SafeArray<VBoxEventType_T> &aInterested,
+ BOOL aActive,
+ EventSource *aOwner);
~ListenerRecord();
- HRESULT process(IEvent* aEvent, BOOL aWaitable, PendingEventsMap::iterator& pit, AutoLockBase& alock);
- HRESULT enqueue(IEvent* aEvent);
- HRESULT dequeue(IEvent* *aEvent, LONG aTimeout, AutoLockBase& aAlock);
- HRESULT eventProcessed(IEvent * aEvent, PendingEventsMap::iterator& pit);
+ HRESULT process(IEvent *aEvent, BOOL aWaitable, PendingEventsMap::iterator &pit, AutoLockBase &alock);
+ HRESULT enqueue(IEvent *aEvent);
+ HRESULT dequeue(IEvent **aEvent, LONG aTimeout, AutoLockBase &aAlock);
+ HRESULT eventProcessed(IEvent *aEvent, PendingEventsMap::iterator &pit);
+ void shutdown();
+
void addRef()
{
ASMAtomicIncS32(&mRefCnt);
}
+
void release()
{
- if (ASMAtomicDecS32(&mRefCnt) <= 0) delete this;
+ if (ASMAtomicDecS32(&mRefCnt) <= 0)
+ delete this;
}
+
BOOL isActive()
{
return mActive;
@@ -611,15 +620,13 @@ template<typename Held>
class RecordHolder
{
public:
- RecordHolder(Held* lr)
- :
- held(lr)
+ RecordHolder(Held *lr) :
+ held(lr)
{
addref();
}
- RecordHolder(const RecordHolder& that)
- :
- held(that.held)
+ RecordHolder(const RecordHolder &that) :
+ held(that.held)
{
addref();
}
@@ -633,7 +640,7 @@ public:
release();
}
- Held* obj()
+ Held *obj()
{
return held;
}
@@ -644,7 +651,7 @@ public:
return *this;
}
private:
- Held* held;
+ Held *held;
void addref()
{
@@ -656,7 +663,7 @@ private:
if (held)
held->release();
}
- void safe_assign (Held *that_p)
+ void safe_assign(Held *that_p)
{
if (that_p)
that_p->addRef();
@@ -665,14 +672,17 @@ private:
}
};
-typedef std::map<IEventListener*, RecordHolder<ListenerRecord> > Listeners;
+typedef std::map<IEventListener *, RecordHolder<ListenerRecord> > Listeners;
struct EventSource::Data
{
- Data() {}
+ Data() : fShutdown(false)
+ {}
+
Listeners mListeners;
EventMap mEvMap;
PendingEventsMap mPendingMap;
+ bool fShutdown;
};
/**
@@ -685,24 +695,22 @@ static BOOL implies(VBoxEventType_T who, VBoxEventType_T what)
case VBoxEventType_Any:
return TRUE;
case VBoxEventType_Vetoable:
- return (what == VBoxEventType_OnExtraDataCanChange)
- || (what == VBoxEventType_OnCanShowWindow);
+ return (what == VBoxEventType_OnExtraDataCanChange)
+ || (what == VBoxEventType_OnCanShowWindow);
case VBoxEventType_MachineEvent:
- return (what == VBoxEventType_OnMachineStateChanged)
- || (what == VBoxEventType_OnMachineDataChanged)
- || (what == VBoxEventType_OnMachineRegistered)
- || (what == VBoxEventType_OnSessionStateChanged)
- || (what == VBoxEventType_OnGuestPropertyChanged);
+ return (what == VBoxEventType_OnMachineStateChanged)
+ || (what == VBoxEventType_OnMachineDataChanged)
+ || (what == VBoxEventType_OnMachineRegistered)
+ || (what == VBoxEventType_OnSessionStateChanged)
+ || (what == VBoxEventType_OnGuestPropertyChanged);
case VBoxEventType_SnapshotEvent:
- return (what == VBoxEventType_OnSnapshotTaken)
- || (what == VBoxEventType_OnSnapshotDeleted)
- || (what == VBoxEventType_OnSnapshotChanged)
- ;
+ return (what == VBoxEventType_OnSnapshotTaken)
+ || (what == VBoxEventType_OnSnapshotDeleted)
+ || (what == VBoxEventType_OnSnapshotChanged) ;
case VBoxEventType_InputEvent:
- return (what == VBoxEventType_OnKeyboardLedsChanged)
- || (what == VBoxEventType_OnMousePointerShapeChanged)
- || (what == VBoxEventType_OnMouseCapabilityChanged)
- ;
+ return (what == VBoxEventType_OnKeyboardLedsChanged)
+ || (what == VBoxEventType_OnMousePointerShapeChanged)
+ || (what == VBoxEventType_OnMouseCapabilityChanged);
case VBoxEventType_Invalid:
return FALSE;
default:
@@ -712,17 +720,14 @@ static BOOL implies(VBoxEventType_T who, VBoxEventType_T what)
return who == what;
}
-ListenerRecord::ListenerRecord(IEventListener* aListener,
- com::SafeArray<VBoxEventType_T>& aInterested,
- BOOL aActive,
- EventSource* aOwner)
- :
- mActive(aActive),
- mOwner(aOwner),
- mRefCnt(0)
+ListenerRecord::ListenerRecord(IEventListener *aListener,
+ com::SafeArray<VBoxEventType_T> &aInterested,
+ BOOL aActive,
+ EventSource *aOwner) :
+ mActive(aActive), mOwner(aOwner), mRefCnt(0)
{
mListener = aListener;
- EventMap* aEvMap = &aOwner->m->mEvMap;
+ EventMap *aEvMap = &aOwner->m->mEvMap;
for (size_t i = 0; i < aInterested.size(); ++i)
{
@@ -740,12 +745,12 @@ ListenerRecord::ListenerRecord(IEventListener* aListener,
if (!mActive)
{
::RTCritSectInit(&mcsQLock);
- ::RTSemEventCreate (&mQEvent);
+ ::RTSemEventCreate(&mQEvent);
mLastRead = RTTimeMilliTS();
}
else
{
- mQEvent =NIL_RTSEMEVENT;
+ mQEvent = NIL_RTSEMEVENT;
RT_ZERO(mcsQLock);
mLastRead = 0;
}
@@ -754,7 +759,7 @@ ListenerRecord::ListenerRecord(IEventListener* aListener,
ListenerRecord::~ListenerRecord()
{
/* Remove references to us from the event map */
- EventMap* aEvMap = &mOwner->m->mEvMap;
+ EventMap *aEvMap = &mOwner->m->mEvMap;
for (int j = FirstEvent; j < LastEvent; j++)
{
(*aEvMap)[j - FirstEvent].remove(this);
@@ -764,7 +769,7 @@ ListenerRecord::~ListenerRecord()
{
// at this moment nobody could add elements to our queue, so we can safely
// clean it up, otherwise there will be pending events map elements
- PendingEventsMap* aPem = &mOwner->m->mPendingMap;
+ PendingEventsMap *aPem = &mOwner->m->mPendingMap;
while (true)
{
ComPtr<IEvent> aEvent;
@@ -786,21 +791,21 @@ ListenerRecord::~ListenerRecord()
}
::RTCritSectDelete(&mcsQLock);
- ::RTSemEventDestroy(mQEvent);
}
+ shutdown();
}
-HRESULT ListenerRecord::process(IEvent* aEvent,
- BOOL aWaitable,
- PendingEventsMap::iterator& pit,
- AutoLockBase& aAlock)
+HRESULT ListenerRecord::process(IEvent *aEvent,
+ BOOL aWaitable,
+ PendingEventsMap::iterator &pit,
+ AutoLockBase &aAlock)
{
if (mActive)
{
/*
* We release lock here to allow modifying ops on EventSource inside callback.
*/
- HRESULT rc = S_OK;
+ HRESULT rc = S_OK;
if (mListener)
{
aAlock.release();
@@ -818,7 +823,7 @@ HRESULT ListenerRecord::process(IEvent* aEvent,
}
-HRESULT ListenerRecord::enqueue (IEvent* aEvent)
+HRESULT ListenerRecord::enqueue(IEvent *aEvent)
{
AssertMsg(!mActive, ("must be passive\n"));
@@ -829,7 +834,7 @@ HRESULT ListenerRecord::enqueue (IEvent* aEvent)
// and events keep coming, or queue is oversized we shall unregister this listener.
uint64_t sinceRead = RTTimeMilliTS() - mLastRead;
size_t queueSize = mQueue.size();
- if ( (queueSize > 1000) || ((queueSize > 500) && (sinceRead > 60 * 1000)))
+ if ((queueSize > 1000) || ((queueSize > 500) && (sinceRead > 60 * 1000)))
{
::RTCritSectLeave(&mcsQLock);
return E_ABORT;
@@ -845,15 +850,15 @@ HRESULT ListenerRecord::enqueue (IEvent* aEvent)
::RTCritSectLeave(&mcsQLock);
- // notify waiters
+ // notify waiters
::RTSemEventSignal(mQEvent);
return S_OK;
}
-HRESULT ListenerRecord::dequeue (IEvent* *aEvent,
- LONG aTimeout,
- AutoLockBase& aAlock)
+HRESULT ListenerRecord::dequeue(IEvent **aEvent,
+ LONG aTimeout,
+ AutoLockBase &aAlock)
{
if (mActive)
return VBOX_E_INVALID_OBJECT_STATE;
@@ -865,7 +870,8 @@ HRESULT ListenerRecord::dequeue (IEvent* *aEvent,
mLastRead = RTTimeMilliTS();
- if (mQueue.empty()) {
+ if (mQueue.empty())
+ {
::RTCritSectLeave(&mcsQLock);
// Speed up common case
if (aTimeout == 0)
@@ -893,7 +899,7 @@ HRESULT ListenerRecord::dequeue (IEvent* *aEvent,
return S_OK;
}
-HRESULT ListenerRecord::eventProcessed (IEvent* aEvent, PendingEventsMap::iterator& pit)
+HRESULT ListenerRecord::eventProcessed(IEvent *aEvent, PendingEventsMap::iterator &pit)
{
if (--pit->second == 0)
{
@@ -905,6 +911,16 @@ HRESULT ListenerRecord::eventProcessed (IEvent* aEvent, PendingEventsMap::iterat
return S_OK;
}
+void ListenerRecord::shutdown()
+{
+ if (mQEvent != NIL_RTSEMEVENT)
+ {
+ RTSEMEVENT tmp = mQEvent;
+ mQEvent = NIL_RTSEMEVENT;
+ ::RTSemEventDestroy(tmp);
+ }
+}
+
EventSource::EventSource()
{}
@@ -924,7 +940,7 @@ void EventSource::FinalRelease()
BaseFinalRelease();
}
-HRESULT EventSource::init(IUnknown *)
+HRESULT EventSource::init()
{
HRESULT rc = S_OK;
@@ -938,32 +954,58 @@ HRESULT EventSource::init(IUnknown *)
void EventSource::uninit()
{
+ {
+ // First of all (before even thinking about entering the uninit span):
+ // make sure that all listeners are are shut down (no pending events or
+ // wait calls), because they cannot be alive without the associated
+ // event source. Otherwise API clients which use long-term (or
+ // indefinite) waits will block VBoxSVC termination (just one example)
+ // for a long time or even infinitely long.
+ AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+ if (!m->fShutdown)
+ {
+ m->fShutdown = true;
+ for (Listeners::iterator it = m->mListeners.begin();
+ it != m->mListeners.end();
+ ++it)
+ {
+ it->second.obj()->shutdown();
+ }
+ }
+ }
+
AutoUninitSpan autoUninitSpan(this);
if (autoUninitSpan.uninitDone())
return;
+
m->mListeners.clear();
// m->mEvMap shall be cleared at this point too by destructors, assert?
}
-STDMETHODIMP EventSource::RegisterListener(IEventListener * aListener,
+STDMETHODIMP EventSource::RegisterListener(IEventListener *aListener,
ComSafeArrayIn(VBoxEventType_T, aInterested),
- BOOL aActive)
+ BOOL aActive)
{
CheckComArgNotNull(aListener);
CheckComArgSafeArrayNotNull(aInterested);
AutoCaller autoCaller(this);
- if (FAILED(autoCaller.rc())) return autoCaller.rc();
+ if (FAILED(autoCaller.rc()))
+ return autoCaller.rc();
{
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+ if (m->fShutdown)
+ return setError(VBOX_E_INVALID_OBJECT_STATE,
+ tr("This event source is already shut down"));
+
Listeners::const_iterator it = m->mListeners.find(aListener);
if (it != m->mListeners.end())
return setError(E_INVALIDARG,
tr("This listener already registered"));
- com::SafeArray<VBoxEventType_T> interested(ComSafeArrayInArg (aInterested));
+ com::SafeArray<VBoxEventType_T> interested(ComSafeArrayInArg(aInterested));
RecordHolder<ListenerRecord> lrh(new ListenerRecord(aListener, interested, aActive, this));
m->mListeners.insert(Listeners::value_type(aListener, lrh));
}
@@ -975,12 +1017,13 @@ STDMETHODIMP EventSource::RegisterListener(IEventListener * aListener,
return S_OK;
}
-STDMETHODIMP EventSource::UnregisterListener(IEventListener * aListener)
+STDMETHODIMP EventSource::UnregisterListener(IEventListener *aListener)
{
CheckComArgNotNull(aListener);
AutoCaller autoCaller(this);
- if (FAILED(autoCaller.rc())) return autoCaller.rc();
+ if (FAILED(autoCaller.rc()))
+ return autoCaller.rc();
HRESULT rc;
{
@@ -990,6 +1033,7 @@ STDMETHODIMP EventSource::UnregisterListener(IEventListener * aListener)
if (it != m->mListeners.end())
{
+ it->second.obj()->shutdown();
m->mListeners.erase(it);
// destructor removes refs from the event map
rc = S_OK;
@@ -1011,15 +1055,16 @@ STDMETHODIMP EventSource::UnregisterListener(IEventListener * aListener)
return rc;
}
-STDMETHODIMP EventSource::FireEvent(IEvent * aEvent,
- LONG aTimeout,
- BOOL *aProcessed)
+STDMETHODIMP EventSource::FireEvent(IEvent *aEvent,
+ LONG aTimeout,
+ BOOL *aProcessed)
{
CheckComArgNotNull(aEvent);
CheckComArgOutPointerValid(aProcessed);
AutoCaller autoCaller(this);
- if (FAILED(autoCaller.rc())) return autoCaller.rc();
+ if (FAILED(autoCaller.rc()))
+ return autoCaller.rc();
HRESULT hrc;
BOOL aWaitable = FALSE;
@@ -1028,6 +1073,10 @@ STDMETHODIMP EventSource::FireEvent(IEvent * aEvent,
do {
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+ if (m->fShutdown)
+ return setError(VBOX_E_INVALID_OBJECT_STATE,
+ tr("This event source is already shut down"));
+
VBoxEventType_T evType;
hrc = aEvent->COMGETTER(Type)(&evType);
AssertComRCReturn(hrc, hrc);
@@ -1074,7 +1123,10 @@ STDMETHODIMP EventSource::FireEvent(IEvent * aEvent,
{
Listeners::iterator lit = m->mListeners.find(record.obj()->mListener);
if (lit != m->mListeners.end())
+ {
+ lit->second.obj()->shutdown();
m->mListeners.erase(lit);
+ }
}
// anything else to do with cbRc?
}
@@ -1090,18 +1142,23 @@ STDMETHODIMP EventSource::FireEvent(IEvent * aEvent,
}
-STDMETHODIMP EventSource::GetEvent(IEventListener * aListener,
- LONG aTimeout,
- IEvent ** aEvent)
+STDMETHODIMP EventSource::GetEvent(IEventListener *aListener,
+ LONG aTimeout,
+ IEvent **aEvent)
{
CheckComArgNotNull(aListener);
AutoCaller autoCaller(this);
- if (FAILED(autoCaller.rc())) return autoCaller.rc();
+ if (FAILED(autoCaller.rc()))
+ return autoCaller.rc();
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+ if (m->fShutdown)
+ return setError(VBOX_E_INVALID_OBJECT_STATE,
+ tr("This event source is already shut down"));
+
Listeners::iterator it = m->mListeners.find(aListener);
HRESULT rc;
@@ -1117,17 +1174,22 @@ STDMETHODIMP EventSource::GetEvent(IEventListener * aListener,
return rc;
}
-STDMETHODIMP EventSource::EventProcessed(IEventListener * aListener,
- IEvent * aEvent)
+STDMETHODIMP EventSource::EventProcessed(IEventListener *aListener,
+ IEvent *aEvent)
{
CheckComArgNotNull(aListener);
CheckComArgNotNull(aEvent);
AutoCaller autoCaller(this);
- if (FAILED(autoCaller.rc())) return autoCaller.rc();
+ if (FAILED(autoCaller.rc()))
+ return autoCaller.rc();
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+ if (m->fShutdown)
+ return setError(VBOX_E_INVALID_OBJECT_STATE,
+ tr("This event source is already shut down"));
+
Listeners::iterator it = m->mListeners.find(aListener);
HRESULT rc;
@@ -1136,11 +1198,11 @@ STDMETHODIMP EventSource::EventProcessed(IEventListener * aListener,
if (it != m->mListeners.end())
{
- ListenerRecord* aRecord = it->second.obj();
+ ListenerRecord *aRecord = it->second.obj();
if (aRecord->isActive())
return setError(E_INVALIDARG,
- tr("Only applicable to passive listeners"));
+ tr("Only applicable to passive listeners"));
if (aWaitable)
{
@@ -1246,14 +1308,14 @@ public:
BaseFinalRelease();
}
- HRESULT init(IEventSource* aSource)
+ HRESULT init(IEventSource *aSource)
{
mSource = aSource;
return S_OK;
}
// IEventListener methods
- STDMETHOD(HandleEvent)(IEvent * aEvent)
+ STDMETHOD(HandleEvent)(IEvent *aEvent)
{
BOOL fProcessed = FALSE;
if (mSource)
@@ -1269,7 +1331,7 @@ class ATL_NO_VTABLE EventSourceAggregator :
{
typedef std::list <ComPtr<IEventSource> > EventSourceList;
/* key is weak reference */
- typedef std::map<IEventListener*, ComPtr<IEventListener> > ProxyListenerMap;
+ typedef std::map<IEventListener *, ComPtr<IEventListener> > ProxyListenerMap;
EventSourceList mEventSources;
ProxyListenerMap mListenerProxies;
@@ -1308,28 +1370,28 @@ public:
HRESULT init(ComSafeArrayIn(IEventSource *, aSources));
// IEventSource methods
- STDMETHOD(CreateListener)(IEventListener ** aListener);
- STDMETHOD(CreateAggregator)(ComSafeArrayIn(IEventSource*, aSubordinates),
- IEventSource ** aAggregator);
- STDMETHOD(RegisterListener)(IEventListener * aListener,
+ STDMETHOD(CreateListener)(IEventListener **aListener);
+ STDMETHOD(CreateAggregator)(ComSafeArrayIn(IEventSource *, aSubordinates),
+ IEventSource **aAggregator);
+ STDMETHOD(RegisterListener)(IEventListener *aListener,
ComSafeArrayIn(VBoxEventType_T, aInterested),
- BOOL aActive);
- STDMETHOD(UnregisterListener)(IEventListener * aListener);
- STDMETHOD(FireEvent)(IEvent * aEvent,
- LONG aTimeout,
- BOOL *aProcessed);
- STDMETHOD(GetEvent)(IEventListener * aListener,
- LONG aTimeout,
- IEvent * *aEvent);
- STDMETHOD(EventProcessed)(IEventListener * aListener,
- IEvent * aEvent);
+ BOOL aActive);
+ STDMETHOD(UnregisterListener)(IEventListener *aListener);
+ STDMETHOD(FireEvent)(IEvent *aEvent,
+ LONG aTimeout,
+ BOOL *aProcessed);
+ STDMETHOD(GetEvent)(IEventListener *aListener,
+ LONG aTimeout,
+ IEvent **aEvent);
+ STDMETHOD(EventProcessed)(IEventListener *aListener,
+ IEvent *aEvent);
protected:
- HRESULT createProxyListener(IEventListener * aListener,
- IEventListener * *aProxy);
- HRESULT getProxyListener (IEventListener * aListener,
- IEventListener * *aProxy);
- HRESULT removeProxyListener(IEventListener * aListener);
+ HRESULT createProxyListener(IEventListener *aListener,
+ IEventListener **aProxy);
+ HRESULT getProxyListener(IEventListener *aListener,
+ IEventListener **aProxy);
+ HRESULT removeProxyListener(IEventListener *aListener);
};
#ifdef VBOX_WITH_XPCOM
@@ -1348,12 +1410,13 @@ NS_IMPL_THREADSAFE_ISUPPORTS1_CI(EventSourceAggregator, IEventSource)
#endif
-STDMETHODIMP EventSource::CreateListener(IEventListener ** aListener)
+STDMETHODIMP EventSource::CreateListener(IEventListener **aListener)
{
CheckComArgOutPointerValid(aListener);
AutoCaller autoCaller(this);
- if (FAILED(autoCaller.rc())) return autoCaller.rc();
+ if (FAILED(autoCaller.rc()))
+ return autoCaller.rc();
ComObjPtr<PassiveEventListener> listener;
@@ -1365,13 +1428,14 @@ STDMETHODIMP EventSource::CreateListener(IEventListener ** aListener)
}
-STDMETHODIMP EventSource::CreateAggregator(ComSafeArrayIn(IEventSource*, aSubordinates),
- IEventSource ** aResult)
+STDMETHODIMP EventSource::CreateAggregator(ComSafeArrayIn(IEventSource *, aSubordinates),
+ IEventSource **aResult)
{
CheckComArgOutPointerValid(aResult);
AutoCaller autoCaller(this);
- if (FAILED(autoCaller.rc())) return autoCaller.rc();
+ if (FAILED(autoCaller.rc()))
+ return autoCaller.rc();
ComObjPtr<EventSourceAggregator> agg;
@@ -1383,12 +1447,11 @@ STDMETHODIMP EventSource::CreateAggregator(ComSafeArrayIn(IEventSource*, aSubord
if (FAILED(rc))
return rc;
-
agg.queryInterfaceTo(aResult);
return S_OK;
}
-HRESULT EventSourceAggregator::init(ComSafeArrayIn(IEventSource*, aSourcesIn))
+HRESULT EventSourceAggregator::init(ComSafeArrayIn(IEventSource *, aSourcesIn))
{
HRESULT rc;
@@ -1398,7 +1461,7 @@ HRESULT EventSourceAggregator::init(ComSafeArrayIn(IEventSource*, aSourcesIn))
rc = mSource.createObject();
ComAssertMsgRet(SUCCEEDED(rc), ("Could not create source (%Rhrc)", rc),
E_FAIL);
- rc = mSource->init((IEventSource*)this);
+ rc = mSource->init();
ComAssertMsgRet(SUCCEEDED(rc), ("Could not init source (%Rhrc)", rc),
E_FAIL);
@@ -1418,26 +1481,27 @@ HRESULT EventSourceAggregator::init(ComSafeArrayIn(IEventSource*, aSourcesIn))
return rc;
}
-STDMETHODIMP EventSourceAggregator::CreateListener(IEventListener ** aListener)
+STDMETHODIMP EventSourceAggregator::CreateListener(IEventListener **aListener)
{
return mSource->CreateListener(aListener);
}
-STDMETHODIMP EventSourceAggregator::CreateAggregator(ComSafeArrayIn(IEventSource*, aSubordinates),
- IEventSource ** aResult)
+STDMETHODIMP EventSourceAggregator::CreateAggregator(ComSafeArrayIn(IEventSource *, aSubordinates),
+ IEventSource **aResult)
{
return mSource->CreateAggregator(ComSafeArrayInArg(aSubordinates), aResult);
}
-STDMETHODIMP EventSourceAggregator::RegisterListener(IEventListener * aListener,
+STDMETHODIMP EventSourceAggregator::RegisterListener(IEventListener *aListener,
ComSafeArrayIn(VBoxEventType_T, aInterested),
- BOOL aActive)
+ BOOL aActive)
{
CheckComArgNotNull(aListener);
CheckComArgSafeArrayNotNull(aInterested);
AutoCaller autoCaller(this);
- if (FAILED(autoCaller.rc())) return autoCaller.rc();
+ if (FAILED(autoCaller.rc()))
+ return autoCaller.rc();
HRESULT rc;
@@ -1462,12 +1526,13 @@ STDMETHODIMP EventSourceAggregator::RegisterListener(IEventListener * aListener,
return rc;
}
-STDMETHODIMP EventSourceAggregator::UnregisterListener(IEventListener * aListener)
+STDMETHODIMP EventSourceAggregator::UnregisterListener(IEventListener *aListener)
{
CheckComArgNotNull(aListener);
AutoCaller autoCaller(this);
- if (FAILED(autoCaller.rc())) return autoCaller.rc();
+ if (FAILED(autoCaller.rc()))
+ return autoCaller.rc();
HRESULT rc = S_OK;
@@ -1490,19 +1555,20 @@ STDMETHODIMP EventSourceAggregator::UnregisterListener(IEventListener * aListene
}
-STDMETHODIMP EventSourceAggregator::FireEvent(IEvent * aEvent,
- LONG aTimeout,
- BOOL *aProcessed)
+STDMETHODIMP EventSourceAggregator::FireEvent(IEvent *aEvent,
+ LONG aTimeout,
+ BOOL *aProcessed)
{
CheckComArgNotNull(aEvent);
CheckComArgOutPointerValid(aProcessed);
AutoCaller autoCaller(this);
- if (FAILED(autoCaller.rc())) return autoCaller.rc();
+ if (FAILED(autoCaller.rc()))
+ return autoCaller.rc();
HRESULT rc = S_OK;
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
- /* Aggresgator event source shalln't have direct event firing, but we may
+ /* Aggregator event source shall not have direct event firing, but we may
wish to support aggregation chains */
for (EventSourceList::const_iterator it = mEventSources.begin(); it != mEventSources.end();
++it)
@@ -1517,21 +1583,21 @@ STDMETHODIMP EventSourceAggregator::FireEvent(IEvent * aEvent,
return S_OK;
}
-STDMETHODIMP EventSourceAggregator::GetEvent(IEventListener * aListener,
- LONG aTimeout,
- IEvent ** aEvent)
+STDMETHODIMP EventSourceAggregator::GetEvent(IEventListener *aListener,
+ LONG aTimeout,
+ IEvent **aEvent)
{
return mSource->GetEvent(aListener, aTimeout, aEvent);
}
-STDMETHODIMP EventSourceAggregator::EventProcessed(IEventListener * aListener,
- IEvent * aEvent)
+STDMETHODIMP EventSourceAggregator::EventProcessed(IEventListener *aListener,
+ IEvent *aEvent)
{
return mSource->EventProcessed(aListener, aEvent);
}
-HRESULT EventSourceAggregator::createProxyListener(IEventListener * aListener,
- IEventListener * *aProxy)
+HRESULT EventSourceAggregator::createProxyListener(IEventListener *aListener,
+ IEventListener **aProxy)
{
ComObjPtr<ProxyEventListener> proxy;
@@ -1554,8 +1620,8 @@ HRESULT EventSourceAggregator::createProxyListener(IEventListener * aListener,
return S_OK;
}
-HRESULT EventSourceAggregator::getProxyListener(IEventListener * aListener,
- IEventListener * *aProxy)
+HRESULT EventSourceAggregator::getProxyListener(IEventListener *aListener,
+ IEventListener **aProxy)
{
ProxyListenerMap::const_iterator it = mListenerProxies.find(aListener);
if (it == mListenerProxies.end())
@@ -1566,7 +1632,7 @@ HRESULT EventSourceAggregator::getProxyListener(IEventListener * aListener,
return S_OK;
}
-HRESULT EventSourceAggregator::removeProxyListener(IEventListener * aListener)
+HRESULT EventSourceAggregator::removeProxyListener(IEventListener *aListener)
{
ProxyListenerMap::iterator it = mListenerProxies.find(aListener);
if (it == mListenerProxies.end())