Add CF_UNICODETEXT as primary text clipboard format.
[wine.git] / server / timer.c
blobd74fc72fe36398bbe5d2f918a205df9bbe44e016
1 /*
2 * Waitable timers management
4 * Copyright (C) 1999 Alexandre Julliard
5 */
7 #include <assert.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <sys/time.h>
11 #include <sys/types.h>
13 #include "winnt.h"
14 #include "handle.h"
15 #include "request.h"
17 struct timer
19 struct object obj; /* object header */
20 int manual; /* manual reset */
21 int signaled; /* current signaled state */
22 int period; /* timer period in ms */
23 struct timeval when; /* next expiration */
24 struct timeout_user *timeout; /* timeout user */
25 struct thread *thread; /* thread that set the APC function */
26 void *callback; /* callback APC function */
27 void *arg; /* callback argument */
30 static void timer_dump( struct object *obj, int verbose );
31 static int timer_signaled( struct object *obj, struct thread *thread );
32 static int timer_satisfied( struct object *obj, struct thread *thread );
33 static void timer_destroy( struct object *obj );
35 static const struct object_ops timer_ops =
37 sizeof(struct timer), /* size */
38 timer_dump, /* dump */
39 add_queue, /* add_queue */
40 remove_queue, /* remove_queue */
41 timer_signaled, /* signaled */
42 timer_satisfied, /* satisfied */
43 NULL, /* get_poll_events */
44 NULL, /* poll_event */
45 no_read_fd, /* get_read_fd */
46 no_write_fd, /* get_write_fd */
47 no_flush, /* flush */
48 no_get_file_info, /* get_file_info */
49 timer_destroy /* destroy */
53 /* create a timer object */
54 static struct timer *create_timer( const WCHAR *name, size_t len, int manual )
56 struct timer *timer;
58 if ((timer = create_named_object( &timer_ops, name, len )))
60 if (get_error() != STATUS_OBJECT_NAME_COLLISION)
62 /* initialize it if it didn't already exist */
63 timer->manual = manual;
64 timer->signaled = 0;
65 timer->when.tv_sec = 0;
66 timer->when.tv_usec = 0;
67 timer->period = 0;
68 timer->timeout = NULL;
69 timer->thread = NULL;
72 return timer;
75 /* callback on timer expiration */
76 static void timer_callback( void *private )
78 struct timer *timer = (struct timer *)private;
80 /* queue an APC */
81 if (timer->thread)
82 thread_queue_apc( timer->thread, &timer->obj, timer->callback, APC_TIMER, 3,
83 (void *)timer->when.tv_sec, (void *)timer->when.tv_usec, timer->arg );
85 if (timer->period) /* schedule the next expiration */
87 add_timeout( &timer->when, timer->period );
88 timer->timeout = add_timeout_user( &timer->when, timer_callback, timer );
90 else timer->timeout = NULL;
92 /* wake up waiters */
93 timer->signaled = 1;
94 wake_up( &timer->obj, 0 );
97 /* cancel a running timer */
98 static void cancel_timer( struct timer *timer )
100 if (timer->timeout)
102 remove_timeout_user( timer->timeout );
103 timer->timeout = NULL;
105 if (timer->thread)
107 thread_cancel_apc( timer->thread, &timer->obj );
108 timer->thread = NULL;
112 /* set the timer expiration and period */
113 static void set_timer( struct timer *timer, int sec, int usec, int period,
114 void *callback, void *arg )
116 cancel_timer( timer );
117 if (timer->manual)
119 period = 0; /* period doesn't make any sense for a manual timer */
120 timer->signaled = 0;
122 if (!sec && !usec)
124 /* special case: use now + period as first expiration */
125 gettimeofday( &timer->when, 0 );
126 add_timeout( &timer->when, period );
128 else
130 timer->when.tv_sec = sec;
131 timer->when.tv_usec = usec;
133 timer->period = period;
134 timer->callback = callback;
135 timer->arg = arg;
136 if (callback) timer->thread = current;
137 timer->timeout = add_timeout_user( &timer->when, timer_callback, timer );
140 static void timer_dump( struct object *obj, int verbose )
142 struct timer *timer = (struct timer *)obj;
143 assert( obj->ops == &timer_ops );
144 fprintf( stderr, "Timer manual=%d when=%ld.%06ld period=%d ",
145 timer->manual, timer->when.tv_sec, timer->when.tv_usec, timer->period );
146 dump_object_name( &timer->obj );
147 fputc( '\n', stderr );
150 static int timer_signaled( struct object *obj, struct thread *thread )
152 struct timer *timer = (struct timer *)obj;
153 assert( obj->ops == &timer_ops );
154 return timer->signaled;
157 static int timer_satisfied( struct object *obj, struct thread *thread )
159 struct timer *timer = (struct timer *)obj;
160 assert( obj->ops == &timer_ops );
161 if (!timer->manual) timer->signaled = 0;
162 return 0;
165 static void timer_destroy( struct object *obj )
167 struct timer *timer = (struct timer *)obj;
168 assert( obj->ops == &timer_ops );
170 if (timer->timeout) remove_timeout_user( timer->timeout );
173 /* create a timer */
174 DECL_HANDLER(create_timer)
176 struct timer *timer;
178 req->handle = -1;
179 if ((timer = create_timer( get_req_data(req), get_req_data_size(req), req->manual )))
181 req->handle = alloc_handle( current->process, timer, TIMER_ALL_ACCESS, req->inherit );
182 release_object( timer );
186 /* open a handle to a timer */
187 DECL_HANDLER(open_timer)
189 req->handle = open_object( get_req_data(req), get_req_data_size(req),
190 &timer_ops, req->access, req->inherit );
193 /* set a waitable timer */
194 DECL_HANDLER(set_timer)
196 struct timer *timer;
198 if ((timer = (struct timer *)get_handle_obj( current->process, req->handle,
199 TIMER_MODIFY_STATE, &timer_ops )))
201 set_timer( timer, req->sec, req->usec, req->period, req->callback, req->arg );
202 release_object( timer );
206 /* cancel a waitable timer */
207 DECL_HANDLER(cancel_timer)
209 struct timer *timer;
211 if ((timer = (struct timer *)get_handle_obj( current->process, req->handle,
212 TIMER_MODIFY_STATE, &timer_ops )))
214 cancel_timer( timer );
215 release_object( timer );