Compare commits

..

4 Commits

Author SHA1 Message Date
Mid
3cdd88a52d Update README.md 2025-09-06 16:24:03 +03:00
Mid
eca0ac6fe4 Expand table.insert test 2025-09-06 16:23:51 +03:00
Mid
3d8b09167b table.insert test 2025-09-06 15:45:54 +03:00
Mid
3edff81d89 finish table_insert interface 2025-09-06 15:45:47 +03:00
4 changed files with 62 additions and 5 deletions

View File

@@ -17,9 +17,33 @@ Impotent is still work-in-progress:
5. Most operators are still missing
6. The user API is completely different from that of PoC Lua
7. Being lock-free, tables are not split to "array" and "hash" parts
8. Userdata is not yet supported.
Impotent requires C11 and an architecture with 8-byte atomic operations, but otherwise it is completely cross-platform.
Performance-wise, it's surprisingly competitive with PoC Lua, considering how quickly it was made up to the point of writing this README (~2 weeks). By far the worst bottleneck is the GC, since it requires all threads and their heaps to synchronize.
Certain Lua idioms become impossible under Impotent. For example the idiom of appending to tables (`t[#t + 1] = x`) isn't atomic, therefore `table.insert` should be used instead.
## Additions
Obviously, threading. Any thread can access any value from any other thread, including for reading or writing. Operations such as getting or setting are lock-free in the best case scenario, but other operations (such as the `#` operator) must lock the table temporarily.
Besides this, I have no intent to greatly deviate from standard Lua, to keep source-level compatibility as best I can. The only addition to the standard library is the `threads` global, with two methods as of now.
### `threads.run`
Runs a function in a newly created thread. Does not block the caller.
threads.run(function()
-- Do something expensive
end)
### `threads.parallel`
Runs a function in n parallel threads. Blocks the caller until all threads finish.
threads.parallel(8, function()
-- Do something parallelizable.
end)

5
main.c
View File

@@ -32,7 +32,12 @@ static size_t native_print(LVM *lvm, void *ud, size_t argn, set_LValueU *heap, L
static size_t table_insert(LVM *lvm, void *ud, size_t argn, set_LValueU *heap, LRegSet *regset) {
LTable *tbl = (LTable*) (regset->regs[0].u & ~LTAG_MASK);
if(argn == 2) {
ltable_insert(tbl, regset->regs[1], 0);
} else if(argn > 2) {
size_t idx = lvalue_to_int32(regset->regs[1]);
ltable_insert(tbl, regset->regs[2], idx);
}
return 0;
}

15
table.h
View File

@@ -241,9 +241,20 @@ static inline size_t ltable_len(LTable *self) {
return ret;
}
static inline void ltable_insert(LTable *self, LValue val, size_t index) {
static inline bool ltable_insert(LTable *self, LValue val, size_t index) {
lrwl_write_lock(&self->lock);
index = ltable_len_nolock(self) + 1;
size_t len = ltable_len_nolock(self);
if(index == 0) {
index = len + 1;
}
bool success = false;
if(index <= len + 1) {
for(size_t i = len; i >= index; i--) {
ltable_set_nolock(self, lvalue_from_int32(i + 1), ltable_get_nolock(self, lvalue_from_int32(i)));
}
ltable_set_nolock(self, lvalue_from_int32(index), val);
success = true;
}
lrwl_write_unlock(&self->lock);
return success;
}

17
table_insert.lua Normal file
View File

@@ -0,0 +1,17 @@
t = {}
for i = 50, 1, -1 do
table.insert(t, 1, i)
end
for i = 50, 25, -1 do
table.insert(t, #t + 1, i)
end
for i = 24, 1, -1 do
table.insert(t, i)
end
for i = 1, #t do
print(t[i])
end