Main Page
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 Event Framework 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
// Count of consecutive errors occurring before event loop registration.
77
// Used to prevent deep recursion.
78
uint32_t
errors
;
79
bool
pipe_cb_calling
;
80
}
as_event_loop
;
81
82
/******************************************************************************
83
* GLOBAL VARIABLES
84
*****************************************************************************/
85
86
extern
as_event_loop
*
as_event_loops
;
87
extern
as_event_loop
*
as_event_loop_current
;
88
extern
uint32_t
as_event_loop_size
;
89
90
/******************************************************************************
91
* PUBLIC FUNCTIONS
92
*****************************************************************************/
93
94
/**
95
* Create new event loops. This method should only be called when asynchronous client commands
96
* will be used and the calling program itself is not asynchronous. If this method is used,
97
* it must be called before aerospike_connect().
98
*
99
* @param capacity Number of event loops to create.
100
* @return Event loop array.
101
*
102
* @ingroup async_events
103
*/
104
as_event_loop
*
105
as_event_create_loops
(uint32_t capacity);
106
107
/**
108
* Set the number of externally created event loops. This method should be called when the
109
* calling program wants to share event loops with the client. This reduces resource usage and
110
* can increase performance.
111
*
112
* This method is used in conjunction with as_event_set_external_loop() to fully define the
113
* the external loop to the client and obtain a reference the client's event loop abstraction.
114
*
115
* ~~~~~~~~~~{.c}
116
* struct {
117
* pthread_t thread;
118
* struct ev_loop* loop;
119
* as_event_loop* as_loop;
120
* } my_loop;
121
*
122
* static void* my_loop_worker_thread(void* udata) {
123
* struct my_loop* myloop = udata;
124
* myloop->loop = ev_loop_new(EVFLAG_AUTO);
125
* myloop->as_loop = as_event_set_external_loop(myloop->loop);
126
* ev_loop(myloop->loop, 0);
127
* ev_loop_destroy(myloop->loop);
128
* return NULL;
129
* }
130
*
131
* int capacity = 8;
132
* struct my_loop* loops = malloc(sizeof(struct my_loop) * capacity);
133
* as_event_set_external_loop_capacity(capacity);
134
*
135
* for (int i = 0; i < capacity; i++) {
136
* struct my_loop* myloop = &loops[i];
137
* return pthread_create(&myloop->thread, NULL, my_loop_worker_thread, myloop) == 0;
138
* }
139
* ~~~~~~~~~~
140
*
141
* @param capacity Number of externally created event loops.
142
* @return True if all external loops were initialized.
143
*
144
* @ingroup async_events
145
*/
146
bool
147
as_event_set_external_loop_capacity
(uint32_t capacity);
148
149
/**
150
* Register an external event loop with the client. This method should be called when the
151
* calling program wants to share event loops with the client. This reduces resource usage and
152
* can increase performance.
153
*
154
* This method must be called in the same thread as the event loop that is being registered.
155
*
156
* This method is used in conjunction with as_event_set_external_loop_capacity() to fully define
157
* the external loop to the client and obtain a reference the client's event loop abstraction.
158
*
159
* ~~~~~~~~~~{.c}
160
* struct {
161
* pthread_t thread;
162
* struct ev_loop* loop;
163
* as_event_loop* as_loop;
164
* } my_loop;
165
*
166
* static void* my_loop_worker_thread(void* udata) {
167
* struct my_loop* myloop = udata;
168
* myloop->loop = ev_loop_new(EVFLAG_AUTO);
169
* myloop->as_loop = as_event_set_external_loop(myloop->loop);
170
* ev_loop(myloop->loop, 0);
171
* ev_loop_destroy(myloop->loop);
172
* return NULL;
173
* }
174
*
175
* int capacity = 8;
176
* struct my_loop* loops = malloc(sizeof(struct my_loop) * capacity);
177
* as_event_set_external_loop_capacity(capacity);
178
*
179
* for (int i = 0; i < capacity; i++) {
180
* struct my_loop* myloop = &loops[i];
181
* return pthread_create(&myloop->thread, NULL, my_loop_worker_thread, myloop) == 0;
182
* }
183
* ~~~~~~~~~~
184
*
185
* @param loop External event loop.
186
* @return Client's generic event loop abstraction that is used in client async commands.
187
* Returns NULL if external loop capacity would be exceeded.
188
*
189
* @ingroup async_events
190
*/
191
as_event_loop
*
192
as_event_set_external_loop
(
void
*
loop
);
193
194
/**
195
* Find client's event loop abstraction given the external event loop.
196
*
197
* @param loop External event loop.
198
* @return Client's generic event loop abstraction that is used in client async commands.
199
* Returns NULL if loop not found.
200
*
201
* @ingroup async_events
202
*/
203
as_event_loop
*
204
as_event_loop_find
(
void
*
loop
);
205
206
/**
207
* Retrieve event loop by array index.
208
*
209
* @param index Event loop array index.
210
* @return Client's generic event loop abstraction that is used in client async commands.
211
*
212
* @ingroup async_events
213
*/
214
static
inline
as_event_loop
*
215
as_event_loop_get_by_index
(uint32_t
index
)
216
{
217
return
index < as_event_loop_size ? &as_event_loops[
index
] : NULL;
218
}
219
220
/**
221
* Retrieve a random event loop using round robin distribution.
222
*
223
* @return Client's generic event loop abstraction that is used in client async commands.
224
*
225
* @ingroup async_events
226
*/
227
static
inline
as_event_loop
*
228
as_event_loop_get
()
229
{
230
// The last event loop points to the first event loop to create a circular linked list.
231
// Not atomic because doesn't need to be exactly accurate.
232
as_event_loop
* event_loop = as_event_loop_current;
233
as_event_loop_current = event_loop->
next
;
234
return
event_loop;
235
}
236
237
/**
238
* Close internal event loops and release watchers for internal and external event loops.
239
* The global event loop array will also be destroyed for internal event loops.
240
*
241
* This method should be called once on program shutdown if as_event_create_loops() or
242
* as_event_set_external_loop_capacity() was called.
243
*
244
* The shutdown sequence is slightly different for internal and external event loops.
245
*
246
* Internal:
247
* ~~~~~~~~~~{.c}
248
* as_event_close_loops();
249
* ~~~~~~~~~~
250
*
251
* External:
252
* ~~~~~~~~~~{.c}
253
* as_event_close_loops();
254
* Join on external loop threads.
255
* as_event_destroy_loops();
256
* ~~~~~~~~~~
257
*
258
* @return True if event loop close was successful. If false, as_event_destroy_loops() should
259
* not be called.
260
*
261
* @ingroup async_events
262
*/
263
bool
264
as_event_close_loops
();
265
266
/**
267
* Destroy global event loop array. This function only needs to be called for external
268
* event loops.
269
*
270
* @ingroup async_events
271
*/
272
void
273
as_event_destroy_loops
();
274
275
#ifdef __cplusplus
276
}
// end extern "C"
277
#endif