summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/thr_timer.h2
-rw-r--r--mysys/thr_timer.c31
2 files changed, 32 insertions, 1 deletions
diff --git a/include/thr_timer.h b/include/thr_timer.h
index 4f0c4f08660..6bca815480b 100644
--- a/include/thr_timer.h
+++ b/include/thr_timer.h
@@ -23,6 +23,7 @@ extern "C" {
typedef struct st_timer {
struct timespec expire_time;
+ ulonglong period;
my_bool expired;
uint index_in_queue;
void (*func)(void*);
@@ -36,6 +37,7 @@ void end_thr_timer();
/* Functions for handling one timer */
void thr_timer_init(thr_timer_t *timer_data, void(*function)(void*),
void *arg);
+void thr_timer_set_period(thr_timer_t* timer_data, ulonglong microseconds);
my_bool thr_timer_settime(thr_timer_t *timer_data, ulonglong microseconds);
void thr_timer_end(thr_timer_t *timer_data);
diff --git a/mysys/thr_timer.c b/mysys/thr_timer.c
index 1532875d7f3..f87c1f75555 100644
--- a/mysys/thr_timer.c
+++ b/mysys/thr_timer.c
@@ -85,7 +85,7 @@ my_bool init_thr_timer(uint alloc_timers)
/* Create a thread to handle timers */
pthread_attr_init(&thr_attr);
pthread_attr_setscope(&thr_attr,PTHREAD_SCOPE_PROCESS);
- pthread_attr_setstacksize(&thr_attr,8196);
+ pthread_attr_setstacksize(&thr_attr,64*1024);
thr_timer_inited= 1;
if (mysql_thread_create(key_thread_timer, &timer_thread, &thr_attr,
timer_handler, NULL))
@@ -141,6 +141,18 @@ void thr_timer_init(thr_timer_t *timer_data, void(*function)(void*),
DBUG_VOID_RETURN;
}
+/*
+ Make timer periodic
+
+ @param timer_data Timer structure
+ @param micro_seconds Period
+*/
+void thr_timer_set_period(thr_timer_t* timer_data, ulonglong micro_seconds)
+{
+ DBUG_ENTER("thr_timer_set_period");
+ timer_data->period= micro_seconds;
+ DBUG_VOID_RETURN;
+}
/*
Request timer after X milliseconds
@@ -240,18 +252,35 @@ static sig_handler process_timers(struct timespec *now)
{
void (*function)(void*);
void *func_arg;
+ my_bool is_periodic;
timer_data= (thr_timer_t*) queue_top(&timer_queue);
function= timer_data->func;
func_arg= timer_data->func_arg;
+ is_periodic= timer_data->period != 0;
timer_data->expired= 1; /* Mark expired */
/*
We remove timer before calling timer function to allow thread to
delete it's timer data any time.
+
+ Deleting timer inside the callback would not work
+ for periodic timers, they need to be removed from
+ queue prior to destroying timer_data.
*/
queue_remove_top(&timer_queue); /* Remove timer */
(*function)(func_arg); /* Inform thread of timeout */
+ /*
+ If timer is periodic, recalculate next expiration time, and
+ reinsert it into the queue.
+ */
+ if (is_periodic && timer_data->period)
+ {
+ set_timespec_nsec(timer_data->expire_time, timer_data->period * 1000);
+ timer_data->expired= 0;
+ queue_insert(&timer_queue, (uchar*)timer_data);
+ }
+
/* Check if next one has also expired */
timer_data= (thr_timer_t*) queue_top(&timer_queue);
if (cmp_timespec(timer_data->expire_time, (*now)) > 0)