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;
|
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;
|
||||||
|
Loading…
Reference in New Issue
Block a user