EventImpl.cpp revision 94b7446cdceebfaf85efe6c4af03a57342a8031e
/* $Id$ */
/** @file
* VirtualBox COM Event class implementation
*/
/*
* Copyright (C) 2010 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* General Public License (GPL) as published by the Free Software
* Foundation, in version 2 as it comes in the "COPYING" file of the
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*/
#include <list>
#include <map>
#include <deque>
#include "EventImpl.h"
#include "AutoCaller.h"
#include "Logging.h"
#include <iprt/semaphore.h>
#include <iprt/critsect.h>
{
Data()
:
{}
};
{
m = new Data;
return S_OK;
}
void VBoxEvent::FinalRelease()
{
uninit();
delete m;
}
{
AutoInitSpan autoInitSpan(this);
m->mProcessed = !aWaitable;
do {
if (aWaitable)
{
if (RT_FAILURE(vrc))
{
AssertFailed ();
}
}
} while (0);
/* Confirm a successful initialization */
return rc;
}
{
m->mProcessed = TRUE;
m->mType = VBoxEventType_Invalid;
if (m->mWaitEvent != NIL_RTSEMEVENT)
{
::RTSemEventDestroy(m->mWaitEvent);
}
}
{
AutoCaller autoCaller(this);
// never changes till event alive, no locking?
return S_OK;
}
{
AutoCaller autoCaller(this);
return S_OK;
}
{
AutoCaller autoCaller(this);
// never changes till event alive, no locking?
return S_OK;
}
{
AutoCaller autoCaller(this);
if (m->mProcessed)
return S_OK;
m->mProcessed = TRUE;
// notify waiters
::RTSemEventSignal(m->mWaitEvent);
return S_OK;
}
{
AutoCaller autoCaller(this);
{
if (m->mProcessed)
return S_OK;
}
("RTSemEventWait returned %Rrc\n", vrc));
if (RT_SUCCESS(vrc))
{
AssertMsg(m->mProcessed,
("mProcessed must be set here\n"));
*aResult = m->mProcessed;
}
else
{
}
return S_OK;
}
static const int LastEvent = (int)VBoxEventType_Last;
struct ListenerRecord;
struct ListenerRecord
{
~ListenerRecord();
};
struct EventSource::Data
{
Data() {}
};
{
switch (who)
{
case VBoxEventType_Any:
return TRUE;
return (what == VBoxEventType_OnMachineStateChange)
|| (what == VBoxEventType_OnMachineRegistered);
case VBoxEventType_Invalid:
return FALSE;
}
}
:
{
{
for (int j = FirstEvent; j < LastEvent; j++)
{
{
}
}
}
if (!mActive)
{
::RTSemEventCreate (&mQEvent);
}
}
{
/* Remove references to us from the event map */
for (int j = FirstEvent; j < LastEvent; j++)
{
}
if (!mActive)
{
::RTCritSectDelete(&mcsQLock);
}
}
{
if (mActive)
{
if (aWaitable)
return rc;
}
else
}
{
::RTCritSectEnter(&mcsQLock);
// notify waiters
::RTCritSectLeave(&mcsQLock);
return S_OK;
}
{
::RTCritSectEnter(&mcsQLock);
{
::RTCritSectLeave(&mcsQLock);
::RTCritSectEnter(&mcsQLock);
}
{
}
else
{
}
::RTCritSectLeave(&mcsQLock);
return S_OK;
}
{
{
aEvent->SetProcessed();
}
return S_OK;
}
{}
{}
{
m = new Data;
return S_OK;
}
void EventSource::FinalRelease()
{
uninit();
delete m;
}
{
AutoInitSpan autoInitSpan(this);
/* Confirm a successful initialization */
return rc;
}
void EventSource::uninit()
{
m->mListeners.clear();
// m->mEvMap shall be cleared at this point too by destructors
}
{
AutoCaller autoCaller(this);
E_FAIL);
return S_OK;
}
{
AutoCaller autoCaller(this);
return setError(E_INVALIDARG,
tr("This listener already registered"));
m->mListeners.insert(
);
return S_OK;
}
{
AutoCaller autoCaller(this);
{
// destructor removes refs from the event map
}
else
{
tr("Listener was never registered"));
}
return rc;
}
{
AutoCaller autoCaller(this);
if (cListeners > 0 && aWaitable)
{
// we keep it here to allow processing active listeners without pending events lookup
}
{
// @todo: callback under (read) lock, is it good?
// what to do with cbRc?
}
if (aWaitable)
else
*aProcessed = TRUE;
return hrc;
}
{
AutoCaller autoCaller(this);
else
tr("Listener was never registered"));
return rc;
}
{
AutoCaller autoCaller(this);
{
return setError(E_INVALIDARG,
tr("Only applicable to passive listeners"));
if (aWaitable)
{
{
AssertFailed();
tr("Unknown event"));
}
else
}
else
{
// for non-waitable events we're done
}
}
else
{
tr("Listener was never registered"));
}
return rc;
}