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-2016 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
* such as libev and libuv. Only one library can be supported per build.
30
*/
31
#if defined(AS_USE_LIBEV)
32
#include <ev.h>
33
#elif defined(AS_USE_LIBUV)
34
#include <uv.h>
35
#else
36
#endif
37
38
#ifdef __cplusplus
39
extern
"C"
{
40
#endif
41
42
/******************************************************************************
43
* TYPES
44
*****************************************************************************/
45
46
/**
47
* Generic asynchronous event loop abstraction. There is one event loop per thread.
48
* Event loops can be created by the client, or be referenced to externally created event loops.
49
*
50
* @ingroup async_events
51
*/
52
typedef
struct
as_event_loop
{
53
#if defined(AS_USE_LIBEV)
54
struct
ev_loop*
loop
;
55
struct
ev_async wakeup;
56
#elif defined(AS_USE_LIBUV)
57
uv_loop_t*
loop
;
58
uv_async_t* wakeup;
59
#else
60
void
*
loop
;
61
#endif
62
63
struct
as_event_loop
*
next
;
64
pthread_mutex_t
lock
;
65
as_queue
queue
;
66
as_queue
pipe_cb_queue
;
67
pthread_t
thread
;
68
uint32_t
index
;
69
bool
pipe_cb_calling
;
70
}
as_event_loop
;
71
72
/******************************************************************************
73
* GLOBAL VARIABLES
74
*****************************************************************************/
75
76
extern
as_event_loop
*
as_event_loops
;
77
extern
as_event_loop
*
as_event_loop_current
;
78
extern
uint32_t
as_event_loop_size
;
79
80
/******************************************************************************
81
* PUBLIC FUNCTIONS
82
*****************************************************************************/
83
84
/**
85
* Create new event loops. This method should only be called when asynchronous client commands
86
* will be used and the calling program itself is not asynchronous. If this method is used,
87
* it must be called before aerospike_connect().
88
*
89
* @param capacity Number of event loops to create.
90
* @return Event loop array.
91
*
92
* @ingroup async_events
93
*/
94
as_event_loop
*
95
as_event_create_loops
(uint32_t capacity);
96
97
/**
98
* Set the number of externally created event loops. This method should be called when the
99
* calling program wants to share event loops with the client. This reduces resource usage and
100
* can increase performance.
101
*
102
* This method is used in conjunction with as_event_set_external_loop() to fully define the
103
* the external loop to the client and obtain a reference the client's event loop abstraction.
104
*
105
* ~~~~~~~~~~{.c}
106
* struct {
107
* pthread_t thread;
108
* struct ev_loop* loop;
109
* as_event_loop* as_loop;
110
* } my_loop;
111
*
112
* static void* my_loop_worker_thread(void* udata) {
113
* struct my_loop* myloop = udata;
114
* myloop->loop = ev_loop_new(EVFLAG_AUTO);
115
* myloop->as_loop = as_event_set_external_loop(myloop->loop);
116
* ev_loop(myloop->loop, 0);
117
* ev_loop_destroy(myloop->loop);
118
* return NULL;
119
* }
120
*
121
* int capacity = 8;
122
* struct my_loop* loops = malloc(sizeof(struct my_loop) * capacity);
123
* as_event_set_external_loop_capacity(capacity);
124
*
125
* for (int i = 0; i < capacity; i++) {
126
* struct my_loop* myloop = &loops[i];
127
* return pthread_create(&myloop->thread, NULL, my_loop_worker_thread, myloop) == 0;
128
* }
129
* ~~~~~~~~~~
130
*
131
* @param capacity Number of externally created event loops.
132
* @return True if all external loops were initialized.
133
*
134
* @ingroup async_events
135
*/
136
bool
137
as_event_set_external_loop_capacity
(uint32_t capacity);
138
139
/**
140
* Register an external event loop with the client. This method should be called when the
141
* calling program wants to share event loops with the client. This reduces resource usage and
142
* can increase performance.
143
*
144
* This method must be called in the same thread as the event loop that is being registered.
145
*
146
* This method is used in conjunction with as_event_set_external_loop_capacity() to fully define
147
* the external loop to the client and obtain a reference the client's event loop abstraction.
148
*
149
* ~~~~~~~~~~{.c}
150
* struct {
151
* pthread_t thread;
152
* struct ev_loop* loop;
153
* as_event_loop* as_loop;
154
* } my_loop;
155
*
156
* static void* my_loop_worker_thread(void* udata) {
157
* struct my_loop* myloop = udata;
158
* myloop->loop = ev_loop_new(EVFLAG_AUTO);
159
* myloop->as_loop = as_event_set_external_loop(myloop->loop);
160
* ev_loop(myloop->loop, 0);
161
* ev_loop_destroy(myloop->loop);
162
* return NULL;
163
* }
164
*
165
* int capacity = 8;
166
* struct my_loop* loops = malloc(sizeof(struct my_loop) * capacity);
167
* as_event_set_external_loop_capacity(capacity);
168
*
169
* for (int i = 0; i < capacity; i++) {
170
* struct my_loop* myloop = &loops[i];
171
* return pthread_create(&myloop->thread, NULL, my_loop_worker_thread, myloop) == 0;
172
* }
173
* ~~~~~~~~~~
174
*
175
* @param loop External event loop.
176
* @return Client's generic event loop abstraction that is used in client async commands.
177
* Returns NULL if external loop capacity would be exceeded.
178
*
179
* @ingroup async_events
180
*/
181
as_event_loop
*
182
as_event_set_external_loop
(
void
*
loop
);
183
184
/**
185
* Find client's event loop abstraction given the external event loop.
186
*
187
* @param loop External event loop.
188
* @return Client's generic event loop abstraction that is used in client async commands.
189
* Returns NULL if loop not found.
190
*
191
* @ingroup async_events
192
*/
193
as_event_loop
*
194
as_event_loop_find
(
void
*
loop
);
195
196
/**
197
* Retrieve event loop by array index.
198
*
199
* @param index Event loop array index.
200
* @return Client's generic event loop abstraction that is used in client async commands.
201
*
202
* @ingroup async_events
203
*/
204
static
inline
as_event_loop
*
205
as_event_loop_get_by_index
(uint32_t
index
)
206
{
207
return
index < as_event_loop_size ? &as_event_loops[
index
] : NULL;
208
}
209
210
/**
211
* Retrieve a random event loop using round robin distribution.
212
*
213
* @return Client's generic event loop abstraction that is used in client async commands.
214
*
215
* @ingroup async_events
216
*/
217
static
inline
as_event_loop
*
218
as_event_loop_get
()
219
{
220
// The last event loop points to the first event loop to create a circular linked list.
221
// Not atomic because doesn't need to be exactly accurate.
222
as_event_loop
* event_loop = as_event_loop_current;
223
as_event_loop_current = event_loop->
next
;
224
return
event_loop;
225
}
226
227
/**
228
* Close internal event loops and release watchers for internal and external event loops.
229
* The global event loop array will also be destroyed for internal event loops.
230
*
231
* This method should be called once on program shutdown if as_event_create_loops() or
232
* as_event_set_external_loop_capacity() was called.
233
*
234
* The shutdown sequence is slightly different for internal and external event loops.
235
*
236
* Internal:
237
* ~~~~~~~~~~{.c}
238
* as_event_close_loops();
239
* ~~~~~~~~~~
240
*
241
* External:
242
* ~~~~~~~~~~{.c}
243
* as_event_close_loops();
244
* Join on external loop threads.
245
* as_event_destroy_loops();
246
* ~~~~~~~~~~
247
*
248
* @return True if event loop close was successful. If false, as_event_destroy_loops() should
249
* not be called.
250
*
251
* @ingroup async_events
252
*/
253
bool
254
as_event_close_loops
();
255
256
/**
257
* Destroy global event loop array. This function only needs to be called for external
258
* event loops.
259
*
260
* @ingroup async_events
261
*/
262
void
263
as_event_destroy_loops
();
264
265
#ifdef __cplusplus
266
}
// end extern "C"
267
#endif