Main Page
Related Pages
Modules
Data Structures
Files
File List
Globals
All
Data Structures
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Friends
Macros
Groups
Pages
aerospike
as_event.h
Go to the documentation of this file.
1
/*
2
* Copyright 2008-2017 Aerospike, Inc.
3
*
4
* Portions may be licensed to Aerospike, Inc. under one or more contributor
5
* license agreements.
6
*
7
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
8
* use this file except in compliance with the License. You may obtain a copy of
9
* the License at http://www.apache.org/licenses/LICENSE-2.0
10
*
11
* Unless required by applicable law or agreed to in writing, software
12
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14
* License for the specific language governing permissions and limitations under
15
* the License.
16
*/
17
#pragma once
18
19
#include <
aerospike/as_queue.h
>
20
#include <pthread.h>
21
#include <stdint.h>
22
#include <stdbool.h>
23
#include <unistd.h>
24
25
/**
26
* @defgroup async_events Asynchronous Event Abstraction
27
*
28
* Generic asynchronous events abstraction. Designed to support multiple event libraries.
29
* Only one library is supported per build.
30
*/
31
#define AS_EVENT_LIB_DEFINED (defined(AS_USE_LIBEV) || defined(AS_USE_LIBUV) || defined(AS_USE_LIBEVENT))
32
33
#if defined(AS_USE_LIBEV)
34
#include <ev.h>
35
#elif defined(AS_USE_LIBUV)
36
#include <uv.h>
37
#elif defined(AS_USE_LIBEVENT)
38
#include <event2/event_struct.h>
39
#else
40
#endif
41
42
#ifdef __cplusplus
43
extern
"C"
{
44
#endif
45
46
/******************************************************************************
47
* TYPES
48
*****************************************************************************/
49
50
/**
51
* Generic asynchronous event loop abstraction. There is one event loop per thread.
52
* Event loops can be created by the client, or be referenced to externally created event loops.
53
*
54
* @ingroup async_events
55
*/
56
typedef
struct
as_event_loop
{
57
#if defined(AS_USE_LIBEV)
58
struct
ev_loop*
loop
;
59
struct
ev_async wakeup;
60
#elif defined(AS_USE_LIBUV)
61
uv_loop_t*
loop
;
62
uv_async_t* wakeup;
63
#elif defined(AS_USE_LIBEVENT)
64
struct
event_base*
loop
;
65
struct
event wakeup;
66
#else
67
void
*
loop
;
68
#endif
69
70
struct
as_event_loop
*
next
;
71
pthread_mutex_t
lock
;
72
as_queue
queue
;
73
as_queue
pipe_cb_queue
;
74
pthread_t
thread
;
75
uint32_t
index
;
76
bool
pipe_cb_calling
;
77
}
as_event_loop
;
78
79
/******************************************************************************
80
* GLOBAL VARIABLES
81
*****************************************************************************/
82
83
extern
as_event_loop
*
as_event_loops
;
84
extern
as_event_loop
*
as_event_loop_current
;
85
extern
uint32_t
as_event_loop_size
;
86
87
/******************************************************************************
88
* PUBLIC FUNCTIONS
89
*****************************************************************************/
90
91
/**
92
* Create new event loops. This method should only be called when asynchronous client commands
93
* will be used and the calling program itself is not asynchronous. If this method is used,
94
* it must be called before aerospike_connect().
95
*
96
* @param capacity Number of event loops to create.
97
* @return Event loop array.
98
*
99
* @ingroup async_events
100
*/
101
as_event_loop
*
102
as_event_create_loops
(uint32_t capacity);
103
104
/**
105
* Set the number of externally created event loops. This method should be called when the
106
* calling program wants to share event loops with the client. This reduces resource usage and
107
* can increase performance.
108
*
109
* This method is used in conjunction with as_event_set_external_loop() to fully define the
110
* the external loop to the client and obtain a reference the client's event loop abstraction.
111
*
112
* ~~~~~~~~~~{.c}
113
* struct {
114
* pthread_t thread;
115
* struct ev_loop* loop;
116
* as_event_loop* as_loop;
117
* } my_loop;
118
*
119
* static void* my_loop_worker_thread(void* udata) {
120
* struct my_loop* myloop = udata;
121
* myloop->loop = ev_loop_new(EVFLAG_AUTO);
122
* myloop->as_loop = as_event_set_external_loop(myloop->loop);
123
* ev_loop(myloop->loop, 0);
124
* ev_loop_destroy(myloop->loop);
125
* return NULL;
126
* }
127
*
128
* int capacity = 8;
129
* struct my_loop* loops = malloc(sizeof(struct my_loop) * capacity);
130
* as_event_set_external_loop_capacity(capacity);
131
*
132
* for (int i = 0; i < capacity; i++) {
133
* struct my_loop* myloop = &loops[i];
134
* return pthread_create(&myloop->thread, NULL, my_loop_worker_thread, myloop) == 0;
135
* }
136
* ~~~~~~~~~~
137
*
138
* @param capacity Number of externally created event loops.
139
* @return True if all external loops were initialized.
140
*
141
* @ingroup async_events
142
*/
143
bool
144
as_event_set_external_loop_capacity
(uint32_t capacity);
145
146
/**
147
* Register an external event loop with the client. This method should be called when the
148
* calling program wants to share event loops with the client. This reduces resource usage and
149
* can increase performance.
150
*
151
* This method must be called in the same thread as the event loop that is being registered.
152
*
153
* This method is used in conjunction with as_event_set_external_loop_capacity() to fully define
154
* the external loop to the client and obtain a reference the client's event loop abstraction.
155
*
156
* ~~~~~~~~~~{.c}
157
* struct {
158
* pthread_t thread;
159
* struct ev_loop* loop;
160
* as_event_loop* as_loop;
161
* } my_loop;
162
*
163
* static void* my_loop_worker_thread(void* udata) {
164
* struct my_loop* myloop = udata;
165
* myloop->loop = ev_loop_new(EVFLAG_AUTO);
166
* myloop->as_loop = as_event_set_external_loop(myloop->loop);
167
* ev_loop(myloop->loop, 0);
168
* ev_loop_destroy(myloop->loop);
169
* return NULL;
170
* }
171
*
172
* int capacity = 8;
173
* struct my_loop* loops = malloc(sizeof(struct my_loop) * capacity);
174
* as_event_set_external_loop_capacity(capacity);
175
*
176
* for (int i = 0; i < capacity; i++) {
177
* struct my_loop* myloop = &loops[i];
178
* return pthread_create(&myloop->thread, NULL, my_loop_worker_thread, myloop) == 0;
179
* }
180
* ~~~~~~~~~~
181
*
182
* @param loop External event loop.
183
* @return Client's generic event loop abstraction that is used in client async commands.
184
* Returns NULL if external loop capacity would be exceeded.
185
*
186
* @ingroup async_events
187
*/
188
as_event_loop
*
189
as_event_set_external_loop
(
void
*
loop
);
190
191
/**
192
* Find client's event loop abstraction given the external event loop.
193
*
194
* @param loop External event loop.
195
* @return Client's generic event loop abstraction that is used in client async commands.
196
* Returns NULL if loop not found.
197
*
198
* @ingroup async_events
199
*/
200
as_event_loop
*
201
as_event_loop_find
(
void
*
loop
);
202
203
/**
204
* Retrieve event loop by array index.
205
*
206
* @param index Event loop array index.
207
* @return Client's generic event loop abstraction that is used in client async commands.
208
*
209
* @ingroup async_events
210
*/
211
static
inline
as_event_loop
*
212
as_event_loop_get_by_index
(uint32_t
index
)
213
{
214
return
index < as_event_loop_size ? &as_event_loops[
index
] : NULL;
215
}
216
217
/**
218
* Retrieve a random event loop using round robin distribution.
219
*
220
* @return Client's generic event loop abstraction that is used in client async commands.
221
*
222
* @ingroup async_events
223
*/
224
static
inline
as_event_loop
*
225
as_event_loop_get
()
226
{
227
// The last event loop points to the first event loop to create a circular linked list.
228
// Not atomic because doesn't need to be exactly accurate.
229
as_event_loop
* event_loop = as_event_loop_current;
230
as_event_loop_current = event_loop->
next
;
231
return
event_loop;
232
}
233
234
/**
235
* Close internal event loops and release watchers for internal and external event loops.
236
* The global event loop array will also be destroyed for internal event loops.
237
*
238
* This method should be called once on program shutdown if as_event_create_loops() or
239
* as_event_set_external_loop_capacity() was called.
240
*
241
* The shutdown sequence is slightly different for internal and external event loops.
242
*
243
* Internal:
244
* ~~~~~~~~~~{.c}
245
* as_event_close_loops();
246
* ~~~~~~~~~~
247
*
248
* External:
249
* ~~~~~~~~~~{.c}
250
* as_event_close_loops();
251
* Join on external loop threads.
252
* as_event_destroy_loops();
253
* ~~~~~~~~~~
254
*
255
* @return True if event loop close was successful. If false, as_event_destroy_loops() should
256
* not be called.
257
*
258
* @ingroup async_events
259
*/
260
bool
261
as_event_close_loops
();
262
263
/**
264
* Destroy global event loop array. This function only needs to be called for external
265
* event loops.
266
*
267
* @ingroup async_events
268
*/
269
void
270
as_event_destroy_loops
();
271
272
#ifdef __cplusplus
273
}
// end extern "C"
274
#endif