diff --git a/src/task.c b/src/task.c index 4e4bc239..47f44456 100644 --- a/src/task.c +++ b/src/task.c @@ -58,7 +58,6 @@ typedef struct _promise_t promise_t; typedef struct _promise_t { promiseid_t id; JSValue values[3]; - promise_t* next; } promise_t; typedef struct _tf_task_t { @@ -1006,16 +1005,45 @@ tf_trace_t* tf_task_get_trace(tf_task_t* task) return task->_trace; } +static int _promise_compare(const void* a, const void* b) +{ + promiseid_t ida = (promiseid_t)(intptr_t)a; + const promise_t* pb = b; + return ida < pb->id ? -1 : pb->id < ida ? 1 : 0; +} + +static int _insert_index(const void* key, const void* base, size_t count, size_t size, int (*compare)(const void*, const void*)) +{ + int lower = 0; + int upper = count; + while (lower < upper && lower < (int)count) + { + int guess = (lower + upper) / 2; + int result = compare(key, ((char*)base) + size * guess); + if (result < 0) + { + upper = guess; + } + else if (result > 0) + { + lower = guess + 1; + } + else + { + return guess; + } + }; + return lower; +} + static promise_t* _tf_task_find_promise(tf_task_t* task, promiseid_t id) { - for (promise_t* it = task->_promises; it; it = it->next) + if (!task->_promises) { - if (it->id == id) - { - return it; - } + return NULL; } - return NULL; + promise_t* it = bsearch((void*)(intptr_t)id, task->_promises, task->_promise_count, sizeof(promise_t), _promise_compare); + return it ? it : NULL; } static void _tf_task_trace_promises(tf_task_t* task) @@ -1025,17 +1053,13 @@ static void _tf_task_trace_promises(tf_task_t* task) static void _tf_task_free_promise(tf_task_t* task, promiseid_t id) { - for (promise_t** it = &task->_promises; *it; it = &(*it)->next) + promise_t* it = bsearch((void*)(intptr_t)id, task->_promises, task->_promise_count, sizeof(promise_t), _promise_compare); + if (it) { - if ((*it)->id == id) - { - promise_t* promise = *it; - *it = (*it)->next; - free(promise); - task->_promise_count--; - _tf_task_trace_promises(task); - break; - } + int index = it - task->_promises; + memmove(it, it + 1, sizeof(promise_t) * (task->_promise_count - index - 1)); + task->_promise_count--; + _tf_task_trace_promises(task); } } @@ -1046,15 +1070,16 @@ promiseid_t tf_task_allocate_promise(tf_task_t* task) promiseId = task->_nextPromise++; } while (_tf_task_find_promise(task, promiseId)); - promise_t* promise = malloc(sizeof(promise_t)); - *promise = (promise_t) + promise_t promise = { .id = promiseId, - .next = task->_promises, .values = { JS_NULL, JS_NULL, JS_NULL }, }; - promise->values[0] = JS_NewPromiseCapability(task->_context, &promise->values[1]); - task->_promises = promise; + promise.values[0] = JS_NewPromiseCapability(task->_context, &promise.values[1]); + int index = _insert_index((void*)(intptr_t)promiseId, task->_promises, task->_promise_count, sizeof(promise_t), _promise_compare); + task->_promises = realloc(task->_promises, sizeof(promise_t) * (task->_promise_count + 1)); + memmove(task->_promises + index, task->_promises + index + 1, sizeof(promise_t) * (task->_promise_count - index)); + task->_promises[index] = promise; task->_promise_count++; _tf_task_trace_promises(task); return promiseId; @@ -1327,10 +1352,12 @@ void tf_task_destroy(tf_task_t* task) { JS_FreeValue(task->_context, tf_taskstub_get_task_object(task->_parent)); } - while (task->_promises) + while (task->_promise_count) { - tf_task_reject_promise(task, task->_promises->id, JS_NULL); + tf_task_reject_promise(task, task->_promises[task->_promise_count - 1].id, JS_NULL); } + free(task->_promises); + task->_promises = NULL; JS_FreeValue(task->_context, task->_requires); JS_FreeValue(task->_context, task->_loadedFiles); while (task->_scriptExports)