From 1efc0fd73b6016ab00c8a499dcce14aebc6cc5d6 Mon Sep 17 00:00:00 2001 From: Cory McWilliams Date: Tue, 12 Jul 2022 01:51:15 +0000 Subject: [PATCH] Another linked list bites the dust. git-svn-id: https://www.unprompted.com/svn/projects/tildefriends/trunk@3928 ed5197a5-7fde-0310-b194-c3ffbd925b24 --- src/mem.c | 4 +- src/ssb.c | 104 ++++++++++++++++++++++++++++++-------------------- src/task.c | 30 ++------------- src/util.js.c | 25 ++++++++++++ src/util.js.h | 1 + 5 files changed, 94 insertions(+), 70 deletions(-) diff --git a/src/mem.c b/src/mem.c index b4be62c3..29f13f8e 100644 --- a/src/mem.c +++ b/src/mem.c @@ -174,9 +174,9 @@ void* tf_resize_vec(void* ptr, size_t size) memcpy(&alloc_size, alloc_ptr, sizeof(size_t)); } - if (alloc_size >= 16 * size + sizeof(size_t)) + if ((alloc_size >= 16 * size + sizeof(size_t)) || !size) { - /* If we've dropped significantly in size, resize down. */ + /* If we've dropped significantly in size or are freeing, resize down. */ return tf_realloc(ptr, size); } else if (alloc_size >= size + sizeof(size_t)) diff --git a/src/ssb.c b/src/ssb.c index 193c344d..534b39dd 100644 --- a/src/ssb.c +++ b/src/ssb.c @@ -64,14 +64,15 @@ typedef struct _tf_ssb_broadcast_t tf_ssb_broadcast_t; typedef struct _tf_ssb_connection_t tf_ssb_connection_t; typedef struct _tf_ssb_request_t tf_ssb_request_t; -typedef struct _tf_ssb_request_t { - tf_ssb_request_t* next; +typedef struct _tf_ssb_request_t +{ int32_t request_number; tf_ssb_rpc_callback_t* callback; void* user_data; } tf_ssb_request_t; -typedef struct _tf_ssb_broadcast_t { +typedef struct _tf_ssb_broadcast_t +{ tf_ssb_broadcast_t* next; time_t ctime; time_t mtime; @@ -81,7 +82,8 @@ typedef struct _tf_ssb_broadcast_t { } tf_ssb_broadcast_t; typedef struct _tf_ssb_rpc_callback_node_t tf_ssb_rpc_callback_node_t; -typedef struct _tf_ssb_rpc_callback_node_t { +typedef struct _tf_ssb_rpc_callback_node_t +{ const char** name; tf_ssb_rpc_callback_t* callback; tf_ssb_callback_cleanup_t* cleanup; @@ -90,7 +92,8 @@ typedef struct _tf_ssb_rpc_callback_node_t { } tf_ssb_rpc_callback_node_t; typedef struct _tf_ssb_connections_changed_callback_node_t tf_ssb_connections_changed_callback_node_t; -typedef struct _tf_ssb_connections_changed_callback_node_t { +typedef struct _tf_ssb_connections_changed_callback_node_t +{ tf_ssb_connections_changed_callback_t* callback; tf_ssb_callback_cleanup_t* cleanup; void* user_data; @@ -98,7 +101,8 @@ typedef struct _tf_ssb_connections_changed_callback_node_t { } tf_ssb_connections_changed_callback_node_t; typedef struct _tf_ssb_message_added_callback_node_t tf_ssb_message_added_callback_node_t; -typedef struct _tf_ssb_message_added_callback_node_t { +typedef struct _tf_ssb_message_added_callback_node_t +{ tf_ssb_message_added_callback_t* callback; tf_ssb_callback_cleanup_t* cleanup; void* user_data; @@ -106,7 +110,8 @@ typedef struct _tf_ssb_message_added_callback_node_t { } tf_ssb_message_added_callback_node_t; typedef struct _tf_ssb_blob_want_added_callback_node_t tf_ssb_blob_want_added_callback_node_t; -typedef struct _tf_ssb_blob_want_added_callback_node_t { +typedef struct _tf_ssb_blob_want_added_callback_node_t +{ tf_ssb_blob_want_added_callback_t* callback; tf_ssb_callback_cleanup_t* cleanup; void* user_data; @@ -114,14 +119,16 @@ typedef struct _tf_ssb_blob_want_added_callback_node_t { } tf_ssb_blob_want_added_callback_node_t; typedef struct _tf_ssb_broadcasts_changed_callback_node_t tf_ssb_broadcasts_changed_callback_node_t; -typedef struct _tf_ssb_broadcasts_changed_callback_node_t { +typedef struct _tf_ssb_broadcasts_changed_callback_node_t +{ tf_ssb_broadcasts_changed_callback_t* callback; tf_ssb_callback_cleanup_t* cleanup; void* user_data; tf_ssb_broadcasts_changed_callback_node_t* next; } tf_ssb_broadcasts_changed_callback_node_t; -typedef struct _tf_ssb_t { +typedef struct _tf_ssb_t +{ bool own_context; JSRuntime* runtime; JSContext* context; @@ -174,7 +181,8 @@ typedef struct _tf_ssb_t { int broadcasts_changed_count; } tf_ssb_t; -typedef struct _tf_ssb_connection_t { +typedef struct _tf_ssb_connection_t +{ tf_ssb_t* ssb; uv_tcp_t tcp; uv_connect_t connect; @@ -215,6 +223,7 @@ typedef struct _tf_ssb_connection_t { tf_ssb_connection_t* next; tf_ssb_request_t* requests; + int requests_count; const char* destroy_reason; } tf_ssb_connection_t; @@ -402,26 +411,33 @@ static void _tf_ssb_connection_box_stream_send(tf_ssb_connection_t* connection, tf_free(message_enc); } +static int _request_compare(const void* a, const void* b) +{ + int32_t ai = *(const int32_t*)a; + const tf_ssb_request_t* br = (const tf_ssb_request_t*)b; + return ai < br->request_number ? -1 : br->request_number < ai ? 1 : 0; +} + static bool _tf_ssb_connection_get_request_callback(tf_ssb_connection_t* connection, int32_t request_number, tf_ssb_rpc_callback_t** out_callback, void** out_user_data) { - bool found = false; - for (tf_ssb_request_t* it = connection->requests; it; it = it->next) + if (!connection->requests) { - if (it->request_number == request_number) - { - if (out_callback) - { - *out_callback = it->callback; - } - if (out_user_data) - { - *out_user_data = it->user_data; - } - found = true; - break; - } + return false; } - return found; + tf_ssb_request_t* request = bsearch(&request_number, connection->requests, connection->requests_count, sizeof(tf_ssb_request_t), _request_compare); + if (request) + { + if (out_callback) + { + *out_callback = request->callback; + } + if (out_user_data) + { + *out_user_data = request->user_data; + } + return true; + } + return false; } void tf_ssb_connection_add_request(tf_ssb_connection_t* connection, int32_t request_number, tf_ssb_rpc_callback_t* callback, void* user_data) @@ -429,36 +445,41 @@ void tf_ssb_connection_add_request(tf_ssb_connection_t* connection, int32_t requ if (_tf_ssb_connection_get_request_callback(connection, request_number, NULL, NULL)) { /* TODO: This leaks the callback. */ + printf("Adding a request %d that is already registered.\n", request_number); return; } - tf_ssb_request_t* request = tf_malloc(sizeof(tf_ssb_request_t)); - *request = (tf_ssb_request_t) + tf_ssb_request_t request = { - .next = connection->requests, .request_number = request_number, .callback = callback, .user_data = user_data, }; - connection->requests = request; + int index = tf_util_insert_index(&request_number, connection->requests, connection->requests_count, sizeof(tf_ssb_request_t), _request_compare); + connection->requests = tf_resize_vec(connection->requests, sizeof(tf_ssb_request_t) * (connection->requests_count + 1)); + if (connection->requests_count - index) + { + memmove(connection->requests + index + 1, connection->requests + index, sizeof(tf_ssb_request_t) * (connection->requests_count - index)); + } + connection->requests[index] = request; + connection->requests_count++; + connection->ssb->request_count++; } static void _tf_ssb_connection_remove_request(tf_ssb_connection_t* connection, int32_t request_number) { - for (tf_ssb_request_t** it = &connection->requests; *it; it = &(*it)->next) + tf_ssb_request_t* request = bsearch(&request_number, connection->requests, connection->requests_count, sizeof(tf_ssb_request_t), _request_compare); + if (request) { - if ((*it)->request_number == request_number) + if (request->user_data) { - tf_ssb_request_t* found = *it; - if (found->user_data) - { - JS_FreeValue(tf_ssb_connection_get_context(connection), JS_MKPTR(JS_TAG_OBJECT, found->user_data)); - } - *it = found->next; - tf_free(found); - connection->ssb->request_count--; - break; + JS_FreeValue(tf_ssb_connection_get_context(connection), JS_MKPTR(JS_TAG_OBJECT, request->user_data)); } + int index = request - connection->requests; + memmove(request, request + 1, sizeof(tf_ssb_request_t) * (connection->requests_count - index - 1)); + connection->requests_count--; + connection->requests = tf_resize_vec(connection->requests, sizeof(tf_ssb_request_t) * connection->requests_count); + connection->ssb->request_count--; } } @@ -1342,6 +1363,7 @@ void _tf_ssb_connection_destroy(tf_ssb_connection_t* connection, const char* rea } while (connection->requests) { + printf("%d %d\n", connection->requests_count, connection->requests->request_number); _tf_ssb_connection_remove_request(connection, connection->requests->request_number); } if (!JS_IsUndefined(connection->object)) diff --git a/src/task.c b/src/task.c index 6b94e006..949a3b01 100644 --- a/src/task.c +++ b/src/task.c @@ -602,30 +602,6 @@ 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; @@ -654,7 +630,7 @@ exportid_t tf_task_export_function(tf_task_t* task, tf_taskstub_t* to, JSValue f ._function = JS_DupValue(task->_context, function), }; - int index = _insert_index(&id, task->_exports, task->_export_count, sizeof(export_record_t*), _export_compare); + int index = tf_util_insert_index(&id, task->_exports, task->_export_count, sizeof(export_record_t*), _export_compare); task->_exports = tf_resize_vec(task->_exports, sizeof(export_record_t*) * (task->_export_count + 1)); if (task->_export_count - index) { @@ -1021,7 +997,7 @@ JSValue tf_task_allocate_promise(tf_task_t* task, promiseid_t* out_promise) .values = { JS_NULL, JS_NULL }, }; JSValue result = JS_NewPromiseCapability(task->_context, promise.values); - int index = _insert_index((void*)(intptr_t)promiseId, task->_promises, task->_promise_count, sizeof(promise_t), _promise_compare); + int index = tf_util_insert_index((void*)(intptr_t)promiseId, task->_promises, task->_promise_count, sizeof(promise_t), _promise_compare); task->_promises = tf_resize_vec(task->_promises, sizeof(promise_t) * (task->_promise_count + 1)); if (task->_promise_count - index) { @@ -1540,7 +1516,7 @@ JSValue tf_task_add_import(tf_task_t* task, taskid_t stub_id, exportid_t export_ ._useCount = 1, }; - int index = _insert_index(import, task->_imports, task->_import_count, sizeof(import_record_t*), _import_compare); + int index = tf_util_insert_index(import, task->_imports, task->_import_count, sizeof(import_record_t*), _import_compare); task->_imports = tf_resize_vec(task->_imports, sizeof(import_record_t*) * (task->_import_count + 1)); if (task->_import_count - index) { diff --git a/src/util.js.c b/src/util.js.c index 7d26d9c0..f867fa48 100644 --- a/src/util.js.c +++ b/src/util.js.c @@ -214,3 +214,28 @@ int tf_util_get_length(JSContext* context, JSValue value) JS_FreeValue(context, length); return result; } + +int tf_util_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; +} + diff --git a/src/util.js.h b/src/util.js.h index c89a3aec..c59f8043 100644 --- a/src/util.js.h +++ b/src/util.js.h @@ -10,3 +10,4 @@ uint8_t* tf_util_try_get_array_buffer(JSContext* context, size_t* psize, JSValue JSValue tf_util_try_get_typed_array_buffer(JSContext* context, JSValueConst obj, size_t* pbyte_offset, size_t* pbyte_length, size_t* pbytes_per_element); bool tf_util_report_error(JSContext* context, JSValue value); int tf_util_get_length(JSContext* context, JSValue value); +int tf_util_insert_index(const void* key, const void* base, size_t count, size_t size, int (*compare)(const void*, const void*));