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
|
#include "config.h"
#include <assert.h>
#include "lua_common.h"
#include "lua_thread_pool.h"
struct lua_thread_pool {
GQueue *available_items;
lua_State *L;
gint max_items;
struct thread_entry *running_entry;
};
static struct thread_entry *
thread_entry_new (lua_State * L)
{
struct thread_entry *ent;
ent = g_malloc (sizeof *ent);
ent->lua_state = lua_newthread (L);
ent->thread_index = luaL_ref (L, LUA_REGISTRYINDEX);
return ent;
}
static void
thread_entry_free (lua_State * L, struct thread_entry *ent)
{
luaL_unref (L, LUA_REGISTRYINDEX, ent->thread_index);
g_free (ent);
}
struct lua_thread_pool *
lua_thread_pool_new (lua_State * L)
{
struct lua_thread_pool * pool = g_new0 (struct lua_thread_pool, 1);
pool->L = L;
pool->max_items = 100;
pool->available_items = g_queue_new ();
int i;
struct thread_entry *ent;
for (i = 0; i < pool->max_items; i ++) {
ent = thread_entry_new (pool->L);
g_queue_push_head (pool->available_items, ent);
}
return pool;
}
void
lua_thread_pool_free (struct lua_thread_pool *pool)
{
struct thread_entry *ent = NULL;
while (!g_queue_is_empty (pool->available_items)) {
ent = g_queue_pop_head (pool->available_items);
thread_entry_free (pool->L, ent);
}
g_queue_free (pool->available_items);
g_free (pool);
}
struct thread_entry *
lua_thread_pool_get(struct lua_thread_pool *pool)
{
gpointer cur;
struct thread_entry *ent = NULL;
cur = g_queue_pop_head (pool->available_items);
if (cur) {
ent = cur;
}
else {
ent = thread_entry_new (pool->L);
}
return ent;
}
void
lua_thread_pool_return(struct lua_thread_pool *pool, struct thread_entry *thread_entry)
{
assert (lua_status (thread_entry->lua_state) == 0); // we can't return a running/yielded stack into the pool
if (pool->running_entry == thread_entry) {
pool->running_entry = NULL;
}
if (g_queue_get_length (pool->available_items) <= pool->max_items) {
g_queue_push_head (pool->available_items, thread_entry);
}
else {
thread_entry_free (pool->L, thread_entry);
}
}
void
lua_thread_pool_terminate_entry(struct lua_thread_pool *pool, struct thread_entry *thread_entry)
{
struct thread_entry *ent = NULL;
if (pool->running_entry == thread_entry) {
pool->running_entry = NULL;
}
// we should only terminate failed threads
assert (lua_status (thread_entry->lua_state) != 0 && lua_status (thread_entry->lua_state) != LUA_YIELD);
thread_entry_free (pool->L, thread_entry);
if (g_queue_get_length (pool->available_items) <= pool->max_items) {
ent = thread_entry_new (pool->L);
g_queue_push_head (pool->available_items, ent);
}
}
struct thread_entry *
lua_thread_pool_get_running_entry(struct lua_thread_pool *pool)
{
return pool->running_entry;
}
void
lua_thread_pool_set_running_entry(struct lua_thread_pool *pool, struct thread_entry *thread_entry)
{
pool->running_entry = thread_entry;
}
|