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
{
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
pthread_mutex_t
lock
;
64
as_queue
queue
;
65
as_queue
pipe_cb_queue
;
66
pthread_t
thread
;
67
uint32_t
index
;
68
bool
pipe_cb_calling
;
69
}
as_event_loop
;
70
71
/******************************************************************************
72
* GLOBAL VARIABLES
73
*****************************************************************************/
74
75
extern
as_event_loop
*
as_event_loops
;
76
extern
uint32_t
as_event_loop_size
;
77
extern
uint32_t
as_event_loop_current
;
78
79
/******************************************************************************
80
* PUBLIC FUNCTIONS
81
*****************************************************************************/
82
83
/**
84
* Create new event loops. This method should only be called when asynchronous client commands
85
* will be used and the calling program itself is not asynchronous. If this method is used,
86
* it must be called before aerospike_connect().
87
*
88
* @param capacity Number of event loops to create.
89
*
90
* @ingroup async_events
91
*/
92
as_event_loop
*
93
as_event_create_loops
(uint32_t capacity);
94
95
/**
96
* Set the number of externally created event loops. This method should be called when the
97
* calling program wants to share event loops with the client. This reduces resource usage and
98
* can increase performance.
99
*
100
* This method is used in conjunction with as_event_set_external_loop() to fully define the
101
* the external loop to the client and obtain a reference the client's event loop abstraction.
102
*
103
* ~~~~~~~~~~{.c}
104
* struct {
105
* pthread_t thread;
106
* struct ev_loop* loop;
107
* as_event_loop* as_loop;
108
* } my_loop;
109
*
110
* static void* my_loop_worker_thread(void* udata) {
111
* struct my_loop* myloop = udata;
112
* myloop->loop = ev_loop_new(EVFLAG_AUTO);
113
* myloop->as_loop = as_event_set_external_loop(myloop->loop);
114
* ev_loop(myloop->loop, 0);
115
* ev_loop_destroy(myloop->loop);
116
* return NULL;
117
* }
118
*
119
* int capacity = 8;
120
* struct my_loop* loops = malloc(sizeof(struct my_loop) * capacity);
121
* as_event_set_external_loop_capacity(capacity);
122
*
123
* for (int i = 0; i < capacity; i++) {
124
* struct my_loop* myloop = &loops[i];
125
* return pthread_create(&myloop->thread, NULL, my_loop_worker_thread, myloop) == 0;
126
* }
127
* ~~~~~~~~~~
128
*
129
* @param capacity Number of externally created event loops.
130
*
131
* @ingroup async_events
132
*/
133
bool
134
as_event_set_external_loop_capacity
(uint32_t capacity);
135
136
/**
137
* Register an external event loop with the client. This method should be called when the
138
* calling program wants to share event loops with the client. This reduces resource usage and
139
* can increase performance.
140
*
141
* This method must be called in the same thread as the event loop that is being registered.
142
*
143
* This method is used in conjunction with as_event_set_external_loop_capacity() to fully define
144
* the external loop to the client and obtain a reference the client's event loop abstraction.
145
*
146
* ~~~~~~~~~~{.c}
147
* struct {
148
* pthread_t thread;
149
* struct ev_loop* loop;
150
* as_event_loop* as_loop;
151
* } my_loop;
152
*
153
* static void* my_loop_worker_thread(void* udata) {
154
* struct my_loop* myloop = udata;
155
* myloop->loop = ev_loop_new(EVFLAG_AUTO);
156
* myloop->as_loop = as_event_set_external_loop(myloop->loop);
157
* ev_loop(myloop->loop, 0);
158
* ev_loop_destroy(myloop->loop);
159
* return NULL;
160
* }
161
*
162
* int capacity = 8;
163
* struct my_loop* loops = malloc(sizeof(struct my_loop) * capacity);
164
* as_event_set_external_loop_capacity(capacity);
165
*
166
* for (int i = 0; i < capacity; i++) {
167
* struct my_loop* myloop = &loops[i];
168
* return pthread_create(&myloop->thread, NULL, my_loop_worker_thread, myloop) == 0;
169
* }
170
* ~~~~~~~~~~
171
*
172
* @param loop External event loop.
173
* @return Client's generic event loop abstraction that is used in client async commands.
174
* Returns NULL if external loop capacity would be exceeded.
175
*
176
* @ingroup async_events
177
*/
178
as_event_loop
*
179
as_event_set_external_loop
(
void
* loop);
180
181
/**
182
* Find client's event loop abstraction given the external event loop.
183
*
184
* @param loop External event loop.
185
* @return Client's generic event loop abstraction that is used in client async commands.
186
* Returns NULL if loop not found.
187
*
188
* @ingroup async_events
189
*/
190
as_event_loop
*
191
as_event_loop_find
(
void
* loop);
192
193
/**
194
* Retrieve event loop by array index.
195
*
196
* @param index Event loop array index.
197
* @return Client's generic event loop abstraction that is used in client async commands.
198
*
199
* @ingroup async_events
200
*/
201
static
inline
as_event_loop
*
202
as_event_loop_get_by_index
(uint32_t index)
203
{
204
return
index < as_event_loop_size ? &as_event_loops[index] : NULL;
205
}
206
207
/**
208
* Retrieve a random event loop using round robin distribution.
209
*
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
()
216
{
217
// Increment is not atomic because it doesn't need to be exactly accurate.
218
uint32_t current = as_event_loop_current++;
219
return
&as_event_loops[current % as_event_loop_size];
220
}
221
222
/**
223
* Close internally created event loops and release memory for event loop abstraction.
224
* This method should be called once on program shutdown if as_event_create_loops() or
225
* as_event_set_external_loop_capacity() was called.
226
*
227
* @ingroup async_events
228
*/
229
void
230
as_event_close_loops
();
231
232
#ifdef __cplusplus
233
}
// end extern "C"
234
#endif