aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/net.md13
-rw-r--r--docs/thread.md202
-rw-r--r--makefile5
-rw-r--r--src/thread.c277
-rw-r--r--src/thread.h21
-rw-r--r--src/types/larray.c79
-rw-r--r--src/types/larray.h21
-rw-r--r--tests/h.lua32
8 files changed, 397 insertions, 253 deletions
diff --git a/docs/net.md b/docs/net.md
index 28a7070..474cdbe 100644
--- a/docs/net.md
+++ b/docs/net.md
@@ -10,15 +10,6 @@ the function will be ran on initilization, the argument has info on the server a
**
right now everything within a server:GET function is partially global, it can read global variables (by making a copy),
it can not read/copy local variables or modify globals
-
-also, (for now) all globals must be refrenced as _G,
-ie:
-function foo()
- ...
-end
-
-_G.foo()
-_G.llib.crypto.md5("hewwo purr")
**
```lua
@@ -53,14 +44,14 @@ the second (req) contains info on the request, the path allows for wildcards, mu
the actual name of the function will change based on what request method you want to accept, all requests are treated the exact same on the backend, besides HEAD requests which will also use all GET requets, and the 'all' variant will get everything
```lua
-server:all("*", function(res, req, next)
+server:all("*", function(res, req)
if(req['Version'] ~= "HTTP/1.1") then
res:close()
end
end)
...
-server:GET("/", function(res, req) do
+server:GET("/", function(res, req)
--version will always be 1.1, as per the middleware
...
end)
diff --git a/docs/thread.md b/docs/thread.md
index a8c10ad..0c8de77 100644
--- a/docs/thread.md
+++ b/docs/thread.md
@@ -1,101 +1,101 @@
-# threads **
-
-## lock, unlock**
-
-'takes an integer
-
-locks any other thread reaching this lock id until a corresponding unlock is met
-
-```lua
-llib.thread.lock(5)
-...
-llib.thread.unlock(5)
-```
-
-more indepth
-
-```lua
-local t = llib.thread.async(function(info)
- ...
- llib.thread.lock(5)
- ...
- res(N)
-end)
-
-...
-llib.thread.unlock(5)
-t:await()
-```
-
-## aync **
-
-'takes a function which will be ran in a separate thread with a single parameter with thread info
-
-these have the same backend (and limitations) of network threads
-
-```lua
-local thread = llib.thread.async(function(res, rej)
- local N = 0
- ...
- res(N)
-end)
-```
-
-### thread function parameters **
-
-as used with "res" above
-
-#### res:res() **
-
-> will be eventually used as just res()
-
-'takes any amount of "any" values
-
-send a value(s) to thread:await() call then stalls the thread until cleaned
-#### res:send() **
-
-'takes "any" value
-
-send a value which can be retrieved from outside the thread with thread:next()
-
-```lua
-info:send(5)
-info:send("hello")
-```
-
-### thread return object **
-
-#### thread:await() **
-
-'optional timeout in ms and boolean whether to keep or not
-
-waits for the thread to return, and returns whatever it returned then closes it, or nil if timeout was exceeded
-if the input is the boolean value true, it will keep the thread alive (otherwise await() can not be called again)
-
-```lua
-thread:await() -- value of N (above)
-```
-
-```lua
-thread:await(20) -- value of N (above) or nil
-```
-
-```lua
-thread:await(true) -- value of N (above)
-thread:await() -- same
-thread:await() -- error, function above performed cleanup
-```
-
-#### thread:next() **
-
-gets the most oldest value sent using info:send() and pops it
-
-```lua
---(continued from above)
-thread:next() -- 5
-thread:next() -- "hello"
-```
-
-#### thread:kill() **
-
-kills the thread
+# threads **
+
+## lock, unlock
+
+'takes an integer
+
+locks any other thread reaching this lock id until a corresponding unlock is met
+
+```lua
+llib.thread.lock(5)
+...
+llib.thread.unlock(5)
+```
+
+more indepth
+
+```lua
+llib.thread.lock(5)
+local t = llib.thread.async(function(info)
+ ...
+ llib.thread.lock(5)
+ ...
+ res(N)
+end)
+
+...
+llib.thread.unlock(5)
+t:await()
+```
+
+## aync **
+
+'takes a function which will be ran in a separate thread with a single parameter with thread info
+
+these have the same backend (and limitations) of network threads
+
+```lua
+local thread = llib.thread.async(function(res, rej)
+ local N = 0
+ ...
+ res(N)
+end)
+```
+
+### thread function parameters **
+
+as used with "res" above
+
+#### res()
+
+'takes any amount of "any" values
+
+send a value(s) to thread:await() call then stalls the thread until cleaned
+
+#### res:send() **
+
+'takes "any" value
+
+send a value which can be retrieved from outside the thread with thread:next()
+
+```lua
+res:send(5)
+res:send("hello")
+```
+
+### thread return object **
+
+#### thread:await() **
+
+'optional timeout in ms and boolean whether to keep or not
+
+waits for the thread to return, and returns whatever it returned then closes it, or nil if timeout was exceeded
+if the input is the boolean value true, it will keep the thread alive (otherwise await() can not be called again)
+
+```lua
+thread:await() -- value of N (above)
+```
+
+```lua
+thread:await(20) -- value of N (above) or nil
+```
+
+```lua
+thread:await(true) -- value of N (above)
+thread:await() -- same
+thread:await() -- error, function above performed cleanup
+```
+
+#### thread:next() **
+
+gets the most oldest value sent using info:send() and pops it
+
+```lua
+--(continued from above)
+thread:next() -- 5
+thread:next() -- "hello"
+```
+
+#### thread:kill() **
+
+kills the thread
diff --git a/makefile b/makefile
index 8dc9205..3c5b82f 100644
--- a/makefile
+++ b/makefile
@@ -18,6 +18,11 @@ all: $(TARGET)
debug: CFLAGS += -g
debug: all
+reg:
+ rm src/reg.o
+
+reg: all
+
%.o: %.c
$(CC) -c $< -o $@ $(CFLAGS)
diff --git a/src/thread.c b/src/thread.c
index 25ad500..441793b 100644
--- a/src/thread.c
+++ b/src/thread.c
@@ -1,114 +1,163 @@
-#include "thread.h"
-#include "lua5.4/lauxlib.h"
-#include "lua5.4/lua.h"
-#include "stdint.h"
-#include <stdlib.h>
-#include <unistd.h>
-#include <pthread.h>
-#include "types/str.h"
-#include "util.h"
-
-struct thread_info {
- str* function;
- lua_State* L;
- int return_count;
- pthread_t tid;
- pthread_cond_t cond;
- pthread_mutex_t lock;
-};
-
-#include "io.h"
-
-int l_res(lua_State* L){
- int return_count = lua_gettop(L) - 1;
- lua_pushstring(L, "_");
- lua_gettable(L, 1);
- struct thread_info* info = lua_touserdata(L, -1);
- info->return_count = return_count;
-
- for(int i = info->return_count - 1; i != -1; i--){
- int ot = lua_gettop(L);
-
- lua_pushvalue(L, 2 + i);
- i_dcopy(L, info->L, NULL);
-
- lua_settop(L, ot);
- }
-
- pthread_mutex_unlock(&info->lock);
-
- pthread_exit(NULL);
- p_error("thread did not exit");
-
- return 1;
-}
-
-void* handle_thread(void* _args){
- struct thread_info* args = (struct thread_info*)_args;
- lua_State* L = args->L;
-
- lua_newtable(L);
- int res_idx = lua_gettop(L);
- luaI_tsetcf(L, res_idx, "res", l_res);
- luaI_tsetlud(L, res_idx, "_", args);
-
- luaL_loadbuffer(L, args->function->c, args->function->len, "thread");
- str_free(args->function);
-
- lua_pushvalue(L, res_idx);
- lua_call(L, 1, 0);
-
- pthread_mutex_unlock(&args->lock);
-
- return NULL;
-}
-
-int l_await(lua_State* L){
- lua_pushstring(L, "_");
- lua_gettable(L, 1);
- struct thread_info* info = lua_touserdata(L, -1);
-
- pthread_mutex_lock(&info->lock);
-
- for(int i = 0; i != info->return_count; i++){
- int ot = lua_gettop(info->L);
-
- lua_pushvalue(info->L, ot - info->return_count + i);
- i_dcopy(info->L, L, NULL);
-
- lua_settop(info->L, ot);
- }
-
- return info->return_count;
-}
-
-int l_async(lua_State* oL){
- lua_State* L = luaL_newstate();
-
- luaL_openlibs(L);
-
- lua_getglobal(oL, "_G");
- i_dcopy(oL, L, NULL);
- lua_set_global_table(L);
-
- struct thread_info* args = calloc(1, sizeof * args);
- args->L = L;
- args->cond = (pthread_cond_t)PTHREAD_COND_INITIALIZER;
- args->lock = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER;
- pthread_mutex_lock(&args->lock);
- args->return_count = 0;
-
- args->function = str_init("");
- lua_pushvalue(oL, 1);
- lua_dump(oL, writer, (void*)args->function, 0);
-
- pthread_create(&args->tid, NULL, handle_thread, (void*)args);
- pthread_detach(args->tid);
-
- lua_newtable(oL);
- int res_idx = lua_gettop(oL);
- luaI_tsetcf(oL, res_idx, "await", l_await);
- luaI_tsetlud(oL, res_idx, "_", args);
- lua_pushvalue(oL, res_idx);
- return 1;
-}
+#include "thread.h"
+#include "lua5.4/lauxlib.h"
+#include "lua5.4/lua.h"
+#include "stdint.h"
+#include <stdlib.h>
+#include <unistd.h>
+#include <pthread.h>
+#include "types/str.h"
+#include "util.h"
+
+#include "types/larray.h"
+
+struct thread_info {
+ str* function;
+ lua_State* L;
+ int return_count;
+ pthread_t tid;
+ pthread_cond_t cond;
+ pthread_mutex_t lock;
+};
+
+#include "io.h"
+
+pthread_mutex_t thread_lock_lock = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER;
+larray_t* thread_locks = NULL;
+
+int l_tlock(lua_State* L){
+ int idx = luaL_checkinteger(L, 1);
+
+ pthread_mutex_lock(&thread_lock_lock);
+ pthread_mutex_t mutex;
+ if(thread_locks == NULL) thread_locks = larray_init();
+ int i = 0;
+ if((i = larray_geti(thread_locks, idx)) == -1){
+ pthread_mutex_init(&mutex, NULL);
+ pthread_mutex_lock(&mutex);
+ larray_set(&thread_locks, idx, (void*)mutex);
+ } else {
+ pthread_mutex_t m = (pthread_mutex_t)thread_locks->arr[i].value;
+ pthread_mutex_unlock(&thread_lock_lock);
+ pthread_mutex_lock(&m);
+ pthread_mutex_lock(&thread_lock_lock);
+ thread_locks->arr[i].value = (void*)m;
+
+ }
+
+ pthread_mutex_unlock(&thread_lock_lock);
+ return 0;
+}
+
+int l_tunlock(lua_State* L){
+ int idx = luaL_checkinteger(L, 1);
+
+ pthread_mutex_lock(&thread_lock_lock);
+ int i = 0;
+ if(thread_locks != NULL && (i = larray_geti(thread_locks, idx)) != -1){
+ pthread_mutex_t m = (pthread_mutex_t)thread_locks->arr[i].value;
+ pthread_mutex_unlock(&m);
+ thread_locks->arr[i].value = (void*)m;
+ }
+
+ pthread_mutex_unlock(&thread_lock_lock);
+ return 0;
+}
+
+int l_res(lua_State* L){
+ int return_count = lua_gettop(L) - 1;
+ lua_pushstring(L, "_");
+ lua_gettable(L, 1);
+ struct thread_info* info = lua_touserdata(L, -1);
+ info->return_count = return_count;
+
+ for(int i = info->return_count - 1; i != -1; i--){
+ int ot = lua_gettop(L);
+
+ lua_pushvalue(L, 2 + i);
+ i_dcopy(L, info->L, NULL);
+
+ lua_settop(L, ot);
+ }
+
+ pthread_mutex_unlock(&info->lock);
+
+ pthread_exit(NULL);
+ p_error("thread did not exit");
+
+ return 1;
+}
+
+void* handle_thread(void* _args){
+ struct thread_info* args = (struct thread_info*)_args;
+ lua_State* L = args->L;
+
+ lua_newtable(L);
+ int res_idx = lua_gettop(L);
+ luaI_tsetlud(L, res_idx, "_", args);
+
+ lua_newtable(L);
+ int meta_idx = lua_gettop(L);
+ luaI_tsetcf(L, meta_idx, "__call", l_res);
+ lua_pushvalue(L, meta_idx);
+ lua_setmetatable(L, res_idx);
+
+ luaL_loadbuffer(L, args->function->c, args->function->len, "thread");
+ str_free(args->function);
+
+ lua_pushvalue(L, res_idx);
+ lua_call(L, 1, 0);
+
+ pthread_mutex_unlock(&args->lock);
+
+ return NULL;
+}
+
+int l_await(lua_State* L){
+ lua_pushstring(L, "_");
+ lua_gettable(L, 1);
+ struct thread_info* info = lua_touserdata(L, -1);
+
+ pthread_mutex_lock(&info->lock);
+
+ for(int i = 0; i != info->return_count; i++){
+ int ot = lua_gettop(info->L);
+
+ lua_pushvalue(info->L, ot - info->return_count + i);
+ i_dcopy(info->L, L, NULL);
+
+ lua_settop(info->L, ot);
+ }
+
+ return info->return_count;
+}
+
+int l_async(lua_State* oL){
+ lua_State* L = luaL_newstate();
+
+ luaL_openlibs(L);
+
+ lua_getglobal(oL, "_G");
+ i_dcopy(oL, L, NULL);
+ lua_set_global_table(L);
+
+ struct thread_info* args = calloc(1, sizeof * args);
+ args->L = L;
+ args->cond = (pthread_cond_t)PTHREAD_COND_INITIALIZER;
+ args->lock = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER;
+ pthread_mutex_lock(&args->lock);
+ args->return_count = 0;
+
+ args->function = str_init("");
+ lua_pushvalue(oL, 1);
+ lua_dump(oL, writer, (void*)args->function, 0);
+
+ pthread_create(&args->tid, NULL, handle_thread, (void*)args);
+ pthread_detach(args->tid);
+
+ lua_newtable(oL);
+ int res_idx = lua_gettop(oL);
+ luaI_tsetcf(oL, res_idx, "await", l_await);
+ luaI_tsetlud(oL, res_idx, "_", args);
+ lua_pushvalue(oL, res_idx);
+ return 1;
+}
diff --git a/src/thread.h b/src/thread.h
index d25b448..e9ead6d 100644
--- a/src/thread.h
+++ b/src/thread.h
@@ -1,9 +1,12 @@
-#include "lua.h"
-
-int l_async(lua_State*);
-
-static const luaL_Reg thread_function_list [] = {
- {"async",l_async},
-
- {NULL,NULL}
-};
+#include "lua.h"
+
+int l_async(lua_State*);
+int l_tlock(lua_State*);
+int l_tunlock(lua_State*);
+
+static const luaL_Reg thread_function_list [] = {
+ {"async",l_async},
+ {"lock",l_tlock},
+ {"unlock",l_tunlock},
+ {NULL,NULL}
+};
diff --git a/src/types/larray.c b/src/types/larray.c
new file mode 100644
index 0000000..7a5afbc
--- /dev/null
+++ b/src/types/larray.c
@@ -0,0 +1,79 @@
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#include "larray.h"
+
+#define inc 4
+
+larray_t* larray_initl(int len){
+ larray_t* l = calloc(1, sizeof * l);
+ l->size = len;
+ l->arr = calloc(len, sizeof * l->arr);
+ return l;
+}
+
+larray_t* larray_init(){
+ return larray_initl(inc);
+}
+
+void larray_expand(larray_t** _l){
+ larray_t* l = *_l;
+ larray_t* remade = larray_initl(l->size * 4);
+ for(int i = 0; i != l->size; i++){
+ //what happens if the map_set calls map_regraph??? idk
+ if(l->arr[i].used)
+ larray_set(&remade, l->arr[i].idx, l->arr[i].value);
+ }
+
+ *_l = remade;
+}
+
+void larray_set(larray_t** _l, uint64_t idx, void* value){
+ larray_t* l = *_l;
+
+ if(l->len + 1 >= l->size){
+ expand:
+ larray_expand(&l);
+ }
+
+ uint64_t oind, ind = oind = idx % l->size;
+
+ for(int count = 0; l->arr[ind].used && l->arr[ind].idx != idx; count++){
+ ind++;
+ if(ind >= l->size) ind = 0;
+ if(ind == oind || count > 10) goto expand;
+ }
+
+ l->arr[ind].idx = idx;
+ l->arr[ind].value = value;
+ l->arr[ind].used = 1;
+ l->len++;
+
+ *_l = l;
+}
+
+int larray_geti(larray_t* l, uint64_t idx){
+ uint64_t ind = idx % l->size;
+
+ for(uint64_t initial = ind; ind != initial - 1;){
+ if(!l->arr[ind].used) return -1;
+ //printf("%s\n",M->M[ind].key->c);
+ if(l->arr[ind].idx == idx) return ind;
+ ind++;
+ if(ind >= l->size) ind = 0;
+ }
+ return -1;
+}
+
+void* larray_get(larray_t* l, uint64_t idx){
+ int r = larray_geti(l, idx);
+
+ return r == -1 ? NULL : l->arr[r].value;
+}
+
+void larray_clear(larray_t* l){
+ free(l->arr);
+ free(l);
+}
+
diff --git a/src/types/larray.h b/src/types/larray.h
new file mode 100644
index 0000000..ff67857
--- /dev/null
+++ b/src/types/larray.h
@@ -0,0 +1,21 @@
+#include <stdint.h>
+
+struct larray_item {
+ uint64_t idx;
+ void* value;
+ int used;
+};
+
+typedef struct {
+ struct larray_item* arr;
+ size_t len, size;
+} larray_t;
+
+larray_t* larray_initl(int len);
+larray_t* larray_init();
+void larray_expand(larray_t** _l);
+void larray_set(larray_t** _l, uint64_t idx, void* value);
+int larray_geti(larray_t* l, uint64_t idx);
+void* larray_get(larray_t* l, uint64_t idx);
+void larray_clear(larray_t* l);
+
diff --git a/tests/h.lua b/tests/h.lua
index 1472c89..9cddc29 100644
--- a/tests/h.lua
+++ b/tests/h.lua
@@ -1,18 +1,14 @@
-require "llib"
-
-local thread_a = llib.thread.async(function (res)
- --os.execute("sleep 1")
- --print((_G.ll + "hi"):final())
- res:res(_G.llib.crypto.md5("meow"))
- print("after")
-end)
-
-local thread_b = llib.thread.async(function (res)
- --os.execute("sleep 1")
- --print((_G.ll + "hi"):final())
- res:res(_G.llib.crypto.sha512("meow"))
- print("after")
-end)
-
-print(thread_a:await())
-print(thread_b:await()) \ No newline at end of file
+require "llib"
+
+llib.thread.lock(1)
+
+local thread_a = llib.thread.async(function (res)
+ --os.execute("sleep 1")
+ --print((_G.ll + "hi"):final())
+
+ res(_G.llib.crypto.md5("meow"))
+ print("after")
+end)
+
+print(thread_a:await())
+