- rewrite of the named pipe code
[wine] / server / async.c
1 /*
2  * Server-side support for async i/o operations
3  *
4  * Copyright (C) 1998 Alexandre Julliard
5  * Copyright (C) 2000 Mike McCormack
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  */
21
22 #include "config.h"
23
24 #include <assert.h>
25 #include <string.h>
26 #include <stdlib.h>
27 #include <unistd.h>
28 #include <stdio.h>
29
30 #include "handle.h"
31 #include "file.h"
32 #include "thread.h"
33 #include "request.h"
34
35 #include "async.h"
36
37 void destroy_async( struct async *async )
38 {
39     struct async_queue *aq = async->q;
40
41     /*fprintf(stderr,"destroyed async %p\n",async->overlapped); */
42
43     if(async->timeout)
44         remove_timeout_user(async->timeout);
45     async->timeout = NULL;
46
47     if(async->prev)
48         async->prev->next = async->next;
49     else
50         aq->head = async->next;
51
52     if(async->next)
53         async->next->prev = async->prev;
54     else
55         aq->tail = async->prev;
56
57     async->q = NULL;
58     async->next = NULL;
59     async->prev = NULL;
60     release_object( async->thread );
61     free(async);
62 }
63
64 void async_notify(struct async *async, int status)
65 {
66     /* fprintf(stderr,"notifying %p!\n",async->overlapped); */
67     async->status = status;
68     thread_queue_apc(async->thread, NULL, NULL, APC_ASYNC_IO, 1,
69                      async->overlapped, (void *)status, NULL );
70 }
71
72 void destroy_async_queue( struct async_queue *q )
73 {
74     while(q->head)
75     {
76         async_notify(q->head, STATUS_CANCELLED);
77         destroy_async(q->head);
78     }
79 }
80
81 struct async *find_async(struct async_queue *q, struct thread *thread, void *overlapped)
82 {
83     struct async *async;
84
85     /* fprintf(stderr,"find_async: %p\n",overlapped); */
86
87     if(!q)
88         return NULL;
89
90     for(async = q->head; async; async = async->next)
91         if((async->overlapped==overlapped) && (async->thread == thread))
92              return async;
93
94     return NULL;
95 }
96
97 void async_insert(struct async_queue *q, struct async *async)
98 {
99     async->q = q;
100     async->prev = q->tail;
101     async->next = NULL;
102
103     if(q->tail)
104         q->tail->next = async;
105     else
106         q->head = async;
107
108     q->tail = async;
109 }
110
111 static void async_callback(void *private)
112 {
113     struct async *async = (struct async *)private;
114
115     /* fprintf(stderr,"%p timeout out\n",async->overlapped); */
116     async->timeout = NULL;
117     async_notify(async, STATUS_TIMEOUT);
118     destroy_async(async);
119 }
120
121 struct async *create_async(struct object *obj, struct thread *thread,
122                            void *overlapped)
123 {
124     struct async *async = (struct async *) malloc(sizeof(struct async));
125     if(!async)
126     {
127         set_error(STATUS_NO_MEMORY);
128         return NULL;
129     }
130
131     async->obj = obj;
132     async->thread = (struct thread *)grab_object(thread);
133     async->overlapped = overlapped;
134     async->next = NULL;
135     async->prev = NULL;
136     async->q = NULL;
137     async->status = STATUS_PENDING;
138     async->timeout = NULL;
139
140     return async;
141 }
142
143 void async_add_timeout(struct async *async, int timeout)
144 {
145     if(timeout)
146     {
147         gettimeofday( &async->when, 0 );
148         add_timeout( &async->when, timeout );
149         async->timeout = add_timeout_user( &async->when, async_callback, async );
150     }
151 }