fixed WHOHandler.c multithread compatibility
[NeonServV5.git] / src / WHOHandler.c
index 63232f7c7998d0be5451118cecb9cedfb662172b..5ad4ce6f302bf53bb7f5db8e5742700312650242 100644 (file)
@@ -39,13 +39,16 @@ struct WHOQueueEntry {
     struct WHOQueueEntry *next;
     void *callback[MAXCALLBACKS];
     void *data[MAXCALLBACKS];
-    #ifdef HAVE_THREADS
-    unsigned long lock_tid;
-    pthread_mutex_t lock_mutex;
-    int lock_count;
-    #endif
 };
 
+#ifdef HAVE_THREADS
+struct ParseOrder {
+    unsigned long tid;
+    struct ParseOrder *next;
+};
+struct ParseOrder *parse_order = NULL;
+#endif
+
 static int checkWHOID(struct ClientSocket *client, int whoid) {
     struct WHOQueueEntry *entry;
     for(entry = client->whoqueue_first; entry; entry = entry->next) {
@@ -74,11 +77,6 @@ static struct WHOQueueEntry* addWHOQueueEntry(struct ClientSocket *client) {
     }
     entry->next = NULL;
     entry->whoid = whoid;
-    #ifdef HAVE_THREADS
-    entry->lock_tid = 0;
-    THREAD_MUTEX_INIT(entry->lock_mutex);
-    entry->lock_count = 0;
-    #endif
     if(client->whoqueue_last) {
         client->whoqueue_last->next = entry;
     } else {
@@ -106,15 +104,6 @@ static struct WHOQueueEntry* getNextWHOQueueEntry(struct ClientSocket *client, i
         if(entry == client->whoqueue_last) {
             client->whoqueue_last = NULL;
         }
-        #ifdef HAVE_THREADS
-        entry->lock_tid = -1;
-        if(entry->lock_count) {
-            int i;
-            for(i = 0; i < entry->lock_count; i++) {
-                DESYNCHRONIZE(entry->lock_mutex); //unlock ALL
-            }
-        }
-        #endif
     }
     DESYNCHRONIZE(whohandler_sync);
     return entry;
@@ -126,15 +115,6 @@ void clear_whoqueue(struct ClientSocket *client) {
     struct WHOQueueEntry *entry, *next;
     for(entry = client->whoqueue_first; entry; entry = next) {
         next = entry->next;
-        #ifdef HAVE_THREADS
-        entry->lock_tid = -1;
-        if(entry->lock_count) {
-            int i;
-            for(i = 0; i < entry->lock_count; i++) {
-                DESYNCHRONIZE(entry->lock_mutex); //unlock ALL
-            }
-        }
-        #endif
         free(entry);
     }
     client->whoqueue_last = NULL;
@@ -143,15 +123,36 @@ void clear_whoqueue(struct ClientSocket *client) {
 }
 
 #if HAVE_THREADS
-void whohandler_end_of_recv(struct ClientSocket *client) {
+void whohandler_start_of_recv(struct ClientSocket *client, unsigned long tid) {
     SYNCHRONIZE(whohandler_sync);
-    unsigned long tid = syscall(SYS_gettid);
-    struct WHOQueueEntry *entry;
-    for(entry = client->whoqueue_first; entry; entry = entry->next) {
-        if(entry->lock_tid == tid) {
-            entry->lock_tid = 0;
-            DESYNCHRONIZE(entry->lock_mutex);
-        }
+    struct ParseOrder *entry, *last;
+    for(last = parse_order; last; last = last->next) {
+        if(last->next == NULL)
+            break;
+    }
+    entry = malloc(sizeof(*entry));
+    entry->tid = tid;
+    entry->next = NULL;
+    if(last)
+        last->next = entry;
+    else
+        parse_order = entry;
+    DESYNCHRONIZE(whohandler_sync);
+}
+
+void whohandler_end_of_recv(struct ClientSocket *client, unsigned long tid) {
+    SYNCHRONIZE(whohandler_sync);
+    struct ParseOrder *entry, *last = NULL;
+    for(entry = parse_order; entry; entry = entry->next) {
+        if(entry->tid == tid) {
+            if(last)
+                last->next = entry->next;
+            else
+                parse_order = entry->next;
+            free(entry);
+            break;
+        } else
+            last = entry;
     }
     DESYNCHRONIZE(whohandler_sync);
 }
@@ -286,13 +287,8 @@ static void _recv_whohandler_354(struct ClientSocket *client, char **argv, unsig
     if(entry == NULL) return;
     #ifdef HAVE_THREADS
     unsigned long tid = syscall(SYS_gettid);
-    if(entry->lock_tid != tid) {
-        entry->lock_count++;
-        SYNCHRONIZE(entry->lock_mutex);
-        if(entry->lock_tid == -1) {
-            return; //entry has been destroyed
-        }
-        entry->lock_tid = tid;
+    while(parse_order->tid != tid) {
+        usleep(5000); //5ms
     }
     #endif
     if(entry->type & WHOQUEUETYPE_USERLIST) {
@@ -385,13 +381,8 @@ static void _recv_whohandler_315(struct ClientSocket *client, char **argv, unsig
     if(entry == NULL) return;
     #ifdef HAVE_THREADS
     unsigned long tid = syscall(SYS_gettid);
-    if(entry->lock_tid != tid) {
-        entry->lock_count++;
-        SYNCHRONIZE(entry->lock_mutex);
-        if(entry->lock_tid == -1) {
-            return; //entry has been destroyed
-        }
-        entry->lock_tid = tid;
+    while(parse_order->tid != tid) {
+        usleep(5000); //5ms
     }
     #endif
     getNextWHOQueueEntry(client, type, 1);