Event loop hangup when using TimeoutSource and IdleSource
- From: Jim Hodapp <james hodapp gmail com>
- To: gtkmm-list gnome org
- Subject: Event loop hangup when using TimeoutSource and IdleSource
- Date: Thu, 24 Sep 2009 13:31:53 -0400
I am trying to create a pretty simple gtkmm application. The purpose
of the application is to display the status of an attached device and
to also send commands to the device to control it. The device is
connected to the computer via a serial port and abstracted by a
library API that I also wrote. My gtkmm application is designed to
poll the device for various status via one function that gets called
every 100 ms via a TimeoutSource.
code:
sigc::slot<bool> timerSlot = sigc::bind(sigc::mem_fun(*this,
&Emsac::updateEMSStatus), true);
sigc::connection conn = Glib::signal_timeout().connect(timerSlot,
STATUS_UPDATE_RATE_MS, Glib::PRIORITY_HIGH_IDLE);
This function looks something like this:
bool Emsac::updateEMSStatus(bool meaningless)
{
// This function gets called every 100 ms,
// so every 10 counts is 1 s:
static uint8_t count = 1;
try {
// Every 1 second:
if (count % 10 == 0)
{
this->getPrimaryPackCurrent();
this->getSecondaryPackCurrent();
}
// Every 2 seconds:
if (count % 20 == 0)
{
...
}
...
}
catch (EMSNotInitialized &e) {
Logger::Instance().Warn("EMS not yet initialized, not updating EMS
Status window data.");
}
++count;
// Cause the timer to fire again:
return true;
}
Each function, such as getPrimaryPackCurrent, sends a command to the
device with a unique message ID. When the device replies, it has that
same message ID attached and the library is setup to call a callback
function with the requested data as function's parameter(s). The
function would look like this:
void Emsac::getPrimaryPackCurrent() throw (EMSNotInitialized)
{
// Make sure that the EMS has been properly initialized before
performing
// this command:
if (!ems_initialized())
throw EMSNotInitialized(__FILE__, __LINE__);
int ret = LIBEMSACI_SUCCESS;
ret = get_primary_pack_current(Emsac::getPrimaryPackCurrentCbWrapper,
(void *)this, sizeof(Emsac));
}
The callback wrapper function looks like this:
void Emsac::getPrimaryPackCurrentCbWrapper(void *pObject, void
*p_user, size_t len)
{
assert(pObject);
assert(p_user);
Emsac *emsac = reinterpret_cast<Emsac *>(pObject);
float current = *(static_cast<float *>(p_user));
Glib::signal_idle().connect(sigc::bind(sigc::mem_fun(*emsac,
&Emsac::getPrimaryPackCurrentCb), current), Glib::PRIORITY_HIGH_IDLE);
}
And then the function that updates the GUI:
bool Emsac::getPrimaryPackCurrentCb(float current)
{
Logger::Instance().Info("Entering " + Helper::Instance
().charArrayToString(__FUNCTION__));
try {
this->labelPPC->set_text(Glib::ustring::format(std::fixed,
setprecision(4), current, " A"));
}
catch (Glib::ConvertError &e) {
this->labelPPC->set_text(Glib::ustring("n/a"));
}
// Disconnect the idle handler from firing again:
return false;
}
The weird part is that this "loop" of calling the updateEMSStatus()
function via the TimeoutSource hangs randomly. It sometimes will hang
after one cycle through (meaning through every status get request that
fires in 1 second, 2 seconds, 5 seconds, etc)), and sometimes it'll do
several cycles through with the timer returning hundreds of times. It
doesn't seem to get stuck in any of my functions, it seems to be the
Glib event loop that is getting stuck because my GUI becomes
completely unresponsive. Any thoughts? Am I not using the Idlesource
in a proper manner? Is this a resource leak somehow? How would I go
about debugging where in the Glib event loop it might be hanging at?
Thanks,
Jim
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]