When using desktop mode attach all thread inputs together, so that
[wine] / include / async.h
1 /*
2  * Structures and static functions for handling asynchronous I/O.
3  *
4  * Copyright (C) 2002 Mike McCormack,  Martin Wilck
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 /*
22  * This file declares static functions.
23  * It should only be included by those source files that implement async I/O requests.
24  */
25
26 #ifndef __WINE_ASYNC_H
27 #define __WINE_ASYNC_H
28
29 #include "wine/server.h"
30
31 struct async_private;
32
33 typedef void (*async_handler)(struct async_private *ovp);
34 typedef void (CALLBACK *async_call_completion_func)(ULONG_PTR data);
35 typedef DWORD (*async_get_status)(const struct async_private *ovp);
36 typedef DWORD (*async_get_count)(const struct async_private *ovp);
37 typedef void (*async_set_status)(struct async_private *ovp, const DWORD status);
38 typedef void (*async_cleanup)(struct async_private *ovp);
39
40 typedef struct async_ops
41 {
42     async_get_status            get_status;
43     async_set_status            set_status;
44     async_get_count             get_count;
45     async_call_completion_func  call_completion;
46     async_cleanup               cleanup;
47 } async_ops;
48
49 typedef struct async_private
50 {
51     struct async_ops     *ops;
52     HANDLE        handle;
53     HANDLE        event;
54     int           fd;
55     async_handler func;
56     int           type;
57     struct async_private *next;
58     struct async_private *prev;
59 } async_private;
60
61 /* All functions declared static for Dll separation purposes */
62
63 inline static void finish_async( async_private *ovp )
64 {
65     if(ovp->prev)
66         ovp->prev->next = ovp->next;
67     else
68         NtCurrentTeb()->pending_list = ovp->next;
69
70     if(ovp->next)
71         ovp->next->prev = ovp->prev;
72
73     ovp->next = ovp->prev = NULL;
74
75     close( ovp->fd );
76     if( ovp->event != INVALID_HANDLE_VALUE )
77         NtSetEvent( ovp->event, NULL );
78
79     if ( ovp->ops->call_completion )
80         QueueUserAPC( ovp->ops->call_completion, GetCurrentThread(), (ULONG_PTR)ovp );
81     else
82         ovp->ops->cleanup ( ovp );
83 }
84
85 inline static BOOL __register_async( async_private *ovp, const DWORD status )
86 {
87     BOOL ret;
88
89     SERVER_START_REQ( register_async )
90     {
91         req->handle = ovp->handle;
92         req->overlapped = ovp;
93         req->type = ovp->type;
94         req->count = ovp->ops->get_count( ovp );
95         req->status = status;
96         ret = wine_server_call( req );
97     }
98     SERVER_END_REQ;
99
100     if ( ret ) {
101         SetLastError( RtlNtStatusToDosError(ret) );
102         ovp->ops->set_status ( ovp, ret );
103     }
104
105     if ( ovp->ops->get_status (ovp) != STATUS_PENDING )
106         finish_async (ovp);
107
108     return ret;
109 }
110
111 #define register_old_async(ovp) \
112     __register_async (ovp, ovp->ops->get_status( ovp ));
113
114 inline static BOOL register_new_async( async_private *ovp )
115 {
116     ovp->ops->set_status ( ovp, STATUS_PENDING );
117
118     ovp->next = NtCurrentTeb()->pending_list;
119     ovp->prev = NULL;
120     if ( ovp->next ) ovp->next->prev = ovp;
121     NtCurrentTeb()->pending_list = ovp;
122
123     return __register_async( ovp, STATUS_PENDING );
124 }
125
126 inline static BOOL cancel_async ( async_private *ovp )
127 {
128      /* avoid multiple cancellations */
129      if ( ovp->ops->get_status( ovp ) != STATUS_PENDING )
130           return 0;
131      ovp->ops->set_status ( ovp, STATUS_CANCELLED );
132      return __register_async ( ovp, STATUS_CANCELLED );
133 }
134
135 #endif /* __WINE_ASYNC_H */