D-Bus server: more flexible timeouts
Added priorities and proper tracking of "activated" state. The latter depends on having the Timeout instance valid when the callback returns, therefore the Server must delay the deletion of the instance until the callback is done executing. Priorities are needed to order different tasks in the PIM manager correctly. The "activated" state is something that the PIM manager needs to track reliably, which had to be done by every callback. If a callback forgot to do that, in the worst case this might have removed an entirely unrelated source when the tag got reused in the meantime.
This commit is contained in:
parent
44d9b2c989
commit
3c21df32e0
|
@ -274,7 +274,6 @@ void FullView::onIdle()
|
|||
if (isQuiescent()) {
|
||||
m_quiescenceSignal();
|
||||
}
|
||||
m_waitForIdle.deactivate();
|
||||
}
|
||||
|
||||
void FullView::waitForIdle()
|
||||
|
|
|
@ -739,6 +739,10 @@ void Server::passwordResponse(const InfoReq::InfoMap &response,
|
|||
bool Server::callTimeout(const boost::shared_ptr<Timeout> &timeout, const boost::function<void ()> &callback)
|
||||
{
|
||||
callback();
|
||||
// We are executing the timeout, don't invalidate the instance
|
||||
// until later when our caller is no longer using the instance to
|
||||
// call us.
|
||||
delayDeletion(timeout);
|
||||
m_timeouts.remove(timeout);
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -48,6 +48,14 @@ class Timeout : boost::noncopyable
|
|||
boost::function<bool ()> m_callback;
|
||||
|
||||
public:
|
||||
enum {
|
||||
PRIORITY_HIGH = G_PRIORITY_HIGH,
|
||||
PRIORITY_DEFAULT = G_PRIORITY_DEFAULT,
|
||||
PRIORITY_HIGH_IDLE = G_PRIORITY_HIGH_IDLE,
|
||||
PRIORITY_DEFAULT_IDLE = G_PRIORITY_DEFAULT_IDLE,
|
||||
PRIORITY_LOW = G_PRIORITY_LOW
|
||||
};
|
||||
|
||||
Timeout() :
|
||||
m_tag(0)
|
||||
{
|
||||
|
@ -67,7 +75,8 @@ public:
|
|||
* otherwise in the specified amount of time
|
||||
*/
|
||||
void activate(int seconds,
|
||||
const boost::function<bool ()> &callback)
|
||||
const boost::function<bool ()> &callback,
|
||||
int priority = G_PRIORITY_DEFAULT)
|
||||
{
|
||||
deactivate();
|
||||
|
||||
|
@ -80,13 +89,25 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
void activate(const boost::function<bool ()> &idleCallback,
|
||||
int priority = G_PRIORITY_DEFAULT_IDLE)
|
||||
{
|
||||
activate(-1, idleCallback, priority);
|
||||
}
|
||||
|
||||
/**
|
||||
* invoke the callback once
|
||||
*/
|
||||
void runOnce(int seconds,
|
||||
const boost::function<void ()> &callback)
|
||||
const boost::function<void ()> &callback,
|
||||
int priority = G_PRIORITY_DEFAULT)
|
||||
{
|
||||
activate(seconds, boost::bind(&Timeout::once, callback));
|
||||
activate(seconds, boost::bind(&Timeout::once, callback), priority);
|
||||
}
|
||||
void runOnce(const boost::function<void ()> &idleCallback,
|
||||
int priority = G_PRIORITY_DEFAULT)
|
||||
{
|
||||
runOnce(-1, idleCallback, priority);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -107,14 +128,21 @@ public:
|
|||
private:
|
||||
static gboolean triggered(gpointer data) throw ()
|
||||
{
|
||||
Timeout *me = static_cast<Timeout *>(data);
|
||||
bool runAgain = false;
|
||||
try {
|
||||
Timeout *me = static_cast<Timeout *>(data);
|
||||
return me->m_callback();
|
||||
runAgain = me->m_callback();
|
||||
} catch (...) {
|
||||
// Something unexpected went wrong, can only shut down.
|
||||
Exception::handle(HANDLE_EXCEPTION_FATAL);
|
||||
}
|
||||
return false;
|
||||
if (!runAgain) {
|
||||
// Returning false will automatically deactivate the source,
|
||||
// remember that.
|
||||
me->m_tag = 0;
|
||||
me->m_callback = 0;
|
||||
}
|
||||
return runAgain;
|
||||
}
|
||||
|
||||
static bool once(const boost::function<void ()> &callback) {
|
||||
|
|
Loading…
Reference in a new issue