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; promiseid_t _nextPromise;
uv_loop_t _loop; uv_loop_t _loop;
export_record_t* _exports; export_record_t** _exports;
int _export_count; int _export_count;
exportid_t _nextExport; exportid_t _nextExport;
@ -109,11 +109,10 @@ typedef struct _tf_task_t {
} tf_task_t; } tf_task_t;
typedef struct _export_record_t { typedef struct _export_record_t {
exportid_t _export_id;
taskid_t _taskid; taskid_t _taskid;
exportid_t _export_id;
JSValue _function; JSValue _function;
int _useCount; int _useCount;
export_record_t* _next;
} export_record_t; } export_record_t;
static void _export_record_ref(export_record_t* export) static void _export_record_ref(export_record_t* export)
@ -121,9 +120,22 @@ static void _export_record_ref(export_record_t* export)
export->_useCount++; 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); 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 }); 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) static void _export_record_release_for_task(tf_task_t* task, taskid_t task_id)
{ {
bool any = false; bool any = false;
export_record_t** next = NULL; for (int i = 0; i < task->_export_count; i++)
for (export_record_t** it = &task->_exports;
*it;
it = next)
{ {
next = &(*it)->_next; if (task->_exports[i]->_taskid == task_id)
if ((*it)->_taskid == task_id)
{ {
export_record_t* export = *it; if (_export_record_release(task, &task->_exports[i]))
if (_export_record_release(export))
{ {
*it = export->_next;
JS_FreeValue(task->_context, export->_function);
free(export);
task->_export_count--;
_tf_task_trace_exports(task);
next = it;
any = true; any = true;
i--;
} }
} }
} }
@ -402,22 +418,17 @@ static JSValue _import_call(JSContext* context, JSValueConst func_obj, JSValueCo
return result; return result;
} }
static export_record_t* _task_get_export(tf_task_t* task, exportid_t export_id) 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) export_record_t** it = bsearch(&export_id, task->_exports, task->_export_count, sizeof(export_record_t*), _export_compare);
{ return it;
if (it->_export_id == export_id)
{
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 _task_invokeExport_internal(tf_taskstub_t* from, tf_task_t* to, exportid_t exportId, const char* buffer, size_t size)
{ {
JSValue result = JS_NULL; 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) if (export)
{ {
JSValue arguments = tf_serialize_load(to, from, buffer, size); 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); 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) exportid_t tf_task_export_function(tf_task_t* task, tf_taskstub_t* to, JSValue function)
{ {
export_record_t* export = NULL; export_record_t* export = NULL;
/* TODO: _exports_by_function */
for (export_record_t* it = task->_exports; it; it = it->_next) for (int i = 0; i < task->_export_count; i++)
{ {
if (JS_VALUE_GET_PTR(it->_function) == JS_VALUE_GET_PTR(function) && if (JS_VALUE_GET_PTR(task->_exports[i]->_function) == JS_VALUE_GET_PTR(function))
it->_taskid == tf_taskstub_get_id(to))
{ {
export = it; export = task->_exports[i];
break; break;
} }
} }
@ -616,9 +650,15 @@ exportid_t tf_task_export_function(tf_task_t* task, tf_taskstub_t* to, JSValue f
._export_id = id, ._export_id = id,
._taskid = tf_taskstub_get_id(to), ._taskid = tf_taskstub_get_id(to),
._function = JS_DupValue(task->_context, function), ._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++; task->_export_count++;
_tf_task_trace_exports(task); _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)); assert(length == sizeof(exportid_t));
exportid_t exportId; exportid_t exportId;
memcpy(&exportId, begin, sizeof(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; _export_record_release(to, 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;
}
} }
} }
break; 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; 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) static promise_t* _tf_task_find_promise(tf_task_t* task, promiseid_t id)
{ {
if (!task->_promises) if (!task->_promises)
@ -1402,13 +1406,15 @@ void tf_task_destroy(tf_task_t* task)
task->_imports = NULL; task->_imports = NULL;
task->_import_count = 0; 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, task->_exports[i]->_function);
JS_FreeValue(task->_context, export->_function); free(task->_exports[i]);
task->_exports = export->_next;
free(export);
} }
free(task->_exports);
task->_exports = NULL;
task->_export_count = 0;
while (task->_children) while (task->_children)
{ {
task_child_node_t* node = task->_children; task_child_node_t* node = task->_children;