mirror of https://github.com/mgba-emu/mgba.git
Scripting: Allow weakrefs to be marked for auto-collection
This commit is contained in:
parent
58089fb334
commit
b5f600c0c5
|
@ -89,6 +89,7 @@ uint32_t mScriptContextSetWeakref(struct mScriptContext*, struct mScriptValue* v
|
||||||
struct mScriptValue* mScriptContextMakeWeakref(struct mScriptContext*, struct mScriptValue* value);
|
struct mScriptValue* mScriptContextMakeWeakref(struct mScriptContext*, struct mScriptValue* value);
|
||||||
struct mScriptValue* mScriptContextAccessWeakref(struct mScriptContext*, struct mScriptValue* value);
|
struct mScriptValue* mScriptContextAccessWeakref(struct mScriptContext*, struct mScriptValue* value);
|
||||||
void mScriptContextClearWeakref(struct mScriptContext*, uint32_t weakref);
|
void mScriptContextClearWeakref(struct mScriptContext*, uint32_t weakref);
|
||||||
|
void mScriptContextDisownWeakref(struct mScriptContext*, uint32_t weakref);
|
||||||
|
|
||||||
void mScriptContextAttachStdlib(struct mScriptContext* context);
|
void mScriptContextAttachStdlib(struct mScriptContext* context);
|
||||||
void mScriptContextAttachSocket(struct mScriptContext* context);
|
void mScriptContextAttachSocket(struct mScriptContext* context);
|
||||||
|
|
|
@ -12,8 +12,9 @@ set(TEST_FILES
|
||||||
if(USE_LUA)
|
if(USE_LUA)
|
||||||
list(APPEND SOURCE_FILES engines/lua.c)
|
list(APPEND SOURCE_FILES engines/lua.c)
|
||||||
list(APPEND TEST_FILES
|
list(APPEND TEST_FILES
|
||||||
test/stdlib.c
|
test/context.c
|
||||||
test/lua.c)
|
test/lua.c
|
||||||
|
test/stdlib.c)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
source_group("Scripting" FILES ${SOURCE_FILES})
|
source_group("Scripting" FILES ${SOURCE_FILES})
|
||||||
|
|
|
@ -71,8 +71,8 @@ void mScriptContextInit(struct mScriptContext* context) {
|
||||||
|
|
||||||
void mScriptContextDeinit(struct mScriptContext* context) {
|
void mScriptContextDeinit(struct mScriptContext* context) {
|
||||||
HashTableDeinit(&context->rootScope);
|
HashTableDeinit(&context->rootScope);
|
||||||
HashTableDeinit(&context->weakrefs);
|
|
||||||
mScriptContextDrainPool(context);
|
mScriptContextDrainPool(context);
|
||||||
|
HashTableDeinit(&context->weakrefs);
|
||||||
mScriptListDeinit(&context->refPool);
|
mScriptListDeinit(&context->refPool);
|
||||||
HashTableDeinit(&context->callbacks);
|
HashTableDeinit(&context->callbacks);
|
||||||
TableDeinit(&context->callbackId);
|
TableDeinit(&context->callbackId);
|
||||||
|
@ -102,9 +102,12 @@ void mScriptContextFillPool(struct mScriptContext* context, struct mScriptValue*
|
||||||
void mScriptContextDrainPool(struct mScriptContext* context) {
|
void mScriptContextDrainPool(struct mScriptContext* context) {
|
||||||
size_t i;
|
size_t i;
|
||||||
for (i = 0; i < mScriptListSize(&context->refPool); ++i) {
|
for (i = 0; i < mScriptListSize(&context->refPool); ++i) {
|
||||||
struct mScriptValue* value = mScriptValueUnwrap(mScriptListGetPointer(&context->refPool, i));
|
struct mScriptValue* value = mScriptListGetPointer(&context->refPool, i);
|
||||||
if (value) {
|
if (value->type->base == mSCRIPT_TYPE_WRAPPER) {
|
||||||
|
value = mScriptValueUnwrap(value);
|
||||||
mScriptValueDeref(value);
|
mScriptValueDeref(value);
|
||||||
|
} else if (value->type == mSCRIPT_TYPE_MS_WEAKREF) {
|
||||||
|
mScriptContextClearWeakref(context, value->value.u32);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mScriptListClear(&context->refPool);
|
mScriptListClear(&context->refPool);
|
||||||
|
@ -201,6 +204,13 @@ void mScriptContextClearWeakref(struct mScriptContext* context, uint32_t weakref
|
||||||
TableRemove(&context->weakrefs, weakref);
|
TableRemove(&context->weakrefs, weakref);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void mScriptContextDisownWeakref(struct mScriptContext* context, uint32_t weakref) {
|
||||||
|
struct mScriptValue* poolEntry = mScriptListAppend(&context->refPool);
|
||||||
|
poolEntry->type = mSCRIPT_TYPE_MS_WEAKREF;
|
||||||
|
poolEntry->value.u32 = weakref;
|
||||||
|
poolEntry->refs = mSCRIPT_VALUE_UNREF;
|
||||||
|
}
|
||||||
|
|
||||||
void mScriptContextTriggerCallback(struct mScriptContext* context, const char* callback) {
|
void mScriptContextTriggerCallback(struct mScriptContext* context, const char* callback) {
|
||||||
struct mScriptValue* list = HashTableLookup(&context->callbacks, callback);
|
struct mScriptValue* list = HashTableLookup(&context->callbacks, callback);
|
||||||
if (!list) {
|
if (!list) {
|
||||||
|
|
|
@ -0,0 +1,103 @@
|
||||||
|
/* Copyright (c) 2013-2023 Jeffrey Pfau
|
||||||
|
*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
#include "util/test/suite.h"
|
||||||
|
|
||||||
|
#include <mgba/script/context.h>
|
||||||
|
#include <mgba/script/macros.h>
|
||||||
|
#include <mgba/script/types.h>
|
||||||
|
|
||||||
|
M_TEST_DEFINE(weakrefBasic) {
|
||||||
|
struct mScriptContext context;
|
||||||
|
mScriptContextInit(&context);
|
||||||
|
|
||||||
|
struct mScriptValue weakref = mSCRIPT_VAL(WEAKREF, 1);
|
||||||
|
struct mScriptValue fakeVal = mSCRIPT_S32(0x7E57CA5E);
|
||||||
|
struct mScriptValue* val;
|
||||||
|
|
||||||
|
assert_int_equal(TableSize(&context.weakrefs), 0);
|
||||||
|
assert_null(TableLookup(&context.weakrefs, 1));
|
||||||
|
assert_int_equal(context.nextWeakref, 1);
|
||||||
|
assert_null(mScriptContextAccessWeakref(&context, &weakref));
|
||||||
|
|
||||||
|
assert_int_equal(mScriptContextSetWeakref(&context, &fakeVal), 1);
|
||||||
|
assert_int_equal(context.nextWeakref, 2);
|
||||||
|
assert_int_equal(TableSize(&context.weakrefs), 1);
|
||||||
|
val = mScriptContextAccessWeakref(&context, &weakref);
|
||||||
|
assert_non_null(val);
|
||||||
|
assert_int_equal(val->value.u32, 0x7E57CA5E);
|
||||||
|
|
||||||
|
mScriptContextClearWeakref(&context, 1);
|
||||||
|
|
||||||
|
assert_int_equal(TableSize(&context.weakrefs), 0);
|
||||||
|
assert_null(TableLookup(&context.weakrefs, 1));
|
||||||
|
assert_int_equal(context.nextWeakref, 2);
|
||||||
|
assert_null(mScriptContextAccessWeakref(&context, &weakref));
|
||||||
|
|
||||||
|
mScriptContextDeinit(&context);
|
||||||
|
}
|
||||||
|
|
||||||
|
M_TEST_DEFINE(drainPool) {
|
||||||
|
struct mScriptContext context;
|
||||||
|
mScriptContextInit(&context);
|
||||||
|
|
||||||
|
assert_int_equal(mScriptListSize(&context.refPool), 0);
|
||||||
|
|
||||||
|
struct mScriptValue fakeVal = mSCRIPT_CHARP("foo");
|
||||||
|
fakeVal.refs = 2;
|
||||||
|
|
||||||
|
mScriptContextFillPool(&context, &fakeVal);
|
||||||
|
assert_int_equal(mScriptListSize(&context.refPool), 1);
|
||||||
|
assert_int_equal(fakeVal.refs, 2);
|
||||||
|
|
||||||
|
mScriptContextDrainPool(&context);
|
||||||
|
assert_int_equal(mScriptListSize(&context.refPool), 0);
|
||||||
|
assert_int_equal(fakeVal.refs, 1);
|
||||||
|
|
||||||
|
mScriptContextDeinit(&context);
|
||||||
|
}
|
||||||
|
|
||||||
|
M_TEST_DEFINE(disownWeakref) {
|
||||||
|
struct mScriptContext context;
|
||||||
|
mScriptContextInit(&context);
|
||||||
|
|
||||||
|
struct mScriptValue weakref = mSCRIPT_VAL(WEAKREF, 1);
|
||||||
|
struct mScriptValue fakeVal = mSCRIPT_S32(0x7E57CA5E);
|
||||||
|
struct mScriptValue* val;
|
||||||
|
|
||||||
|
assert_int_equal(mScriptListSize(&context.refPool), 0);
|
||||||
|
assert_int_equal(TableSize(&context.weakrefs), 0);
|
||||||
|
assert_null(TableLookup(&context.weakrefs, 1));
|
||||||
|
assert_int_equal(context.nextWeakref, 1);
|
||||||
|
assert_null(mScriptContextAccessWeakref(&context, &weakref));
|
||||||
|
|
||||||
|
assert_int_equal(mScriptContextSetWeakref(&context, &fakeVal), 1);
|
||||||
|
assert_int_equal(TableSize(&context.weakrefs), 1);
|
||||||
|
assert_int_equal(context.nextWeakref, 2);
|
||||||
|
val = mScriptContextAccessWeakref(&context, &weakref);
|
||||||
|
assert_non_null(val);
|
||||||
|
assert_int_equal(val->value.u32, 0x7E57CA5E);
|
||||||
|
|
||||||
|
mScriptContextDisownWeakref(&context, 1);
|
||||||
|
assert_int_equal(mScriptListSize(&context.refPool), 1);
|
||||||
|
assert_int_equal(TableSize(&context.weakrefs), 1);
|
||||||
|
val = mScriptContextAccessWeakref(&context, &weakref);
|
||||||
|
assert_non_null(val);
|
||||||
|
assert_int_equal(val->value.u32, 0x7E57CA5E);
|
||||||
|
|
||||||
|
mScriptContextDrainPool(&context);
|
||||||
|
assert_int_equal(mScriptListSize(&context.refPool), 0);
|
||||||
|
assert_int_equal(TableSize(&context.weakrefs), 0);
|
||||||
|
assert_null(TableLookup(&context.weakrefs, 1));
|
||||||
|
assert_null(mScriptContextAccessWeakref(&context, &weakref));
|
||||||
|
|
||||||
|
mScriptContextDeinit(&context);
|
||||||
|
}
|
||||||
|
|
||||||
|
M_TEST_SUITE_DEFINE(mScript,
|
||||||
|
cmocka_unit_test(weakrefBasic),
|
||||||
|
cmocka_unit_test(drainPool),
|
||||||
|
cmocka_unit_test(disownWeakref),
|
||||||
|
)
|
Loading…
Reference in New Issue