aboutsummaryrefslogtreecommitdiffstats
path: root/src/lua/lua_thread_pool.h
blob: be954271d8a7a150541bba7994e14bf5945fd488 (plain)
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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
#ifndef LUA_THREAD_POOL_H_
#define LUA_THREAD_POOL_H_

#include <lua.h>

#ifdef  __cplusplus
extern "C" {
#endif

struct thread_entry;
struct lua_thread_pool;

typedef void (*lua_thread_finish_t) (struct thread_entry *thread, int ret);

typedef void (*lua_thread_error_t) (struct thread_entry *thread, int ret, const char *msg);

struct thread_entry {
	lua_State *lua_state;
	gint thread_index;
	gpointer cd;

	/* function to handle result of called method, can be NULL */
	lua_thread_finish_t finish_callback;

	/* function to log result, i.e. if you want to modify error logging message or somehow process this state, can be NUL */
	lua_thread_error_t error_callback;
	struct rspamd_task *task;
	struct rspamd_config *cfg;
};

struct lua_callback_state {
	lua_State *L;
	struct thread_entry *my_thread;
	struct thread_entry *previous_thread;
	struct lua_thread_pool *thread_pool;
};

/**
 * Allocates new thread pool on state L. Pre-creates number of lua-threads to use later on
 *
 * @param L
 * @return
 */
struct lua_thread_pool *
lua_thread_pool_new (lua_State *L);

/**
 * Destroys the pool
 * @param pool
 */
void
lua_thread_pool_free (struct lua_thread_pool *pool);

/**
 * Extracts a thread from the list of available ones.
 * It immediately becames running one and should be used to run a Lua script/function straight away.
 * as soon as the code is finished, it should be either returned into list of available threads by
 * calling lua_thread_pool_return() or terminated by calling lua_thread_pool_terminate_entry()
 * if the code finished with error.
 *
 * If the code performed YIELD, the thread is still running and it's live should be controlled by the callee
 *
 * @param task
 * @return
 */
struct thread_entry *
lua_thread_pool_get_for_task (struct rspamd_task *task);

/**
 * The same, but used when task is not available
 *
 * @param cfg
 * @return
 */
struct thread_entry *
lua_thread_pool_get_for_config (struct rspamd_config *cfg);

/**
 * Return thread into the list of available ones. It can't be done with yielded or dead threads.
 *
 * @param pool
 * @param thread_entry
 */
void
lua_thread_pool_return_full (struct lua_thread_pool *pool,
							 struct thread_entry *thread_entry,
							 const gchar *loc);

#define lua_thread_pool_return(pool, thread_entry) \
    lua_thread_pool_return_full (pool, thread_entry, G_STRLOC)

/**
 * Currently running thread. Typically needed in yielding point - to fill-up continuation.
 *
 * @param pool
 * @return
 */
struct thread_entry *
lua_thread_pool_get_running_entry_full (struct lua_thread_pool *pool,
										const gchar *loc);

#define lua_thread_pool_get_running_entry(pool) \
    lua_thread_pool_get_running_entry_full (pool, G_STRLOC)

/**
 * Updates currently running thread
 *
 * @param pool
 * @param thread_entry
 */
void
lua_thread_pool_set_running_entry_full (struct lua_thread_pool *pool,
										struct thread_entry *thread_entry,
										const gchar *loc);

#define lua_thread_pool_set_running_entry(pool, thread_entry) \
    lua_thread_pool_set_running_entry_full (pool, thread_entry, G_STRLOC)

/**
 * Prevents yielded thread to be used for callback execution. lua_thread_pool_restore_callback() should be called afterwards.
 *
 * @param pool
 * @param cbs
 */
void
lua_thread_pool_prepare_callback_full (struct lua_thread_pool *pool,
									   struct lua_callback_state *cbs, const gchar *loc);

#define lua_thread_pool_prepare_callback(pool, cbs) \
    lua_thread_pool_prepare_callback_full (pool, cbs, G_STRLOC)

/**
 * Restores state after lua_thread_pool_prepare_callback () usage
 *
 * @param cbs
 */
void
lua_thread_pool_restore_callback_full (struct lua_callback_state *cbs,
									   const gchar *loc);

#define lua_thread_pool_restore_callback(cbs) \
    lua_thread_pool_restore_callback_full (cbs, G_STRLOC)

/**
 * Acts like lua_call but the tread is able to suspend execution.
 * As soon as the call is over, call either thread_entry::finish_callback or thread_entry::error_callback.
 *
 * @param thread_entry
 * @param narg
 */
void
lua_thread_call_full (struct thread_entry *thread_entry,
					  int narg,
					  const gchar *loc);

#define lua_thread_call(thread_entry, narg) \
    lua_thread_call_full (thread_entry, narg, G_STRLOC)

/**
 * Yields thread. should be only called in return statement
 * @param thread_entry
 * @param nresults
 * @return
 */
int
lua_thread_yield_full (struct thread_entry *thread_entry, int nresults,
					   const gchar *loc);

#define lua_thread_yield(thread_entry, narg) \
    lua_thread_yield_full (thread_entry, narg, G_STRLOC)

/**
 * Resumes suspended by lua_yield_thread () thread
 * @param task
 * @param thread_entry
 * @param narg
 */
void
lua_thread_resume_full (struct thread_entry *thread_entry,
						int narg,
						const gchar *loc);

#define lua_thread_resume(thread_entry, narg) \
    lua_thread_resume_full (thread_entry, narg, G_STRLOC)

#ifdef  __cplusplus
}
#endif

#endif /* LUA_THREAD_POOL_H_ */