aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/thread/buffer.md13
-rw-r--r--src/lua.c11
-rw-r--r--src/thread.c69
-rw-r--r--tests/tests.lua2
-rw-r--r--tests/units/closure-copy.lua16
5 files changed, 102 insertions, 9 deletions
diff --git a/docs/thread/buffer.md b/docs/thread/buffer.md
index e366a33..65af0c0 100644
--- a/docs/thread/buffer.md
+++ b/docs/thread/buffer.md
@@ -12,6 +12,19 @@ the __index metamethod will index any value that is not a buffer.* method on the
every other metamethod will be replaced with a proxy to the metamethod in the copied object
+inner functions can be called using the : syntactic sugar
+
+```
+buffer = llby.thread.buffer(llby.crypto.sha1())
+
+buffer:set(buffer:get():update("awa"))
+--or
+buffer:set(buffer.update(buffer:get(), "awa"))
+
+--is the same as
+buffer:set(buffer:update("awa"))
+```
+
### buffer:get
buffer:get()
diff --git a/src/lua.c b/src/lua.c
index a1ae4cd..27547d3 100644
--- a/src/lua.c
+++ b/src/lua.c
@@ -257,8 +257,15 @@ void luaI_deepcopy(lua_State* src, lua_State* dest, enum deep_copy_flags flags){
lua_dump(src, writer, (void*)awa, 0);
luaL_loadbuffer(dest, awa->c, awa->len, "fun");
- if(!(flags & SKIP_LOCALS)) lua_assign_upvalues(dest, lua_gettop(dest));
- //lua_remove(dest, -2);
+ //if(!(flags & SKIP_LOCALS)) lua_assign_upvalues(dest, lua_gettop(dest));
+
+ int f = lua_gettop(dest);
+ for(int i = 1; lua_getupvalue(src, -1, i) != NULL; i++){
+ luaI_deepcopy(src, dest, flags);
+ lua_setupvalue(dest, f, i);
+ lua_pop(src, 1);
+ }
+
str_free(awa);
break;
case LUA_TUSERDATA:
diff --git a/src/thread.c b/src/thread.c
index a5f5cc2..555a62b 100644
--- a/src/thread.c
+++ b/src/thread.c
@@ -15,7 +15,7 @@
struct thread_info {
str* function;
lua_State* L;
- int return_count, done, request_close;
+ int return_count, done, request_close, detached;
pthread_t tid;
pthread_mutex_t* lock, *ready_lock, *close_lock;
pthread_cond_t* cond;
@@ -190,9 +190,38 @@ void* handle_thread(void* _args){
pthread_cond_signal(&*args->cond);
pthread_mutex_unlock(&*args->close_lock);
+#warning "race condition here"
+ if(args->detached) {
+ lua_gc(args->L, LUA_GCCOLLECT);
+ lua_close(args->L);
+ args->L = NULL;
+
+ pthread_mutex_destroy(&*args->lock);
+ free(args->lock);
+ pthread_mutex_destroy(&*args->close_lock);
+ free(args->close_lock);
+
+ pthread_cond_destroy(&*args->cond);
+ free(args->cond);
+ free(args);
+ }
+
return NULL;
}
+int _thread_detach(lua_State* L){
+ lua_pushstring(L, "_");
+ lua_gettable(L, 1);
+ struct thread_info* info = lua_touserdata(L, -1);
+ lua_getmetatable(L, -1);
+ int idx = lua_gettop(L);
+
+ luaI_tsetnil(L, idx, "__gc");
+ info->detached = 1;
+
+ return 0;
+}
+
int _thread_await(lua_State* L){
lua_pushstring(L, "_");
lua_gettable(L, 1);
@@ -243,9 +272,7 @@ int _thread_clean(lua_State* L){
//lua_gc(info->L, LUA_GCRESTART);
lua_gc(info->L, LUA_GCCOLLECT);
-
lua_close(info->L);
-
info->L = NULL;
pthread_mutex_destroy(&*info->lock);
@@ -255,7 +282,6 @@ int _thread_clean(lua_State* L){
pthread_cond_destroy(&*info->cond);
free(info->cond);
-
free(info);
}
return 0;
@@ -340,6 +366,7 @@ int l_async(lua_State* oL){
luaI_tsetcf(oL, res_idx, "clean", _thread_clean);
luaI_tsetcf(oL, res_idx, "kill", _thread_kill);
luaI_tsetcf(oL, res_idx, "close", _thread_close);
+ luaI_tsetcf(oL, res_idx, "detach", _thread_detach);
luaI_tsetlud(oL, res_idx, "_", args);
lua_newtable(oL);
@@ -358,17 +385,18 @@ struct thread_buffer {
};
int _buffer_get(lua_State* L){
- struct thread_buffer *buffer = lua_touserdata(L, 1);
+ struct thread_buffer *buffer = lua_touserdata(L, -1);
pthread_mutex_lock(&*buffer->lock);
luaI_deepcopy(buffer->L, L, SKIP_GC | SKIP_LOCALS);
pthread_mutex_unlock(&*buffer->lock);
return 1;
}
+#warning "how do you handle gc for the new object?"
int _buffer_set(lua_State* L){
struct thread_buffer *buffer = lua_touserdata(L, 1);
pthread_mutex_lock(&*buffer->lock);
- lua_settop(buffer->L, 0);
+ lua_settop(buffer->L, 0);
luaI_deepcopy(L, buffer->L, SKIP_LOCALS | STRIP_GC);
pthread_mutex_unlock(&*buffer->lock);
@@ -401,6 +429,26 @@ int _buffer_mod(lua_State* L){
return 1;
}
+int _buffer_func_wrapper(lua_State* L){
+ int argc = lua_gettop(L);
+
+ if(argc > 0 && lua_type(L, 1) == LUA_TUSERDATA
+ && lua_touserdata(L, 1) == lua_touserdata(L, lua_upvalueindex(2))){
+ lua_pushvalue(L, lua_upvalueindex(2));
+ _buffer_get(L);
+ lua_replace(L, 1);
+ lua_settop(L, argc);
+ }
+
+ lua_pushcfunction(L, luaI_errtraceback);
+ lua_insert(L, 1);
+
+ lua_pushvalue(L, lua_upvalueindex(1));
+ lua_insert(L, 2);
+ luaI_assert(L, lua_pcall(L, argc, LUA_MULTRET, 1) == 0);
+
+ return lua_gettop(L) - 1;
+}
int l_buffer_index(lua_State* L){
uint64_t len, hash;
@@ -430,6 +478,10 @@ int l_buffer_index(lua_State* L){
luaI_deepcopy(buffer->L, L, SKIP_GC | SKIP_LOCALS);
lua_pop(buffer->L, 1);
+ if(lua_type(L, -1) == LUA_TFUNCTION){
+ lua_pushvalue(L, 1);
+ lua_pushcclosure(L, _buffer_func_wrapper, 2);
+ }
break;
}
return 1;
@@ -490,6 +542,11 @@ void meta_proxy_gen(lua_State* L, struct thread_buffer *buffer, int meta_idx, in
char* fn = calloc(128, sizeof * fn);
const char* key = lua_tostring(L, k);
+ if(strcmp(key, "__gc") == 0){
+ free(fn);
+ lua_pop(L, 2);
+ continue;
+ }
sprintf(fn, "return function(...)\
return __proxy_call(__this_obj,'%s',...);end", key);
luaL_dostring(L, fn);
diff --git a/tests/tests.lua b/tests/tests.lua
index c95e072..f605bd0 100644
--- a/tests/tests.lua
+++ b/tests/tests.lua
@@ -21,7 +21,7 @@ local handle = assert(io.popen("find tests/units/".. search .." -type f"))
for file in handle:lines() do
total = total + 1
- print(file)
+ print(file .. " ...")
local f = loadfile(file)()
--move up one line and clear it
diff --git a/tests/units/closure-copy.lua b/tests/units/closure-copy.lua
new file mode 100644
index 0000000..23cbc07
--- /dev/null
+++ b/tests/units/closure-copy.lua
@@ -0,0 +1,16 @@
+local A = 298
+local B = 3428
+local C = 438
+local D = 4444
+local function outer(a, b)
+ local c = C
+ return function(d)
+ return a + b * c + d
+ end
+end
+
+local val = llby.thread.async(function(res)
+ res(outer(A, B)(D))
+end):await()
+
+return val == A + B * C + D