osx - singleshot QTimer on OS X rapid fires multiple times and too early -
i have implemented idle timer on resource (class) instances of can open in several applications @ once. hence, idletimer
not simple qtimer
, slot (trigger) needs verify if no other applications have accessed same resources during last n minutes. if case, timer reset (without updating lastaccessedtime
value), otherwise resource closed. timer singleshot one, , lastaccesstime
kept in qsharedmemory object.
here's trace output:
### "google contacts () of type google contacts" idle timeout 6 min. kwallet::wallet(0x105d1f900) "kdewallet" handle 0 ; elapsed minutes= 5.83601 timer qtimer(0x11d273d60) triggered 1 times ### slotidletimedout ->handleidletiming: setting qtimer(0x11d273d60) wallet "kdewallet" handle 0 timeout 6 ### "google contacts () of type google contacts" idle timeout 6 min. kwallet::wallet(0x105d1f900) "kdewallet" handle 0 ; elapsed minutes= 5.83634 timer qtimer(0x11d273d60) triggered 2 times ### "google contacts () of type google contacts" idle timeout 6 min. kwallet::wallet(0x105d1f900) "kdewallet" handle 0 ; elapsed minutes= 5.83634 timer qtimer(0x11d273d60) triggered 3 times ### "google contacts ()of type google contacts" idle timeout 6 min. kwallet::wallet(0x105d1f900) "kdewallet" handle 0 ; elapsed minutes= 5.83634 timer qtimer(0x11d273d60) triggered 4 times ### "google contacts () of type google contacts" idle timeout 6 min. kwallet::wallet(0x105d1f900) "kdewallet" handle 0 ; elapsed minutes= 5.83634 timer qtimer(0x11d273d60) triggered 5 times ### "google contacts () of type google contacts" idle timeout 6 min. kwallet::wallet(0x105d1f900) "kdewallet" handle 0 ; elapsed minutes= 5.83635 timer qtimer(0x11d273d60) triggered 6 times ### "google contacts () of type google contacts" idle timeout 6 min. kwallet::wallet(0x105d1f900) "kdewallet" handle 0 ; elapsed minutes= 5.83635 timer qtimer(0x11d273d60) triggered 7 times ### "google contacts () of type google contacts" idle timeout 6 min. kwallet::wallet(0x105d1f900) "kdewallet" handle 0 ; elapsed minutes= 5.83635 timer qtimer(0x11d273d60) triggered 8 times ### "kmail" idle timeout 6 min. kwallet::wallet(0x1083f1ac0) "kdewallet" handle 0 ; elapsed minutes= 6 timer qtimer(0x120a1b5f0) triggered 1 times ### "kmail" idle timeout 6 min. kwallet::wallet(0x1083f1ac0) "kdewallet" handle -1 ; elapsed minutes= 6.00008 timer qobject(0x0) triggered 2 times ### "kmail" idle timeout 6 min. kwallet::wallet(0x1083f1ac0) "kdewallet" handle -1 ; elapsed minutes= 6.00009 timer qobject(0x0) triggered 3 times ### "kmail" idle timeout 6 min. kwallet::wallet(0x1083f1ac0) "kdewallet" handle -1 ; elapsed minutes= 6.00012 timer qobject(0x0) triggered 4 times ### "kmail" idle timeout 6 min. kwallet::wallet(0x1083f1ac0) "kdewallet" handle -1 ; elapsed minutes= 6.00012 timer qobject(0x0) triggered 5 times ### "kmail" idle timeout 6 min. kwallet::wallet(0x1083f1ac0) "kdewallet" handle -1 ; elapsed minutes= 6.00012 timer qobject(0x0) triggered 6 times ### "kmail" idle timeout 6 min. kwallet::wallet(0x1083f1ac0) "kdewallet" handle -1 ; elapsed minutes= 6.00012 timer qobject(0x0) triggered 7 times ### "kmail" idle timeout 6 min. kwallet::wallet(0x1083f1ac0) "kdewallet" handle -1 ; elapsed minutes= 6.00012 timer qobject(0x0) triggered 8 times
the principle works, notice 2 things:
- the timer fires bit early. of course causes timer reset.
- it fires several times in fast succession. fact fire should reset doesn't have slightest effect.
below relevant part of code, including function resets timer @ each resource access, , timer's trigger slot.
any idea i'm doing wrong? stop timer before (re)setting singleshot mode , starting (anew). object , application identifiers show indeed same timer triggers multiple times, , can triggered after deleted timer object.
could trigger slot not application (or instance) specific, somehow leading 1 instance receiving idletimer
trigger signals other instances across various applications set instance of timer? idletimer
gets set null in class destructor and/or when timeout
<=0, i'm stymied trigger slot can called null timer object!
from timer install function (handleidletiming
, member of kwallet::wallet
idletimer
itself):
// function called @ every operation supposed launch or reset // idle timing. @p timeout time in minutes. void handleidletiming(const char *caller="", bool touchaccesstime=true) { // ... if( timeout >= 0 ){ if( !idletimer ){ idletimer = new qtimer(0); } else{ idletimer->stop(); } // when idle timer fires, wallet supposed closed. there // no reason use repeating timer. idletimer->setsingleshot(true); connect( idletimer, signal(timeout()), q, slot(slotidletimedout()) ); if( touchaccesstime ){ if( lastaccesstime.lock() ){ *((double*)lastaccesstime.data()) = hrtime_time(); lastaccesstime.unlock(); } else{ qdebug() << "cannot lock lastaccesstime wallet" << name << "error" << lastaccesstime.errorstring(); } } idletimer->start( timeout * 60 * 1000 );
the timer trigger slot:
void wallet::slotidletimedout() { double lastaccesstime = 0; // check last time accessed wallet: if( d->lastaccesstime.lock() ){ lastaccesstime = *((double*)d->lastaccesstime.data()); d->lastaccesstime.unlock(); } else{ qdebug() << "cannot lock lastaccesstime wallet" << d->name << "error" << d->lastaccesstime.errorstring(); } // time elapsed since last access, in minutes: double elapsed = (hrtime_time() - lastaccesstime) / 60; d->idletimertriggered += 1; qdebug() << "###" << appid() << "idle timeout" << d->timeout << "min. for" << << d->name << "handle" << d->handle << "; elapsed minutes=" << elapsed << "timer" << d->idletimer << "triggered" << d->idletimertriggered << "times"; if( elapsed >= d->timeout ){ // have true timeout, i.e. didn't access wallet in timeout minutes, , no 1 else did either. slotwalletclosed(d->handle); } else{ // false alarm, reset timer, there's no need count access! d->handleidletiming(__function__, false); } }
must indeed have been because issued connect statement each time reset timer, instead of once after creating it.
Comments
Post a Comment