-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathmy_context.h
104 lines (78 loc) · 3.09 KB
/
my_context.h
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
/*
Copyright 2011 Kristian Nielsen
Experiments with non-blocking libmysql.
This is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this. If not, see <http://www.gnu.org/licenses/>.
*/
/*
Simple API for spawning a co-routine, to be used for async libmysqlclient.
Idea is that by implementing this interface using whatever facilities are
available for given platform, we can use the same code for the generic
libmysqlclient-async code.
(This particular implementation uses Posix ucontext swapcontext().)
*/
#ifdef __WIN__
#define MY_CONTEXT_USE_WIN32_FIBERS 1
#elif defined(__GNUC__) && __GNUC__ >= 3 && defined(__x86_64__)
#define MY_CONTEXT_USE_X86_64_GCC_ASM
#else
#define MY_CONTEXT_USE_UCONTEXT
#endif
#ifdef MY_CONTEXT_USE_WIN32_FIBERS
#error Windows Fiber-based my_context not yet implemented
#endif
#ifdef MY_CONTEXT_USE_UCONTEXT
#include <ucontext.h>
struct my_context {
void (*user_func)(void *);
void *user_data;
ucontext_t base_context;
ucontext_t spawned_context;
int active;
};
#endif
#ifdef MY_CONTEXT_USE_X86_64_GCC_ASM
#include <stdint.h>
struct my_context {
uint64_t save[17];
};
#endif
/*
Spawn an asynchroneous context. The context will run the supplied user
function, passing the supplied user data pointer.
The user function may call my_context_yield(), which will cause this
function to return 1. Then later my_context_continue() may be called, which
will resume the asynchroneous context by returning from the previous
my_context_yield() call.
When the user function returns, this function returns 0.
In case of error, -1 is returned.
*/
extern int my_context_spawn(struct my_context *c, void (*f)(void *), void *d,
void *stack, size_t stack_size);
/*
Suspend an asynchroneous context started with my_context_spawn.
When my_context_yield() is called, execution immediately returns from the
last my_context_spawn() or my_context_continue() call. Then when later
my_context_continue() is called, execution resumes by returning from this
my_context_yield() call.
Returns 0 if ok, -1 in case of error.
*/
extern int my_context_yield(struct my_context *c);
/*
Resume an asynchroneous context. The context was spawned by
my_context_spawn(), and later suspended inside my_context_yield().
The asynchroneous context may be repeatedly suspended with
my_context_yield() and resumed with my_context_continue().
Each time it is suspended, this function returns 1. When the originally
spawned user function returns, this function returns 0.
In case of error, -1 is returned.
*/
extern int my_context_continue(struct my_context *c);