Needs more work, but several experiments that make things more responsive under load.
git-svn-id: https://www.unprompted.com/svn/projects/tildefriends/trunk@3783 ed5197a5-7fde-0310-b194-c3ffbd925b24
This commit is contained in:
97
src/task.c
97
src/task.c
@ -99,6 +99,9 @@ typedef struct _tf_task_t
|
||||
uint64_t last_hrtime;
|
||||
uint64_t last_idle_time;
|
||||
|
||||
uv_idle_t idle;
|
||||
uv_prepare_t prepare;
|
||||
|
||||
export_record_t** _exports;
|
||||
int _export_count;
|
||||
exportid_t _nextExport;
|
||||
@ -349,7 +352,6 @@ int tf_task_execute(tf_task_t* task, const char* fileName)
|
||||
executed = true;
|
||||
}
|
||||
JS_FreeValue(task->_context, result);
|
||||
tf_task_run_jobs(task);
|
||||
free((void*)source);
|
||||
}
|
||||
else
|
||||
@ -469,7 +471,6 @@ JSValue _task_invokeExport_internal(tf_taskstub_t* from, tf_task_t* to, exportid
|
||||
result = JS_Call(to->_context, function, this_val, length - 1, argument_array);
|
||||
tf_trace_end(to->_trace);
|
||||
tf_util_report_error(to->_context, result);
|
||||
tf_task_run_jobs(to);
|
||||
|
||||
JS_FreeValue(to->_context, this_val);
|
||||
for (int i = 0; i < length - 1; i++)
|
||||
@ -535,8 +536,6 @@ static void _forward_promise(tf_task_t* from, tf_taskstub_t* to, promiseid_t pro
|
||||
JS_FreeValue(from->_context, promise_catch);
|
||||
JS_FreeValue(from->_context, then_handler);
|
||||
JS_FreeValue(from->_context, catch_handler);
|
||||
|
||||
tf_task_run_jobs(from);
|
||||
}
|
||||
|
||||
static void _tf_task_sendPromiseResolve(tf_task_t* from, tf_taskstub_t* to, promiseid_t promise, JSValue result)
|
||||
@ -1000,7 +999,6 @@ JSValue _tf_task_require(JSContext* context, JSValueConst this_val, int argc, JS
|
||||
JS_SetPropertyStr(task->_context, global, "exports", JS_DupValue(task->_context, exports));
|
||||
JSValue eval = JS_Eval(task->_context, source, strlen(source), path, 0);
|
||||
tf_util_report_error(task->_context, eval);
|
||||
tf_task_run_jobs(task);
|
||||
if (JS_IsError(task->_context, eval) ||
|
||||
JS_IsException(eval))
|
||||
{
|
||||
@ -1040,10 +1038,6 @@ static JSValue _tf_task_executeSource(tf_task_t* task, const char* source, const
|
||||
{
|
||||
snprintf(task->_scriptName, sizeof(task->_scriptName), "%s", name);
|
||||
}
|
||||
if (!JS_IsException(result))
|
||||
{
|
||||
tf_task_run_jobs(task);
|
||||
}
|
||||
tf_trace_end(task->_trace);
|
||||
return result;
|
||||
}
|
||||
@ -1079,7 +1073,6 @@ JSValue _tf_task_sandbox_require(JSContext* context, JSValueConst this_val, int
|
||||
tf_util_report_error(context, result);
|
||||
JS_SetPropertyStr(context, global, "exports", oldExports);
|
||||
JS_FreeValue(context, global);
|
||||
tf_task_run_jobs(task);
|
||||
free(source);
|
||||
return exports;
|
||||
}
|
||||
@ -1094,7 +1087,6 @@ JSValue _tf_task_sandbox_require(JSContext* context, JSValueConst this_val, int
|
||||
tf_util_report_error(context, result);
|
||||
JS_SetPropertyStr(context, global, "exports", oldExports);
|
||||
JS_FreeValue(context, global);
|
||||
tf_task_run_jobs(task);
|
||||
return exports;
|
||||
}
|
||||
else
|
||||
@ -1181,7 +1173,6 @@ void tf_task_resolve_promise(tf_task_t* task, promiseid_t promise, JSValue value
|
||||
JS_FreeValue(task->_context, it->values[2]);
|
||||
JS_FreeValue(task->_context, result);
|
||||
_tf_task_free_promise(task, promise);
|
||||
tf_task_run_jobs(task);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1212,7 +1203,6 @@ void tf_task_reject_promise(tf_task_t* task, promiseid_t promise, JSValue value)
|
||||
JS_FreeValue(task->_context, it->values[2]);
|
||||
JS_FreeValue(task->_context, result);
|
||||
_tf_task_free_promise(task, promise);
|
||||
tf_task_run_jobs(task);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1314,6 +1304,54 @@ static void _tf_task_trace_timer(uv_timer_t* timer)
|
||||
tf_trace_counter(task->_trace, "task", sizeof(k_names) / sizeof(*k_names), k_names, values);
|
||||
}
|
||||
|
||||
static void _tf_task_run_jobs_idle(uv_idle_t* idle);
|
||||
static void _tf_task_run_jobs_prepare(uv_prepare_t* prepare);
|
||||
|
||||
static bool _tf_task_run_jobs(tf_task_t* task)
|
||||
{
|
||||
if (JS_IsJobPending(task->_runtime))
|
||||
{
|
||||
JSContext* context = NULL;
|
||||
int r = JS_ExecutePendingJob(task->_runtime, &context);
|
||||
JSValue result = JS_GetException(context);
|
||||
if (context)
|
||||
{
|
||||
tf_util_report_error(context, result);
|
||||
}
|
||||
if (r < 0)
|
||||
{
|
||||
js_std_dump_error(context);
|
||||
}
|
||||
else
|
||||
{
|
||||
return r != 0;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void _tf_task_run_jobs_idle(uv_idle_t* idle)
|
||||
{
|
||||
tf_task_t* task = idle->data;
|
||||
if (!_tf_task_run_jobs(task))
|
||||
{
|
||||
/* No more jobs. Don't try again as actively. */
|
||||
uv_idle_stop(&task->idle);
|
||||
uv_prepare_start(&task->prepare, _tf_task_run_jobs_prepare);
|
||||
}
|
||||
}
|
||||
|
||||
static void _tf_task_run_jobs_prepare(uv_prepare_t* prepare)
|
||||
{
|
||||
tf_task_t* task = prepare->data;
|
||||
if (_tf_task_run_jobs(task))
|
||||
{
|
||||
/* More jobs. We can run again immediately. */
|
||||
uv_idle_start(&task->idle, _tf_task_run_jobs_idle);
|
||||
uv_prepare_stop(&task->prepare);
|
||||
}
|
||||
}
|
||||
|
||||
tf_task_t* tf_task_create()
|
||||
{
|
||||
tf_task_t* task = malloc(sizeof(tf_task_t));
|
||||
@ -1342,6 +1380,11 @@ tf_task_t* tf_task_create()
|
||||
uv_timer_init(&task->_loop, &task->trace_timer);
|
||||
uv_timer_start(&task->trace_timer, _tf_task_trace_timer, 100, 100);
|
||||
uv_unref((uv_handle_t*)&task->trace_timer);
|
||||
task->idle.data = task;
|
||||
uv_idle_init(&task->_loop, &task->idle);
|
||||
task->prepare.data = task;
|
||||
uv_prepare_init(&task->_loop, &task->prepare);
|
||||
uv_idle_start(&task->idle, _tf_task_run_jobs_idle);
|
||||
return task;
|
||||
}
|
||||
|
||||
@ -1531,8 +1574,12 @@ void tf_task_destroy(tf_task_t* task)
|
||||
{
|
||||
uv_close((uv_handle_t*)&task->trace_timer, _tf_task_on_handle_close);
|
||||
}
|
||||
uv_close((uv_handle_t*)&task->idle, _tf_task_on_handle_close);
|
||||
uv_close((uv_handle_t*)&task->prepare, _tf_task_on_handle_close);
|
||||
|
||||
while (task->trace_timer.data)
|
||||
while (task->trace_timer.data ||
|
||||
task->idle.data ||
|
||||
task->prepare.data)
|
||||
{
|
||||
uv_run(&task->_loop, UV_RUN_ONCE);
|
||||
}
|
||||
@ -1587,28 +1634,6 @@ tf_task_t* tf_task_get(JSContext* context)
|
||||
return JS_GetContextOpaque(context);
|
||||
}
|
||||
|
||||
void tf_task_run_jobs(tf_task_t* task)
|
||||
{
|
||||
while (JS_IsJobPending(task->_runtime))
|
||||
{
|
||||
JSContext* context = NULL;
|
||||
int r = JS_ExecutePendingJob(task->_runtime, &context);
|
||||
JSValue result = JS_GetException(context);
|
||||
if (context)
|
||||
{
|
||||
tf_util_report_error(context, result);
|
||||
}
|
||||
if (r < 0)
|
||||
{
|
||||
js_std_dump_error(context);
|
||||
}
|
||||
else if (r == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void tf_task_send_promise_message(tf_task_t* from, tf_taskstub_t* to, tf_task_message_t type, promiseid_t promise, JSValue payload)
|
||||
{
|
||||
_tf_task_sendPromiseMessage(from, to, type, promise, payload);
|
||||
|
Reference in New Issue
Block a user