1 #ifndef LUA_THREAD_POOL_H_
2 #define LUA_THREAD_POOL_H_
3 
4 #include <lua.h>
5 
6 #ifdef  __cplusplus
7 extern "C" {
8 #endif
9 
10 struct thread_entry;
11 struct lua_thread_pool;
12 
13 typedef void (*lua_thread_finish_t) (struct thread_entry *thread, int ret);
14 
15 typedef void (*lua_thread_error_t) (struct thread_entry *thread, int ret, const char *msg);
16 
17 struct thread_entry {
18 	lua_State *lua_state;
19 	gint thread_index;
20 	gpointer cd;
21 
22 	/* function to handle result of called method, can be NULL */
23 	lua_thread_finish_t finish_callback;
24 
25 	/* function to log result, i.e. if you want to modify error logging message or somehow process this state, can be NUL */
26 	lua_thread_error_t error_callback;
27 	struct rspamd_task *task;
28 	struct rspamd_config *cfg;
29 };
30 
31 struct lua_callback_state {
32 	lua_State *L;
33 	struct thread_entry *my_thread;
34 	struct thread_entry *previous_thread;
35 	struct lua_thread_pool *thread_pool;
36 };
37 
38 /**
39  * Allocates new thread pool on state L. Pre-creates number of lua-threads to use later on
40  *
41  * @param L
42  * @return
43  */
44 struct lua_thread_pool *
45 lua_thread_pool_new (lua_State *L);
46 
47 /**
48  * Destroys the pool
49  * @param pool
50  */
51 void
52 lua_thread_pool_free (struct lua_thread_pool *pool);
53 
54 /**
55  * Extracts a thread from the list of available ones.
56  * It immediately becames running one and should be used to run a Lua script/function straight away.
57  * as soon as the code is finished, it should be either returned into list of available threads by
58  * calling lua_thread_pool_return() or terminated by calling lua_thread_pool_terminate_entry()
59  * if the code finished with error.
60  *
61  * If the code performed YIELD, the thread is still running and it's live should be controlled by the callee
62  *
63  * @param task
64  * @return
65  */
66 struct thread_entry *
67 lua_thread_pool_get_for_task (struct rspamd_task *task);
68 
69 /**
70  * The same, but used when task is not available
71  *
72  * @param cfg
73  * @return
74  */
75 struct thread_entry *
76 lua_thread_pool_get_for_config (struct rspamd_config *cfg);
77 
78 /**
79  * Return thread into the list of available ones. It can't be done with yielded or dead threads.
80  *
81  * @param pool
82  * @param thread_entry
83  */
84 void
85 lua_thread_pool_return_full (struct lua_thread_pool *pool,
86 							 struct thread_entry *thread_entry,
87 							 const gchar *loc);
88 
89 #define lua_thread_pool_return(pool, thread_entry) \
90     lua_thread_pool_return_full (pool, thread_entry, G_STRLOC)
91 
92 /**
93  * Currently running thread. Typically needed in yielding point - to fill-up continuation.
94  *
95  * @param pool
96  * @return
97  */
98 struct thread_entry *
99 lua_thread_pool_get_running_entry_full (struct lua_thread_pool *pool,
100 										const gchar *loc);
101 
102 #define lua_thread_pool_get_running_entry(pool) \
103     lua_thread_pool_get_running_entry_full (pool, G_STRLOC)
104 
105 /**
106  * Updates currently running thread
107  *
108  * @param pool
109  * @param thread_entry
110  */
111 void
112 lua_thread_pool_set_running_entry_full (struct lua_thread_pool *pool,
113 										struct thread_entry *thread_entry,
114 										const gchar *loc);
115 
116 #define lua_thread_pool_set_running_entry(pool, thread_entry) \
117     lua_thread_pool_set_running_entry_full (pool, thread_entry, G_STRLOC)
118 
119 /**
120  * Prevents yielded thread to be used for callback execution. lua_thread_pool_restore_callback() should be called afterwards.
121  *
122  * @param pool
123  * @param cbs
124  */
125 void
126 lua_thread_pool_prepare_callback_full (struct lua_thread_pool *pool,
127 									   struct lua_callback_state *cbs, const gchar *loc);
128 
129 #define lua_thread_pool_prepare_callback(pool, cbs) \
130     lua_thread_pool_prepare_callback_full (pool, cbs, G_STRLOC)
131 
132 /**
133  * Restores state after lua_thread_pool_prepare_callback () usage
134  *
135  * @param cbs
136  */
137 void
138 lua_thread_pool_restore_callback_full (struct lua_callback_state *cbs,
139 									   const gchar *loc);
140 
141 #define lua_thread_pool_restore_callback(cbs) \
142     lua_thread_pool_restore_callback_full (cbs, G_STRLOC)
143 
144 /**
145  * Acts like lua_call but the tread is able to suspend execution.
146  * As soon as the call is over, call either thread_entry::finish_callback or thread_entry::error_callback.
147  *
148  * @param thread_entry
149  * @param narg
150  */
151 void
152 lua_thread_call_full (struct thread_entry *thread_entry,
153 					  int narg,
154 					  const gchar *loc);
155 
156 #define lua_thread_call(thread_entry, narg) \
157     lua_thread_call_full (thread_entry, narg, G_STRLOC)
158 
159 /**
160  * Yields thread. should be only called in return statement
161  * @param thread_entry
162  * @param nresults
163  * @return
164  */
165 int
166 lua_thread_yield_full (struct thread_entry *thread_entry, int nresults,
167 					   const gchar *loc);
168 
169 #define lua_thread_yield(thread_entry, narg) \
170     lua_thread_yield_full (thread_entry, narg, G_STRLOC)
171 
172 /**
173  * Resumes suspended by lua_yield_thread () thread
174  * @param task
175  * @param thread_entry
176  * @param narg
177  */
178 void
179 lua_thread_resume_full (struct thread_entry *thread_entry,
180 						int narg,
181 						const gchar *loc);
182 
183 #define lua_thread_resume(thread_entry, narg) \
184     lua_thread_resume_full (thread_entry, narg, G_STRLOC)
185 
186 /**
187  * Terminates thread pool entry and fill the pool with another thread entry if needed
188  * @param pool
189  * @param thread_entry
190  * @param loc
191  */
192 void
193 lua_thread_pool_terminate_entry_full (struct lua_thread_pool *pool,
194 								 struct thread_entry *thread_entry,
195 								 const gchar *loc, bool enforce);
196 #define lua_thread_pool_terminate_entry(pool, thread_entry) \
197     lua_thread_pool_terminate_entry_full (pool, thread_entry, G_STRLOC, false)
198 
199 #ifdef  __cplusplus
200 }
201 #endif
202 
203 #endif /* LUA_THREAD_POOL_H_ */
204 
205