summaryrefslogtreecommitdiff
path: root/cutils/selector.h
blob: dfc2a9d3491506108fc4aa4f3f300f256240f1c1 (plain)
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
127
128
129
130
/*
 * Copyright (C) 2007 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Framework for multiplexing I/O. A selector manages a set of file
 * descriptors and calls out to user-provided callback functions to read and
 * write data and handle errors.
 */

#ifndef __SELECTOR_H
#define __SELECTOR_H

#ifdef __cplusplus
extern "C" {
#endif

#include <stdbool.h>
    
/** 
 * Manages SelectableFds and invokes their callbacks at appropriate times. 
 */
typedef struct Selector Selector;

/** 
 * A selectable descriptor. Contains callbacks which the selector can invoke
 * before calling select(), when the descriptor is readable or writable, and 
 * when the descriptor contains out-of-band data. Simply set a callback to 
 * NULL if you're not interested in that particular event.
 *
 * A selectable descriptor can indicate that it needs to be removed from the
 * selector by setting the 'remove' flag. The selector will remove the
 * descriptor at a later time and invoke the onRemove() callback.
 * 
 * SelectableFd fields should only be modified from the selector loop.
 */
typedef struct SelectableFd SelectableFd;
struct SelectableFd {

    /** The file descriptor itself. */
    int fd;
    
    /** Pointer to user-specific data. Can be NULL. */
    void* data;
    
    /** 
     * Set this flag when you no longer wish to be selected. The selector
     * will invoke onRemove() when the descriptor is actually removed.
     */
    bool remove;

    /** 
     * Invoked by the selector before calling select. You can set up other
     * callbacks from here as necessary.
     */
    void (*beforeSelect)(SelectableFd* self);

    /** 
     * Invoked by the selector when the descriptor has data available. Set to
     * NULL to indicate that you're not interested in reading.
     */
    void (*onReadable)(SelectableFd* self);

    /** 
     * Invoked by the selector when the descriptor can accept data. Set to
     * NULL to indicate that you're not interested in writing.
     */
    void (*onWritable)(SelectableFd* self);

    /** 
     * Invoked by the selector when out-of-band (OOB) data is available. Set to
     * NULL to indicate that you're not interested in OOB data.
     */
    void (*onExcept)(SelectableFd* self);

    /**
     * Invoked by the selector after the descriptor is removed from the
     * selector but before the selector frees the SelectableFd memory.
     */
    void (*onRemove)(SelectableFd* self);

    /**
     * The selector which selected this fd. Set by the selector itself.
     */
    Selector* selector;
};

/** 
 * Creates a new selector. 
 */
Selector* selectorCreate(void);

/** 
 * Creates a new selectable fd, adds it to the given selector and returns a 
 * pointer. Outside of 'selector' and 'fd', all fields are set to 0 or NULL 
 * by default.
 * 
 * The selectable fd should only be modified from the selector loop thread.
 */
SelectableFd* selectorAdd(Selector* selector, int fd);

/**
 * Wakes up the selector even though no I/O events occurred. Use this
 * to indicate that you're ready to write to a descriptor.
 */
void selectorWakeUp(Selector* selector);
    
/** 
 * Loops continuously selecting file descriptors and firing events. 
 * Does not return. 
 */
void selectorLoop(Selector* selector);

#ifdef __cplusplus
}
#endif

#endif /* __SELECTOR_H */