Binary search import records.
git-svn-id: https://www.unprompted.com/svn/projects/tildefriends/trunk@3742 ed5197a5-7fde-0310-b194-c3ffbd925b24
This commit is contained in:
parent
bb81fc87b9
commit
26150f98e1
151
src/task.c
151
src/task.c
@ -95,7 +95,7 @@ typedef struct _tf_task_t {
|
||||
int _export_count;
|
||||
exportid_t _nextExport;
|
||||
|
||||
import_record_t* _imports;
|
||||
import_record_t** _imports;
|
||||
int _import_count;
|
||||
JSValue _requires;
|
||||
JSValue _loadedFiles;
|
||||
@ -143,64 +143,85 @@ static tf_taskstub_t* _tf_task_get_stub(tf_task_t* task, taskid_t id);
|
||||
static void _tf_task_release_export(tf_taskstub_t* stub, exportid_t exportId);
|
||||
|
||||
typedef struct _import_record_t {
|
||||
tf_task_t* _owner;
|
||||
JSValue _function;
|
||||
exportid_t _export;
|
||||
taskid_t _task;
|
||||
tf_task_t* _owner;
|
||||
int _useCount;
|
||||
import_record_t* _next;
|
||||
} import_record_t;
|
||||
|
||||
static int _import_compare(const void* a, const void* b)
|
||||
{
|
||||
const import_record_t* ia = a;
|
||||
const import_record_t* const* ib = b;
|
||||
if (ia->_task != (*ib)->_task)
|
||||
{
|
||||
return ia->_task < (*ib)->_task ? -1 : 1;
|
||||
}
|
||||
else if (ia->_export != (*ib)->_export)
|
||||
{
|
||||
return ia->_export < (*ib)->_export ? -1 : 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static import_record_t** _tf_task_find_import(tf_task_t* task, taskid_t task_id, exportid_t export_id)
|
||||
{
|
||||
if (!task->_imports)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
import_record_t search =
|
||||
{
|
||||
._task = task_id,
|
||||
._export = export_id,
|
||||
};
|
||||
import_record_t** it = bsearch(&search, task->_imports, task->_import_count, sizeof(import_record_t*), _import_compare);
|
||||
return it;
|
||||
}
|
||||
|
||||
static void _tf_task_trace_imports(tf_task_t* task)
|
||||
{
|
||||
tf_trace_counter(task->_trace, "imports", 1, (const char*[]) { "count" }, (int64_t[]) { task->_import_count });
|
||||
}
|
||||
|
||||
static void _import_record_release(import_record_t* import)
|
||||
static void _import_record_release(import_record_t** import)
|
||||
{
|
||||
JSContext* context = import->_owner->_context;
|
||||
if (--import->_useCount > 0)
|
||||
JSContext* context = (*import)->_owner->_context;
|
||||
tf_task_t* task = (*import)->_owner;
|
||||
import_record_t* record = *import;
|
||||
|
||||
if (--record->_useCount > 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
JS_SetOpaque(import->_function, NULL);
|
||||
JS_FreeValue(context, import->_function);
|
||||
import->_function = JS_UNDEFINED;
|
||||
_tf_task_release_export(_tf_task_get_stub(import->_owner, import->_task), import->_export);
|
||||
JS_SetOpaque(record->_function, NULL);
|
||||
JS_FreeValue(context, record->_function);
|
||||
record->_function = JS_UNDEFINED;
|
||||
_tf_task_release_export(_tf_task_get_stub(task, record->_task), record->_export);
|
||||
|
||||
for (import_record_t** it = &import->_owner->_imports;
|
||||
*it;
|
||||
it = &(*it)->_next)
|
||||
{
|
||||
if (*it == import)
|
||||
{
|
||||
*it = import->_next;
|
||||
import->_owner->_import_count--;
|
||||
_tf_task_trace_imports(import->_owner);
|
||||
import->_next = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
int index = import - task->_imports;
|
||||
memmove(import, import + 1, sizeof(import_record_t*) * (task->_import_count - index - 1));
|
||||
task->_import_count--;
|
||||
_tf_task_trace_imports(task);
|
||||
|
||||
free(import);
|
||||
free(record);
|
||||
}
|
||||
|
||||
static void _import_record_release_for_task(tf_task_t* task, taskid_t task_id)
|
||||
{
|
||||
bool any = false;
|
||||
import_record_t** next = NULL;
|
||||
for (import_record_t** it = &task->_imports;
|
||||
*it;
|
||||
it = next)
|
||||
for (int i = 0; i < task->_import_count; i++)
|
||||
{
|
||||
next = &(*it)->_next;
|
||||
if ((*it)->_task == task_id)
|
||||
if (task->_imports[i]->_task == task_id)
|
||||
{
|
||||
import_record_t* import = *it;
|
||||
_import_record_release(import);
|
||||
next = it;
|
||||
_import_record_release(&task->_imports[i]);
|
||||
any = true;
|
||||
--i;
|
||||
}
|
||||
}
|
||||
|
||||
@ -644,12 +665,34 @@ static JSValue _tf_task_getFile(JSContext* context, JSValueConst this_val, int a
|
||||
return result;
|
||||
}
|
||||
|
||||
const char* _tf_task_get_message_type(tf_task_message_t type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case kResolvePromise: return "kResolvePromise";
|
||||
case kRejectPromise: return "kRejectPromise";
|
||||
case kInvokeExport: return "kInvokeExport";
|
||||
case kReleaseExport: return "kReleaseExport";
|
||||
case kReleaseImport: return "kReleaseImport";
|
||||
case kSetRequires: return "kSetRequires";
|
||||
case kActivate: return "kActivate";
|
||||
case kExecute: return "kExecute";
|
||||
case kKill: return "kKill";
|
||||
case kSetImports: return "kSetImports";
|
||||
case kGetExports: return "kGetExports";
|
||||
case kLoadFile: return "kLoadFile";
|
||||
case kTaskError: return "kTaskError";
|
||||
case kTaskTrace: return "kTaskTrace";
|
||||
}
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
void tf_task_on_receive_packet(int packetType, const char* begin, size_t length, void* userData)
|
||||
{
|
||||
tf_taskstub_t* stub = userData;
|
||||
tf_taskstub_t* from = stub;
|
||||
tf_task_t* to = tf_taskstub_get_owner(stub);
|
||||
tf_trace_begin(to->_trace, "tf_task_on_receive_packet");
|
||||
tf_trace_begin(to->_trace, _tf_task_get_message_type(packetType));
|
||||
|
||||
switch (packetType)
|
||||
{
|
||||
@ -721,13 +764,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 (import_record_t* it = to->_imports; it; it = it->_next)
|
||||
import_record_t** it = _tf_task_find_import(to, tf_taskstub_get_id(from), exportId);
|
||||
if (it)
|
||||
{
|
||||
if (it->_task == tf_taskstub_get_id(from) && it->_export == exportId)
|
||||
{
|
||||
_import_record_release(it);
|
||||
break;
|
||||
}
|
||||
_import_record_release(it);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -1091,7 +1131,10 @@ promiseid_t tf_task_allocate_promise(tf_task_t* task)
|
||||
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));
|
||||
if (task->_promise_count - index)
|
||||
{
|
||||
memmove(task->_promises + index + 1, task->_promises + index, sizeof(promise_t) * (task->_promise_count - index));
|
||||
}
|
||||
task->_promises[index] = promise;
|
||||
task->_promise_count++;
|
||||
_tf_task_trace_promises(task);
|
||||
@ -1187,7 +1230,11 @@ void tf_task_remove_child(tf_task_t* task, tf_taskstub_t* child)
|
||||
static void _import_finalizer(JSRuntime* runtime, JSValue value)
|
||||
{
|
||||
import_record_t* import = JS_GetOpaque(value, _import_class_id);
|
||||
_import_record_release(import);
|
||||
if (import)
|
||||
{
|
||||
import_record_t** it = _tf_task_find_import(import->_owner, import->_task, import->_export);
|
||||
_import_record_release(it);
|
||||
}
|
||||
}
|
||||
|
||||
static void _import_mark_func(JSRuntime* runtime, JSValueConst value, JS_MarkFunc mark_func)
|
||||
@ -1346,15 +1393,14 @@ JSContext* tf_task_get_context(tf_task_t* task)
|
||||
|
||||
void tf_task_destroy(tf_task_t* task)
|
||||
{
|
||||
import_record_t* it = task->_imports;
|
||||
while (it)
|
||||
for (int i = 0; i < task->_import_count; i++)
|
||||
{
|
||||
import_record_t* next = it->_next;
|
||||
JS_FreeValue(task->_context, it->_function);
|
||||
free(it);
|
||||
it = next;
|
||||
JS_FreeValue(task->_context, task->_imports[i]->_function);
|
||||
free(task->_imports[i]);
|
||||
}
|
||||
free(task->_imports);
|
||||
task->_imports = NULL;
|
||||
task->_import_count = 0;
|
||||
|
||||
while (task->_exports)
|
||||
{
|
||||
@ -1429,10 +1475,15 @@ JSValue tf_task_add_import(tf_task_t* task, taskid_t stub_id, exportid_t export_
|
||||
._owner = task,
|
||||
._task = stub_id,
|
||||
._useCount = 1,
|
||||
._next = task->_imports,
|
||||
};
|
||||
|
||||
task->_imports = import;
|
||||
int index = _insert_index(import, task->_imports, task->_import_count, sizeof(import_record_t*), _import_compare);
|
||||
task->_imports = realloc(task->_imports, sizeof(import_record_t*) * (task->_import_count + 1));
|
||||
if (task->_import_count - index)
|
||||
{
|
||||
memmove(task->_imports + index + 1, task->_imports + index, sizeof(import_record_t*) * (task->_import_count - index));
|
||||
}
|
||||
task->_imports[index] = import;
|
||||
task->_import_count++;
|
||||
_tf_task_trace_imports(task);
|
||||
return function;
|
||||
|
Loading…
Reference in New Issue
Block a user