summaryrefslogtreecommitdiffstats
path: root/modules/http2/h2_worker.h
blob: 035448e5dbbcf24c35d4c6ce505ac8233d507d35 (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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
/* Copyright 2015 greenbytes GmbH (https://www.greenbytes.de)
 *
 * 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.
 */

#ifndef __mod_h2__h2_worker__
#define __mod_h2__h2_worker__

struct apr_thread_cond_t;
struct h2_mplx;
struct h2_request;
struct h2_task;

/* h2_worker is a basically a apr_thread_t that reads fromt he h2_workers
 * task queue and runs h2_tasks it is given.
 */
typedef struct h2_worker h2_worker;

/* Invoked when the worker wants a new task to process. Will block
 * until a h2_mplx becomes available or the worker itself
 * gets aborted (idle timeout, for example). */
typedef apr_status_t h2_worker_mplx_next_fn(h2_worker *worker,
                                            struct h2_mplx **pm,
                                            struct h2_task **ptask,
                                            void *ctx);

/* Invoked just before the worker thread exits. */
typedef void h2_worker_done_fn(h2_worker *worker, void *ctx);


struct h2_worker {
    /** Links to the rest of the workers */
    APR_RING_ENTRY(h2_worker) link;
    
    int id;
    apr_thread_t *thread;
    apr_pool_t *pool;
    apr_pool_t *task_pool;
    struct apr_thread_cond_t *io;
    apr_socket_t *socket;
    
    h2_worker_mplx_next_fn *get_next;
    h2_worker_done_fn *worker_done;
    void *ctx;
    
    int aborted;
    struct h2_task *task;
};

/**
 * The magic pointer value that indicates the head of a h2_worker list
 * @param  b The worker list
 * @return The magic pointer value
 */
#define H2_WORKER_LIST_SENTINEL(b)	APR_RING_SENTINEL((b), h2_worker, link)

/**
 * Determine if the worker list is empty
 * @param b The list to check
 * @return true or false
 */
#define H2_WORKER_LIST_EMPTY(b)	APR_RING_EMPTY((b), h2_worker, link)

/**
 * Return the first worker in a list
 * @param b The list to query
 * @return The first worker in the list
 */
#define H2_WORKER_LIST_FIRST(b)	APR_RING_FIRST(b)

/**
 * Return the last worker in a list
 * @param b The list to query
 * @return The last worker int he list
 */
#define H2_WORKER_LIST_LAST(b)	APR_RING_LAST(b)

/**
 * Insert a single worker at the front of a list
 * @param b The list to add to
 * @param e The worker to insert
 */
#define H2_WORKER_LIST_INSERT_HEAD(b, e) do {				\
	h2_worker *ap__b = (e);                                        \
	APR_RING_INSERT_HEAD((b), ap__b, h2_worker, link);	\
    } while (0)

/**
 * Insert a single worker at the end of a list
 * @param b The list to add to
 * @param e The worker to insert
 */
#define H2_WORKER_LIST_INSERT_TAIL(b, e) do {				\
	h2_worker *ap__b = (e);					\
	APR_RING_INSERT_TAIL((b), ap__b, h2_worker, link);	\
    } while (0)

/**
 * Get the next worker in the list
 * @param e The current worker
 * @return The next worker
 */
#define H2_WORKER_NEXT(e)	APR_RING_NEXT((e), link)
/**
 * Get the previous worker in the list
 * @param e The current worker
 * @return The previous worker
 */
#define H2_WORKER_PREV(e)	APR_RING_PREV((e), link)

/**
 * Remove a worker from its list
 * @param e The worker to remove
 */
#define H2_WORKER_REMOVE(e)	APR_RING_REMOVE((e), link)


/* Create a new worker with given id, pool and attributes, callbacks
 * callback parameter.
 */
h2_worker *h2_worker_create(int id,
                            apr_pool_t *pool,
                            apr_threadattr_t *attr,
                            h2_worker_mplx_next_fn *get_next,
                            h2_worker_done_fn *worker_done,
                            void *ctx);

apr_status_t h2_worker_destroy(h2_worker *worker);

void h2_worker_abort(h2_worker *worker);

int h2_worker_get_id(h2_worker *worker);

int h2_worker_is_aborted(h2_worker *worker);

struct h2_task *h2_worker_create_task(h2_worker *worker, struct h2_mplx *m, 
                                      const struct h2_request *req, int eos);
apr_status_t h2_worker_setup_task(h2_worker *worker, struct h2_task *task);
void h2_worker_release_task(h2_worker *worker, struct h2_task *task);

apr_socket_t *h2_worker_get_socket(h2_worker *worker);

#endif /* defined(__mod_h2__h2_worker__) */