Pierre Mageau
[wine/multimedia.git] / server / timer.c
blob0a20ca160c49ba9ea57c9a82db087d8596abaa8b
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 "winerror.h"
15 #include "handle.h"
16 #include "request.h"
18 /* FIXME: check values and move to standard header */
19 #define TIMER_MODIFY_STATE 0x0001
20 #define TIMER_QUERY_STATE 0x0002
21 #define TIMER_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|0x3)
23 struct timer
25 struct object obj; /* object header */
26 int manual; /* manual reset */
27 int signaled; /* current signaled state */
28 int period; /* timer period in ms */
29 struct timeval when; /* next expiration */
30 struct timeout_user *timeout; /* timeout user */
31 void *callback; /* callback APC function */
32 void *arg; /* callback argument */
35 static void timer_dump( struct object *obj, int verbose );
36 static int timer_signaled( struct object *obj, struct thread *thread );
37 static int timer_satisfied( struct object *obj, struct thread *thread );
38 static void timer_destroy( struct object *obj );
40 static const struct object_ops timer_ops =
42 sizeof(struct timer),
43 timer_dump,
44 add_queue,
45 remove_queue,
46 timer_signaled,
47 timer_satisfied,
48 no_read_fd,
49 no_write_fd,
50 no_flush,
51 no_get_file_info,
52 timer_destroy
56 /* create a timer object */
57 static struct timer *create_timer( const WCHAR *name, size_t len, int manual )
59 struct timer *timer;
61 if ((timer = create_named_object( &timer_ops, name, len )))
63 if (get_error() != ERROR_ALREADY_EXISTS)
65 /* initialize it if it didn't already exist */
66 timer->manual = manual;
67 timer->signaled = 0;
68 timer->when.tv_sec = 0;
69 timer->when.tv_usec = 0;
70 timer->period = 0;
71 timer->timeout = NULL;
74 return timer;
77 /* callback on timer expiration */
78 static void timer_callback( void *private )
80 struct timer *timer = (struct timer *)private;
82 if (timer->period) /* schedule the next expiration */
84 make_timeout( &timer->when, timer->period );
85 timer->timeout = add_timeout_user( &timer->when, timer_callback, timer );
87 else timer->timeout = NULL;
89 /* wake up waiters */
90 timer->signaled = 1;
91 wake_up( &timer->obj, 0 );
94 /* set the timer expiration and period */
95 static void set_timer( struct timer *timer, int sec, int usec, int period,
96 void *callback, void *arg )
98 if (timer->manual)
100 period = 0; /* period doesn't make any sense for a manual timer */
101 timer->signaled = 0;
103 if (timer->timeout) remove_timeout_user( timer->timeout );
104 timer->when.tv_sec = sec;
105 timer->when.tv_usec = usec;
106 timer->period = period;
107 timer->callback = callback;
108 timer->arg = arg;
109 timer->timeout = add_timeout_user( &timer->when, timer_callback, timer );
112 /* cancel a running timer */
113 static void cancel_timer( struct timer *timer )
115 if (timer->timeout)
117 remove_timeout_user( timer->timeout );
118 timer->timeout = NULL;
122 static void timer_dump( struct object *obj, int verbose )
124 struct timer *timer = (struct timer *)obj;
125 assert( obj->ops == &timer_ops );
126 fprintf( stderr, "Timer manual=%d when=%ld.%06ld period=%d ",
127 timer->manual, timer->when.tv_sec, timer->when.tv_usec, timer->period );
128 dump_object_name( &timer->obj );
129 fputc( '\n', stderr );
132 static int timer_signaled( struct object *obj, struct thread *thread )
134 struct timer *timer = (struct timer *)obj;
135 assert( obj->ops == &timer_ops );
136 return timer->signaled;
139 static int timer_satisfied( struct object *obj, struct thread *thread )
141 struct timer *timer = (struct timer *)obj;
142 assert( obj->ops == &timer_ops );
143 if (!timer->manual) timer->signaled = 0;
144 return 0;
147 static void timer_destroy( struct object *obj )
149 struct timer *timer = (struct timer *)obj;
150 assert( obj->ops == &timer_ops );
152 if (timer->timeout) remove_timeout_user( timer->timeout );
155 /* create a timer */
156 DECL_HANDLER(create_timer)
158 size_t len = get_req_strlenW( req->name );
159 struct timer *timer;
161 req->handle = -1;
162 if ((timer = create_timer( req->name, len, req->manual )))
164 req->handle = alloc_handle( current->process, timer, TIMER_ALL_ACCESS, req->inherit );
165 release_object( timer );
169 /* open a handle to a timer */
170 DECL_HANDLER(open_timer)
172 size_t len = get_req_strlenW( req->name );
173 req->handle = open_object( req->name, len, &timer_ops, req->access, req->inherit );
176 /* set a waitable timer */
177 DECL_HANDLER(set_timer)
179 struct timer *timer;
181 if ((timer = (struct timer *)get_handle_obj( current->process, req->handle,
182 TIMER_MODIFY_STATE, &timer_ops )))
184 set_timer( timer, req->sec, req->usec, req->period, req->callback, req->arg );
185 release_object( timer );
189 /* cancel a waitable timer */
190 DECL_HANDLER(cancel_timer)
192 struct timer *timer;
194 if ((timer = (struct timer *)get_handle_obj( current->process, req->handle,
195 TIMER_MODIFY_STATE, &timer_ops )))
197 cancel_timer( timer );
198 release_object( timer );