|
@@ -15,6 +15,7 @@
|
|
|
*/
|
|
|
|
|
|
#include "../util/darray.h"
|
|
|
+#include "../util/threading.h"
|
|
|
|
|
|
#include "decl.h"
|
|
|
#include "proc.h"
|
|
@@ -32,24 +33,50 @@ static inline void proc_info_free(struct proc_info *pi)
|
|
|
|
|
|
struct proc_handler {
|
|
|
/* TODO: replace with hash table lookup? */
|
|
|
+ pthread_mutex_t mutex;
|
|
|
DARRAY(struct proc_info) procs;
|
|
|
};
|
|
|
|
|
|
+static struct proc_info *getproc(proc_handler_t *handler, const char *name)
|
|
|
+{
|
|
|
+ for (size_t i = 0; i < handler->procs.num; i++) {
|
|
|
+ struct proc_info *info = handler->procs.array + i;
|
|
|
+
|
|
|
+ if (strcmp(info->func.name, name) == 0) {
|
|
|
+ return info;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return NULL;
|
|
|
+}
|
|
|
+
|
|
|
+/* ------------------------------------------------------------------------- */
|
|
|
+
|
|
|
proc_handler_t *proc_handler_create(void)
|
|
|
{
|
|
|
struct proc_handler *handler = bmalloc(sizeof(struct proc_handler));
|
|
|
+
|
|
|
+ if (pthread_mutex_init_recursive(&handler->mutex) != 0) {
|
|
|
+ blog(LOG_ERROR, "Couldn't create proc_handler mutex");
|
|
|
+ bfree(handler);
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+
|
|
|
da_init(handler->procs);
|
|
|
return handler;
|
|
|
}
|
|
|
|
|
|
void proc_handler_destroy(proc_handler_t *handler)
|
|
|
{
|
|
|
- if (handler) {
|
|
|
- for (size_t i = 0; i < handler->procs.num; i++)
|
|
|
- proc_info_free(handler->procs.array + i);
|
|
|
- da_free(handler->procs);
|
|
|
- bfree(handler);
|
|
|
- }
|
|
|
+ if (!handler)
|
|
|
+ return;
|
|
|
+
|
|
|
+ for (size_t i = 0; i < handler->procs.num; i++)
|
|
|
+ proc_info_free(handler->procs.array + i);
|
|
|
+
|
|
|
+ da_free(handler->procs);
|
|
|
+ pthread_mutex_destroy(&handler->mutex);
|
|
|
+ bfree(handler);
|
|
|
}
|
|
|
|
|
|
void proc_handler_add(proc_handler_t *handler, const char *decl_string,
|
|
@@ -70,7 +97,18 @@ void proc_handler_add(proc_handler_t *handler, const char *decl_string,
|
|
|
pi.callback = proc;
|
|
|
pi.data = data;
|
|
|
|
|
|
- da_push_back(handler->procs, &pi);
|
|
|
+ pthread_mutex_lock(&handler->mutex);
|
|
|
+
|
|
|
+ struct proc_info *existing = getproc(handler, pi.func.name);
|
|
|
+ if (existing) {
|
|
|
+ blog(LOG_WARNING, "Procedure '%s' already exists",
|
|
|
+ pi.func.name);
|
|
|
+ proc_info_free(&pi);
|
|
|
+ } else {
|
|
|
+ da_push_back(handler->procs, &pi);
|
|
|
+ }
|
|
|
+
|
|
|
+ pthread_mutex_unlock(&handler->mutex);
|
|
|
}
|
|
|
|
|
|
bool proc_handler_call(proc_handler_t *handler, const char *name,
|
|
@@ -79,14 +117,16 @@ bool proc_handler_call(proc_handler_t *handler, const char *name,
|
|
|
if (!handler)
|
|
|
return false;
|
|
|
|
|
|
- for (size_t i = 0; i < handler->procs.num; i++) {
|
|
|
- struct proc_info *info = handler->procs.array + i;
|
|
|
+ pthread_mutex_lock(&handler->mutex);
|
|
|
+ struct proc_info *info = getproc(handler, name);
|
|
|
+ struct proc_info info_copy;
|
|
|
+ if (info)
|
|
|
+ info_copy = *info;
|
|
|
+ pthread_mutex_unlock(&handler->mutex);
|
|
|
|
|
|
- if (strcmp(info->func.name, name) == 0) {
|
|
|
- info->callback(info->data, params);
|
|
|
- return true;
|
|
|
- }
|
|
|
- }
|
|
|
+ if (!info)
|
|
|
+ return false;
|
|
|
|
|
|
- return false;
|
|
|
+ info_copy.callback(info_copy.data, params);
|
|
|
+ return true;
|
|
|
}
|