@@ -32,20 +32,19 @@ extern "C" {
32
32
#include " filesys.h"
33
33
#include " porting.h"
34
34
#include " common/c_internal.h"
35
+ #include " lua_api/l_base.h"
35
36
36
37
/* *****************************************************************************/
37
38
AsyncEngine::~AsyncEngine ()
38
39
{
39
-
40
40
// Request all threads to stop
41
41
for (AsyncWorkerThread *workerThread : workerThreads) {
42
42
workerThread->stop ();
43
43
}
44
44
45
-
46
45
// Wake up all threads
47
- for (std::vector<AsyncWorkerThread *>::iterator it = workerThreads. begin ();
48
- it != workerThreads. end (); ++it) {
46
+ for (auto it : workerThreads) {
47
+ ( void )it;
49
48
jobQueueCounter.post ();
50
49
}
51
50
@@ -68,6 +67,7 @@ AsyncEngine::~AsyncEngine()
68
67
/* *****************************************************************************/
69
68
void AsyncEngine::registerStateInitializer (StateInitializer func)
70
69
{
70
+ FATAL_ERROR_IF (initDone, " Initializer may not be registered after init" );
71
71
stateInitializers.push_back (func);
72
72
}
73
73
@@ -85,47 +85,47 @@ void AsyncEngine::initialize(unsigned int numEngines)
85
85
}
86
86
87
87
/* *****************************************************************************/
88
- unsigned int AsyncEngine::queueAsyncJob (const std::string &func,
89
- const std::string ¶ms )
88
+ u32 AsyncEngine::queueAsyncJob (std::string && func, std::string &¶ms ,
89
+ const std::string &mod_origin )
90
90
{
91
91
jobQueueMutex.lock ();
92
- LuaJobInfo toAdd;
93
- toAdd.id = jobIdCounter++;
94
- toAdd.serializedFunction = func;
95
- toAdd.serializedParams = params;
92
+ u32 jobId = jobIdCounter++;
96
93
97
- jobQueue.push_back (toAdd);
94
+ jobQueue.emplace_back ();
95
+ auto &to_add = jobQueue.back ();
96
+ to_add.id = jobId;
97
+ to_add.function = std::move (func);
98
+ to_add.params = std::move (params);
99
+ to_add.mod_origin = mod_origin;
98
100
99
101
jobQueueCounter.post ();
100
-
101
102
jobQueueMutex.unlock ();
102
-
103
- return toAdd.id ;
103
+ return jobId;
104
104
}
105
105
106
106
/* *****************************************************************************/
107
- LuaJobInfo AsyncEngine::getJob ()
107
+ bool AsyncEngine::getJob (LuaJobInfo *job )
108
108
{
109
109
jobQueueCounter.wait ();
110
110
jobQueueMutex.lock ();
111
111
112
- LuaJobInfo retval;
112
+ bool retval = false ;
113
113
114
114
if (!jobQueue.empty ()) {
115
- retval = jobQueue.front ();
115
+ *job = std::move ( jobQueue.front () );
116
116
jobQueue.pop_front ();
117
- retval. valid = true ;
117
+ retval = true ;
118
118
}
119
119
jobQueueMutex.unlock ();
120
120
121
121
return retval;
122
122
}
123
123
124
124
/* *****************************************************************************/
125
- void AsyncEngine::putJobResult (const LuaJobInfo &result)
125
+ void AsyncEngine::putJobResult (LuaJobInfo & &result)
126
126
{
127
127
resultQueueMutex.lock ();
128
- resultQueue.push_back ( result);
128
+ resultQueue.emplace_back ( std::move ( result) );
129
129
resultQueueMutex.unlock ();
130
130
}
131
131
@@ -134,26 +134,30 @@ void AsyncEngine::step(lua_State *L)
134
134
{
135
135
int error_handler = PUSH_ERROR_HANDLER (L);
136
136
lua_getglobal (L, " core" );
137
- resultQueueMutex.lock ();
137
+
138
+ ScriptApiBase *script = ModApiBase::getScriptApiBase (L);
139
+
140
+ MutexAutoLock autolock (resultQueueMutex);
138
141
while (!resultQueue.empty ()) {
139
- LuaJobInfo jobDone = resultQueue.front ();
142
+ LuaJobInfo j = std::move ( resultQueue.front () );
140
143
resultQueue.pop_front ();
141
144
142
145
lua_getfield (L, -1 , " async_event_handler" );
143
-
144
- if (lua_isnil (L, -1 )) {
146
+ if (lua_isnil (L, -1 ))
145
147
FATAL_ERROR (" Async event handler does not exist!" );
146
- }
147
-
148
148
luaL_checktype (L, -1 , LUA_TFUNCTION);
149
149
150
- lua_pushinteger (L, jobDone.id );
151
- lua_pushlstring (L, jobDone.serializedResult .data (),
152
- jobDone.serializedResult .size ());
150
+ lua_pushinteger (L, j.id );
151
+ lua_pushlstring (L, j.result .data (), j.result .size ());
153
152
154
- PCALL_RESL (L, lua_pcall (L, 2 , 0 , error_handler));
153
+ // Call handler
154
+ const char *origin = j.mod_origin .empty () ? nullptr : j.mod_origin .c_str ();
155
+ script->setOriginDirect (origin);
156
+ int result = lua_pcall (L, 2 , 0 , error_handler);
157
+ if (result)
158
+ script_error (L, result, origin, " <async>" );
155
159
}
156
- resultQueueMutex. unlock ();
160
+
157
161
lua_pop (L, 2 ); // Pop core and error handler
158
162
}
159
163
@@ -168,8 +172,8 @@ void AsyncEngine::prepareEnvironment(lua_State* L, int top)
168
172
/* *****************************************************************************/
169
173
AsyncWorkerThread::AsyncWorkerThread (AsyncEngine* jobDispatcher,
170
174
const std::string &name) :
171
- Thread(name),
172
175
ScriptApiBase(ScriptingType::Async),
176
+ Thread(name),
173
177
jobDispatcher(jobDispatcher)
174
178
{
175
179
lua_State *L = getStack ();
@@ -196,9 +200,9 @@ void* AsyncWorkerThread::run()
196
200
{
197
201
lua_State *L = getStack ();
198
202
199
- std::string script = getServer ()->getBuiltinLuaPath () + DIR_DELIM + " init.lua" ;
200
203
try {
201
- loadScript (script);
204
+ loadMod (getServer ()->getBuiltinLuaPath () + DIR_DELIM + " init.lua" ,
205
+ BUILTIN_MOD_NAME);
202
206
} catch (const ModError &e) {
203
207
errorstream << " Execution of async base environment failed: "
204
208
<< e.what () << std::endl;
@@ -213,44 +217,44 @@ void* AsyncWorkerThread::run()
213
217
}
214
218
215
219
// Main loop
220
+ LuaJobInfo j;
216
221
while (!stopRequested ()) {
217
222
// Wait for job
218
- LuaJobInfo toProcess = jobDispatcher->getJob ();
219
-
220
- if (!toProcess.valid || stopRequested ()) {
223
+ if (!jobDispatcher->getJob (&j) || stopRequested ())
221
224
continue ;
222
- }
223
225
224
226
lua_getfield (L, -1 , " job_processor" );
225
- if (lua_isnil (L, -1 )) {
227
+ if (lua_isnil (L, -1 ))
226
228
FATAL_ERROR (" Unable to get async job processor!" );
227
- }
228
-
229
229
luaL_checktype (L, -1 , LUA_TFUNCTION);
230
230
231
- // Call it
232
- lua_pushlstring (L,
233
- toProcess.serializedFunction .data (),
234
- toProcess.serializedFunction .size ());
235
- lua_pushlstring (L,
236
- toProcess.serializedParams .data (),
237
- toProcess.serializedParams .size ());
231
+ if (luaL_loadbuffer (L, j.function .data (), j.function .size (), " =(async)" )) {
232
+ errorstream << " ASYNC WORKER: Unable to deserialize function" << std::endl;
233
+ lua_pushnil (L);
234
+ }
235
+ lua_pushlstring (L, j.params .data (), j.params .size ());
238
236
237
+ // Call it
238
+ setOriginDirect (j.mod_origin .empty () ? nullptr : j.mod_origin .c_str ());
239
239
int result = lua_pcall (L, 2 , 1 , error_handler);
240
240
if (result) {
241
- PCALL_RES (result);
242
- toProcess.serializedResult = " " ;
241
+ try {
242
+ scriptError (result, " <async>" );
243
+ } catch (const ModError &e) {
244
+ errorstream << e.what () << std::endl;
245
+ }
243
246
} else {
244
247
// Fetch result
245
248
size_t length;
246
249
const char *retval = lua_tolstring (L, -1 , &length);
247
- toProcess. serializedResult = std::string (retval, length);
250
+ j. result . assign (retval, length);
248
251
}
249
252
250
253
lua_pop (L, 1 ); // Pop retval
251
254
252
255
// Put job result
253
- jobDispatcher->putJobResult (toProcess);
256
+ if (!j.result .empty ())
257
+ jobDispatcher->putJobResult (std::move (j));
254
258
}
255
259
256
260
lua_pop (L, 2 ); // Pop core and error handler
0 commit comments