File: async.h

package info (click to toggle)
wine 0.0.20020411-1
  • links: PTS
  • area: main
  • in suites: woody
  • size: 43,012 kB
  • ctags: 104,265
  • sloc: ansic: 550,196; perl: 21,747; yacc: 3,990; sh: 3,904; makefile: 3,297; tcl: 2,616; lex: 2,443
file content (126 lines) | stat: -rw-r--r-- 3,725 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
/*
 * Structures and static functions for handling asynchronous I/O.
 *
 * Copyright (C) 2002 Mike McCormack,  Martin Wilck
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

/*
 * This file declares static functions.
 * It should only be included by those source files that implement async I/O requests.
 */

#ifndef __WINE_ASYNC_H
#define __WINE_ASYNC_H

#include "wine/server.h"

struct async_private;

typedef void (*async_handler)(struct async_private *ovp);
typedef void CALLBACK (*async_call_completion_func)(ULONG_PTR data);
typedef DWORD (*async_get_status)(const struct async_private *ovp);
typedef DWORD (*async_get_count)(const struct async_private *ovp);
typedef void (*async_set_status)(struct async_private *ovp, const DWORD status);

typedef struct async_ops
{
    async_get_status            get_status;
    async_set_status            set_status;
    async_get_count             get_count;
    async_call_completion_func  call_completion;
} async_ops;

typedef struct async_private
{
    struct async_ops     *ops;
    HANDLE        handle;
    HANDLE        event;
    int           fd;
    async_handler func;
    int           type;
    struct async_private *next;
    struct async_private *prev;
} async_private;

/* All functions declared static for Dll separation purposes */

inline static void finish_async( async_private *ovp )
{
    if(ovp->prev)
        ovp->prev->next = ovp->next;
    else
        NtCurrentTeb()->pending_list = ovp->next;

    if(ovp->next)
        ovp->next->prev = ovp->prev;

    ovp->next = ovp->prev = NULL;

    close( ovp->fd );
    if( ovp->event != INVALID_HANDLE_VALUE )
        NtSetEvent( ovp->event, NULL );

    QueueUserAPC( ovp->ops->call_completion, GetCurrentThread(), (ULONG_PTR)ovp );
}

inline static BOOL __register_async( async_private *ovp, const DWORD status )
{
    BOOL ret;

    SERVER_START_REQ( register_async )
    {
        req->handle = ovp->handle;
        req->overlapped = ovp;
        req->type = ovp->type;
        req->count = ovp->ops->get_count( ovp );
        req->status = status;
        ret = wine_server_call( req );
    }
    SERVER_END_REQ;

    if ( ret ) ovp->ops->set_status ( ovp, GetLastError() );
    if ( ovp->ops->get_status (ovp) != STATUS_PENDING )
        finish_async (ovp);

    return ret;
}

#define register_old_async(ovp) \
    __register_async (ovp, ovp->ops->get_status( ovp ));

inline static BOOL register_new_async( async_private *ovp )
{
    ovp->ops->set_status ( ovp, STATUS_PENDING );

    ovp->next = NtCurrentTeb()->pending_list;
    ovp->prev = NULL;
    if ( ovp->next ) ovp->next->prev = ovp;
    NtCurrentTeb()->pending_list = ovp;

    return __register_async( ovp, STATUS_PENDING );
}

inline static BOOL cancel_async ( async_private *ovp )
{
     /* avoid multiple cancellations */
     if ( ovp->ops->get_status( ovp ) != STATUS_PENDING )
          return 0;
     ovp->ops->set_status ( ovp, STATUS_CANCELLED );
     return __register_async ( ovp, STATUS_CANCELLED );
}

#endif /* __WINE_ASYNC_H */