forked from cory/tildefriends
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:
parent
7f8155613c
commit
873019f054
166
src/task.c
166
src/task.c
@ -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)
|
||||
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)
|
||||
{
|
||||
return it;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
export_record_t** it = bsearch(&export_id, task->_exports, task->_export_count, sizeof(export_record_t*), _export_compare);
|
||||
return it;
|
||||
}
|
||||
|
||||
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;
|
||||
|
Loading…
Reference in New Issue
Block a user