Binary search exports, too. Is that all the things? This could still be improved, some. And tested.

git-svn-id: https://www.unprompted.com/svn/projects/tildefriends/trunk@3750 ed5197a5-7fde-0310-b194-c3ffbd925b24
This commit is contained in:
Cory McWilliams 2022-01-10 01:50:58 +00:00
parent 7f8155613c
commit 873019f054

View File

@ -91,7 +91,7 @@ typedef struct _tf_task_t {
promiseid_t _nextPromise;
uv_loop_t _loop;
export_record_t* _exports;
export_record_t** _exports;
int _export_count;
exportid_t _nextExport;
@ -109,11 +109,10 @@ typedef struct _tf_task_t {
} tf_task_t;
typedef struct _export_record_t {
exportid_t _export_id;
taskid_t _taskid;
exportid_t _export_id;
JSValue _function;
int _useCount;
export_record_t* _next;
} export_record_t;
static void _export_record_ref(export_record_t* export)
@ -121,9 +120,22 @@ static void _export_record_ref(export_record_t* export)
export->_useCount++;
}
static bool _export_record_release(export_record_t* export)
static bool _export_record_release(tf_task_t* task, export_record_t** export)
{
return --export->_useCount == 0;
if (--(*export)->_useCount == 0)
{
JS_FreeValue(task->_context, (*export)->_function);
(*export)->_function = JS_UNDEFINED;
free(*export);
int index = export - task->_exports;
if (task->_export_count - index)
{
memmove(export, export + 1, sizeof(export_record_t*) * (task->_export_count - index - 1));
}
task->_export_count--;
return true;
}
return false;
}
static JSValue _tf_task_version(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv);
@ -236,27 +248,31 @@ static void _tf_task_trace_exports(tf_task_t* task)
tf_trace_counter(task->_trace, "exports", 1, (const char*[]) { "count" }, (int64_t[]) { task->_export_count });
}
static int _export_compare(const void* a, const void* b)
{
exportid_t ia = *(const exportid_t*)a;
const export_record_t* const* ib = b;
if (ia != (*ib)->_export_id)
{
return ia < (*ib)->_export_id ? -1 : 1;
}
else
{
return 0;
}
}
static void _export_record_release_for_task(tf_task_t* task, taskid_t task_id)
{
bool any = false;
export_record_t** next = NULL;
for (export_record_t** it = &task->_exports;
*it;
it = next)
for (int i = 0; i < task->_export_count; i++)
{
next = &(*it)->_next;
if ((*it)->_taskid == task_id)
if (task->_exports[i]->_taskid == task_id)
{
export_record_t* export = *it;
if (_export_record_release(export))
if (_export_record_release(task, &task->_exports[i]))
{
*it = export->_next;
JS_FreeValue(task->_context, export->_function);
free(export);
task->_export_count--;
_tf_task_trace_exports(task);
next = it;
any = true;
i--;
}
}
}
@ -402,22 +418,17 @@ static JSValue _import_call(JSContext* context, JSValueConst func_obj, JSValueCo
return result;
}
static export_record_t* _task_get_export(tf_task_t* task, exportid_t export_id)
{
for (export_record_t* it = task->_exports; it; it = it->_next)
{
if (it->_export_id == export_id)
static export_record_t** _task_get_export(tf_task_t* task, exportid_t export_id)
{
export_record_t** it = bsearch(&export_id, task->_exports, task->_export_count, sizeof(export_record_t*), _export_compare);
return it;
}
}
return NULL;
}
JSValue _task_invokeExport_internal(tf_taskstub_t* from, tf_task_t* to, exportid_t exportId, const char* buffer, size_t size)
{
JSValue result = JS_NULL;
export_record_t* export = _task_get_export(to, exportId);
export_record_t** it = _task_get_export(to, exportId);
export_record_t* export = it ? *it : NULL;
if (export)
{
JSValue arguments = tf_serialize_load(to, from, buffer, size);
@ -589,16 +600,39 @@ static JSValue _tf_task_version(JSContext* context, JSValueConst this_val, int a
return JS_NewString(task->_context, k_version);
}
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;
}
exportid_t tf_task_export_function(tf_task_t* task, tf_taskstub_t* to, JSValue function)
{
export_record_t* export = NULL;
for (export_record_t* it = task->_exports; it; it = it->_next)
/* TODO: _exports_by_function */
for (int i = 0; i < task->_export_count; i++)
{
if (JS_VALUE_GET_PTR(it->_function) == JS_VALUE_GET_PTR(function) &&
it->_taskid == tf_taskstub_get_id(to))
if (JS_VALUE_GET_PTR(task->_exports[i]->_function) == JS_VALUE_GET_PTR(function))
{
export = it;
export = task->_exports[i];
break;
}
}
@ -616,9 +650,15 @@ exportid_t tf_task_export_function(tf_task_t* task, tf_taskstub_t* to, JSValue f
._export_id = id,
._taskid = tf_taskstub_get_id(to),
._function = JS_DupValue(task->_context, function),
._next = task->_exports,
};
task->_exports = export;
int index = _insert_index(&id, task->_exports, task->_export_count, sizeof(export_record_t*), _export_compare);
task->_exports = realloc(task->_exports, sizeof(export_record_t*) * (task->_export_count + 1));
if (task->_export_count - index)
{
memmove(task->_exports + index + 1, task->_exports + index, sizeof(export_record_t*) * (task->_export_count - index));
}
task->_exports[index] = export;
task->_export_count++;
_tf_task_trace_exports(task);
}
@ -740,22 +780,10 @@ void tf_task_on_receive_packet(int packetType, const char* begin, size_t length,
assert(length == sizeof(exportid_t));
exportid_t exportId;
memcpy(&exportId, begin, sizeof(exportId));
for (export_record_t** it = &to->_exports; *it; it = &(*it)->_next)
export_record_t** it = _task_get_export(to, exportId);
if (it)
{
export_record_t* export = *it;
if (export->_export_id == exportId &&
export->_taskid == tf_taskstub_get_id(from))
{
if (_export_record_release(export))
{
*it = export->_next;
JS_FreeValue(to->_context, export->_function);
free(export);
to->_export_count--;
_tf_task_trace_exports(to);
}
break;
}
_export_record_release(to, it);
}
}
break;
@ -1065,30 +1093,6 @@ static int _promise_compare(const void* a, const void* 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)
{
if (!task->_promises)
@ -1402,13 +1406,15 @@ void tf_task_destroy(tf_task_t* task)
task->_imports = NULL;
task->_import_count = 0;
while (task->_exports)
for (int i = 0; i < task->_export_count; i++)
{
export_record_t* export = task->_exports;
JS_FreeValue(task->_context, export->_function);
task->_exports = export->_next;
free(export);
JS_FreeValue(task->_context, task->_exports[i]->_function);
free(task->_exports[i]);
}
free(task->_exports);
task->_exports = NULL;
task->_export_count = 0;
while (task->_children)
{
task_child_node_t* node = task->_children;