diff options
| author | ame <[email protected]> | 2025-06-20 20:34:18 -0500 |
|---|---|---|
| committer | ame <[email protected]> | 2025-06-20 20:34:18 -0500 |
| commit | 76495ea9809c256ebc216e7aa2954c4e0592fd1d (patch) | |
| tree | 4f6b08a23632659199ebcb16b198ecf0ede1f5d7 | |
| parent | e058a29d70dd299b7fc2a84cae5824fd03fbef84 (diff) | |
thread.mutex
| -rw-r--r-- | library/lullaby/thread.lua | 22 | ||||
| -rw-r--r-- | src/thread.c | 59 | ||||
| -rw-r--r-- | src/thread.h | 2 | ||||
| -rw-r--r-- | src/util.h | 2 | ||||
| -rw-r--r-- | tests/mutex.lua | 23 |
5 files changed, 107 insertions, 1 deletions
diff --git a/library/lullaby/thread.lua b/library/lullaby/thread.lua index 1b0e89d..d4efe2d 100644 --- a/library/lullaby/thread.lua +++ b/library/lullaby/thread.lua @@ -64,4 +64,26 @@ function thread.unlock(tid) end ---@deprecated function thread.testcopy() end +---@class mutex-table +local mutex = {} + +---locks the mutex +---@param T mutex-table +---@return nil +function mutex.lock(T) end + +---unlocks the mutex +---@param T mutex-table +---@return nil +function mutex.unlock(T) end + +---frees the mutex, automatically called by __gc +---@param T mutex-table +---@return nil +function mutex.free(T) end + +---returns a mutex object, useful for solving race conditions in multi-threaded environments +---@return mutex-table +function thread.mutex() end + return thread diff --git a/src/thread.c b/src/thread.c index a5eb892..6d4540d 100644 --- a/src/thread.c +++ b/src/thread.c @@ -85,6 +85,65 @@ int l_tunlock(lua_State* L){ return 0;
}
+int _mutex_lock(lua_State* L){
+ lua_pushstring(L, "_");
+ lua_gettable(L, 1);
+ pthread_mutex_t *lock = lua_touserdata(L, -1);
+
+ pthread_mutex_lock(lock);
+
+ return 0;
+}
+
+int _mutex_unlock(lua_State* L){
+ lua_pushstring(L, "_");
+ lua_gettable(L, 1);
+ pthread_mutex_t *lock = lua_touserdata(L, -1);
+
+ pthread_mutex_unlock(lock);
+
+ return 0;
+}
+
+int _mutex_free(lua_State* L){
+ lua_pushstring(L, "_");
+ lua_gettable(L, 1);
+ pthread_mutex_t *lock = lua_touserdata(L, -1);
+
+ if(lock != NULL){
+ pthread_mutex_destroy(&*lock);
+ free(lock);
+
+ luaI_tsetlud(L, 1, "_", NULL);
+ }
+
+ return 0;
+}
+
+int l_mutex(lua_State* L){
+ pthread_mutex_t *lock = malloc(sizeof * lock);
+
+ if(pthread_mutex_init(&*lock, NULL) != 0)
+ luaI_error(L, -1, "mutex init failed");
+
+ lua_newtable(L);
+ int idx = lua_gettop(L);
+ luaI_tsetlud(L, idx, "_", lock);
+ luaI_tsetcf(L, idx, "lock", _mutex_lock);
+ luaI_tsetcf(L, idx, "unlock", _mutex_unlock);
+ luaI_tsetcf(L, idx, "free", _mutex_free);
+
+ lua_newtable(L);
+ int midx = lua_gettop(L);
+ luaI_tsetcf(L, midx, "__gc", _mutex_free);
+
+ lua_pushvalue(L, midx);
+ lua_setmetatable(L, idx);
+ lua_pushvalue(L, idx);
+
+ return 1;
+}
+
int l_res(lua_State* L){
int return_count = lua_gettop(L) - 1;
lua_pushstring(L, "_");
diff --git a/src/thread.h b/src/thread.h index be9cadd..0b3a27d 100644 --- a/src/thread.h +++ b/src/thread.h @@ -6,6 +6,7 @@ int l_tlock(lua_State*); int l_tunlock(lua_State*);
int l_buffer(lua_State*);
int l_testcopy(lua_State*);
+int l_mutex(lua_State*);
void lib_thread_clean();
@@ -17,6 +18,7 @@ static const luaL_Reg thread_function_list [] = { {"unlock",l_tunlock},
{"buffer",l_buffer},
{"testcopy",l_testcopy},
+ {"mutex", l_mutex},
{NULL,NULL}
};
@@ -38,4 +38,4 @@ void _p_fatal(const char*, int, const char*, const char*); void p_error(const char*); char* strnstr(const char*, const char*, size_t); -#endif //__UTIL_H
\ No newline at end of file +#endif //__UTIL_H diff --git a/tests/mutex.lua b/tests/mutex.lua new file mode 100644 index 0000000..2e5ce4b --- /dev/null +++ b/tests/mutex.lua @@ -0,0 +1,23 @@ +local llby = require"lullaby" + + +local mutex = llby.thread.mutex() + +llby.io.print_meta = 1 +llby.io.pprint(mutex) + +local th = llby.thread.async(function(res) + mutex:lock() + os.execute("sleep 5") + print("thread") + mutex:unlock() +end) + +os.execute("sleep 1") +mutex:lock() +print("main") +mutex:unlock() +mutex:free() +-- +th:await() + |
