Recalculation of timeouts with g_timeout_add

View: New views
7 Messages — Rating Filter:   Alert me  

Recalculation of timeouts with g_timeout_add

by Mitko Haralanov-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

I have a question about g_timeout_add's timeout recalculation.

Currently, the next call time is calculated based on <time of callback
thread start> + <timeout given to g_timeout_add>. This means that if I
call g_timeout_add with a timeout of 20*1000 msecs (20 seconds) and my
callback takes 10 seconds to complete, my callback will be called 10
seconds after it completes. Here is an example:

#include <gtk/gtk.h>
#include <glib.h>
#include <time.h>
#include <stdio.h>

gboolean callback (gpointer data) {
     int timeout = *((int *)data);
     printf ("callback called at: %lu\n", time (NULL));
     sleep (timeout);
     printf ("callback returns at: %lu\n", time (NULL));
     return TRUE;
}

int main (int argc, char **argv) {
     int timeout = 10;
     gtk_init (&argc, &argv);
     g_timeout_add (20*1000, callback, (gpointer)&timeout);
     gtk_main ();
}


will produce this:
callback called at: 1210893003
callback returns at: 1210893013
callback called at: 1210893023
callback returns at: 1210893033
callback called at: 1210893043

What I would to happen is that my callback is called 20 seconds after
it returns, not 20 seconds after it is started.

How can I accomplish this?

--
Mitko Haralanov
==========================================
What this country needs is a good five cent microcomputer.
_______________________________________________
gtk-app-devel-list mailing list
gtk-app-devel-list@...
http://mail.gnome.org/mailman/listinfo/gtk-app-devel-list

Re: Recalculation of timeouts with g_timeout_add

by Pascal Bonfils :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

I haven't tried to pass the timeout value but what do is with a global
variable.

Imagine that you have the reference of the timeout, as a global variable :
    guint TimeOut_Ref;

then you have a first call to your callback function
    TimeOut_Ref = g_timeout_add (20*1000, callback, (gpointer)&timeout);

you stop the timeout just when you enter the function :
    gboolean callback (gpointer data) {
        if (TimeOut_Ref > 0) {
            g_source_remove(TimeOut_Ref);
            TimeOut_Ref = 0;
            }
        ....
Then, at the end of you called function, just before the return, you
reactivate the timeout :
        .....
        TimeOut_Ref = g_timeout_add (20*1000, callback, (gpointer)&timeout);
         return TRUE;
    }


Regards

Pascal


Mitko Haralanov a écrit :

> I have a question about g_timeout_add's timeout recalculation.
>
> Currently, the next call time is calculated based on <time of callback
> thread start> + <timeout given to g_timeout_add>. This means that if I
> call g_timeout_add with a timeout of 20*1000 msecs (20 seconds) and my
> callback takes 10 seconds to complete, my callback will be called 10
> seconds after it completes. Here is an example:
>
> #include <gtk/gtk.h>
> #include <glib.h>
> #include <time.h>
> #include <stdio.h>
>
> gboolean callback (gpointer data) {
>      int timeout = *((int *)data);
>      printf ("callback called at: %lu\n", time (NULL));
>      sleep (timeout);
>      printf ("callback returns at: %lu\n", time (NULL));
>      return TRUE;
> }
>
> int main (int argc, char **argv) {
>      int timeout = 10;
>      gtk_init (&argc, &argv);
>      g_timeout_add (20*1000, callback, (gpointer)&timeout);
>      gtk_main ();
> }
>
>
> will produce this:
> callback called at: 1210893003
> callback returns at: 1210893013
> callback called at: 1210893023
> callback returns at: 1210893033
> callback called at: 1210893043
>
> What I would to happen is that my callback is called 20 seconds after
> it returns, not 20 seconds after it is started.
>
> How can I accomplish this?
>
>  

_______________________________________________
gtk-app-devel-list mailing list
gtk-app-devel-list@...
http://mail.gnome.org/mailman/listinfo/gtk-app-devel-list

Re: Recalculation of timeouts with g_timeout_add

by G Hasse-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Let your callback return FALSE and reregister before the return

#include <glib.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

gboolean callback (gpointer data) {

  int seconds = 0;
  struct tm *mytm;
  time_t mytime;

  mytime = time( NULL );
  mytm = gmtime( &mytime );
 
  printf("Called :");  
  printf( "%d-%2.2d-%2.2d ", mytm->tm_year+1900,
mytm->tm_mon+1,mytm->tm_mday);
  printf( "%2.2d:%2.2d:%2.2d\n", mytm->tm_hour,
mytm->tm_min,mytm->tm_sec);

  // Sleeping som random time
  seconds = random()%5+1;
  sleep(seconds);
 
  g_timeout_add (10*1000, callback, NULL );

  mytime = time( NULL );
  mytm = gmtime( &mytime );

  printf("Return :");  
  printf( "%d-%2.2d-%2.2d ", mytm->tm_year+1900,
mytm->tm_mon+1,mytm->tm_mday);
  printf( "%2.2d:%2.2d:%2.2d\n", mytm->tm_hour,
mytm->tm_min,mytm->tm_sec);
 
  //printf ("callback returns at: %lu\n", time (NULL));
  return FALSE;
 
}


int main( int argc, char ** argv )
{

  GMainLoop *loop;
  loop = g_main_new( TRUE );
  g_timeout_add (10*1000, callback, NULL )
  g_main_run( loop );
  return(0);
}



--
Göran Hasse

----------------------------------------------------------------
Göran Hasse           email: gorhas@...  Tel: 019-450105
Raditex AB             http://www.raditex.se   
Planiavägen 15, 1tr                             Mob: 070-5530148
131 34  NACKA, SWEDEN                         OrgNr: 556240-0589
VAT: SE556240058901
------------------------------------------------------------------

_______________________________________________
gtk-app-devel-list mailing list
gtk-app-devel-list@...
http://mail.gnome.org/mailman/listinfo/gtk-app-devel-list

Re: Recalculation of timeouts with g_timeout_add

by Mitko Haralanov-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Fri, 16 May 2008 09:54:22 +0200
G Hasse <gorhas@...> wrote:

> Let your callback return FALSE and reregister before the return

Hi, I thought of that but I was sure that there is a better way to do
this without playing games with unregistering and re-registering the
timeout.

I am not sure why the GTK devs decided that re-calculating the timeout
based on the time right after the timeout thread is started is the
right thing to do but it seems very wrong to me.

What if the timeout function takes longer then the timeout itself? You
end up with multiple threads running the timeout function at the same
time.

--
Mitko Haralanov
==========================================
System going down at 1:45 this afternoon for disk crashing.
_______________________________________________
gtk-app-devel-list mailing list
gtk-app-devel-list@...
http://mail.gnome.org/mailman/listinfo/gtk-app-devel-list

Re: Recalculation of timeouts with g_timeout_add

by datallah :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Fri, May 16, 2008 at 1:20 PM, Mitko Haralanov <mitko@...> wrote:

> On Fri, 16 May 2008 09:54:22 +0200
> G Hasse <gorhas@...> wrote:
>
>> Let your callback return FALSE and reregister before the return
>
> Hi, I thought of that but I was sure that there is a better way to do
> this without playing games with unregistering and re-registering the
> timeout.
>
> I am not sure why the GTK devs decided that re-calculating the timeout
> based on the time right after the timeout thread is started is the
> right thing to do but it seems very wrong to me.

It isn't a "timeout thread", it just a function that is run in the main loop.
It really isn't a matter of right or wrong, it comes down to the fact
that it had to work one way and it so happens that it works like this.
Depending on your intended usage, the way that subsequent timeouts are
called may or may be what you want.

> What if the timeout function takes longer then the timeout itself? You
> end up with multiple threads running the timeout function at the same
> time.

No, the timeout function will block the main loop until it completes;
there will not be multiple threads running your timeout function.

-D
_______________________________________________
gtk-app-devel-list mailing list
gtk-app-devel-list@...
http://mail.gnome.org/mailman/listinfo/gtk-app-devel-list

Re: Recalculation of timeouts with g_timeout_add

by jcupitt :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

2008/5/16 Mitko Haralanov <mitko@...>:
>  I am not sure why the GTK devs decided that re-calculating the timeout
>  based on the time right after the timeout thread is started is the
>  right thing to do but it seems very wrong to me.

I think the idea is that the timeout might represent a counter. If you
set a 1s timeout, you can expect that after 5 calls (for example)
about 5s will have passed.

>  What if the timeout function takes longer then the timeout itself? You
>  end up with multiple threads running the timeout function at the same
>  time.

No, glib never runs more than one callback at once. They will just
queue up and run when the mainloop becomes idle again.

John
_______________________________________________
gtk-app-devel-list mailing list
gtk-app-devel-list@...
http://mail.gnome.org/mailman/listinfo/gtk-app-devel-list

Re: Recalculation of timeouts with g_timeout_add

by Luis Menina-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


Mitko Haralanov a écrit :

> On Fri, 16 May 2008 09:54:22 +0200
> G Hasse <gorhas@...> wrote:
>
>> Let your callback return FALSE and reregister before the return
>
> Hi, I thought of that but I was sure that there is a better way to do
> this without playing games with unregistering and re-registering the
> timeout.
>
> I am not sure why the GTK devs decided that re-calculating the timeout
> based on the time right after the timeout thread is started is the
> right thing to do but it seems very wrong to me.

I think this is really the best solution. And by the way, this timeout
comportment (counting elapsed time since last time the callback was
called) is the right thing to do, as it's the most common case. Just
because your current problem has different needs doesn't mean it was the
wrong choice. How could you trigger an event, say, 10 times per second
otherwise (for an animation for example) ?

> What if the timeout function takes longer then the timeout itself? You
> end up with multiple threads running the timeout function at the same
> time.

As already specified, there's only the main thread. GTK doesn't create
other threads alone.

Oh, and you should use g_timeout_add_seconds for timeouts > 1s.

For your example, just set the timeout at the end of the callback, and
return always FALSE. To set it the first time, just call the callback
alone. That way the callback is called 20 seconds after the last
callback call ended (I didn't tested the code, but it should work).

#include <gtk/gtk.h>
#include <glib.h>
#include <time.h>
#include <stdio.h>

gboolean callback (gpointer data) {
      int timeout = GPOINTER_TO_INT (data);
      printf ("callback called at: %lu\n", time (NULL));
      sleep (timeout);
      printf ("callback returns at: %lu\n", time (NULL));
      g_timeout_add_seconds (20, callback, GINT_TO_POINTER (timeout));
      return FALSE;
}

int main (int argc, char **argv) {
      int timeout = 10;
      gtk_init (&argc, &argv);
      callback (GINT_TO_POINTER (timeout);
      gtk_main ();
}



Also, you should give a look to GTimer, with is nice to use when you
want to measure timings.


Cheers,

Luis
_______________________________________________
gtk-app-devel-list mailing list
gtk-app-devel-list@...
http://mail.gnome.org/mailman/listinfo/gtk-app-devel-list