Move SDLNet_TCP_Send to its own thread qmlfrontend
authorunc0rr
Mon, 18 May 2015 00:07:52 +0300 (2015-05-17)
branchqmlfrontend
changeset 10935 3a65fcd7c335
parent 10933 f1da4126a61c
child 10949 6a1f5f452460
Move SDLNet_TCP_Send to its own thread
hedgewars/uFLIPC.pas
hedgewars/uFLNet.pas
--- a/hedgewars/uFLIPC.pas	Sun May 17 00:14:30 2015 +0300
+++ b/hedgewars/uFLIPC.pas	Mon May 18 00:07:52 2015 +0300
@@ -2,9 +2,9 @@
 interface
 uses SDLh, uFLTypes;
 
-var msgFrontend, msgEngine: TIPCMessage;
-    mutFrontend, mutEngine: PSDL_mutex;
-    condFrontend, condEngine: PSDL_cond;
+var msgFrontend, msgEngine, msgNet: TIPCMessage;
+    mutFrontend, mutEngine, mutNet: PSDL_mutex;
+    condFrontend, condEngine, condNet: PSDL_cond;
 
 procedure initIPC;
 procedure freeIPC;
@@ -14,18 +14,25 @@
 //function  ipcReadFromEngine: shortstring;
 //function  ipcCheckFromEngine: boolean;
 
+procedure ipcToNet(s: shortstring);
+procedure ipcToNetRaw(p: pointer; len: Longword);
+
 procedure ipcToFrontend(s: shortstring);
 procedure ipcToFrontendRaw(p: pointer; len: Longword);
 function ipcReadFromFrontend: shortstring;
 function ipcCheckFromFrontend: boolean;
 
 procedure registerIPCCallback(p: pointer; f: TIPCCallback);
+procedure registerNetCallback(p: pointer; f: TIPCCallback);
 
 implementation
 
-var callbackPointer: pointer;
-    callbackFunction: TIPCCallback;
-    callbackListenerThread: PSDL_Thread;
+var callbackPointerF: pointer;
+    callbackFunctionF: TIPCCallback;
+    callbackListenerThreadF: PSDL_Thread;
+    callbackPointerN: pointer;
+    callbackFunctionN: TIPCCallback;
+    callbackListenerThreadN: PSDL_Thread;
 
 procedure ipcSend(var s: TIPCMessage; var msg: TIPCMessage; mut: PSDL_mutex; cond: PSDL_cond);
 begin
@@ -86,6 +93,14 @@
     ipcSend(msg, msgFrontend, mutFrontend, condFrontend)
 end;
 
+procedure ipcToNet(s: shortstring);
+var msg: TIPCMessage;
+begin
+    msg.str:= s;
+    msg.buf:= nil;
+    ipcSend(msg, msgNet, mutNet, condNet)
+end;
+
 procedure ipcToEngineRaw(p: pointer; len: Longword);
 var msg: TIPCMessage;
 begin
@@ -106,6 +121,16 @@
     ipcSend(msg, msgFrontend, mutFrontend, condFrontend)
 end;
 
+procedure ipcToNetRaw(p: pointer; len: Longword);
+var msg: TIPCMessage;
+begin
+    msg.str[0]:= #0;
+    msg.len:= len;
+    msg.buf:= GetMem(len);
+    Move(p^, msg.buf^, len);
+    ipcSend(msg, msgNet, mutNet, condNet)
+end;
+
 function ipcReadFromEngine: TIPCMessage;
 begin
     ipcReadFromEngine:= ipcRead(msgFrontend, mutFrontend, condFrontend)
@@ -116,6 +141,11 @@
     ipcReadFromFrontend:= ipcRead(msgEngine, mutEngine, condEngine).str
 end;
 
+function ipcReadToNet: TIPCMessage;
+begin
+    ipcReadToNet:= ipcRead(msgNet, mutNet, condNet)
+end;
+
 function ipcCheckFromEngine: boolean;
 begin
     ipcCheckFromEngine:= ipcCheck(msgFrontend, mutFrontend)
@@ -133,10 +163,26 @@
     repeat
         msg:= ipcReadFromEngine();
         if msg.buf = nil then
-            callbackFunction(callbackPointer, @msg.str[1], byte(msg.str[0]))
+            callbackFunctionF(callbackPointerF, @msg.str[1], byte(msg.str[0]))
         else
         begin
-            callbackFunction(callbackPointer, msg.buf, msg.len);
+            callbackFunctionF(callbackPointerF, msg.buf, msg.len);
+            FreeMem(msg.buf, msg.len)
+        end
+    until false
+end;
+
+function  netListener(p: pointer): Longint; cdecl; export;
+var msg: TIPCMessage;
+begin
+    netListener:= 0;
+    repeat
+        msg:= ipcReadToNet();
+        if msg.buf = nil then
+            callbackFunctionN(callbackPointerN, @msg.str[1], byte(msg.str[0]))
+        else
+        begin
+            callbackFunctionN(callbackPointerN, msg.buf, msg.len);
             FreeMem(msg.buf, msg.len)
         end
     until false
@@ -144,9 +190,16 @@
 
 procedure registerIPCCallback(p: pointer; f: TIPCCallback);
 begin
-    callbackPointer:= p;
-    callbackFunction:= f;
-    callbackListenerThread:= SDL_CreateThread(@engineListener{$IFDEF SDL2}, 'engineListener'{$ENDIF}, nil);
+    callbackPointerF:= p;
+    callbackFunctionF:= f;
+    callbackListenerThreadF:= SDL_CreateThread(@engineListener{$IFDEF SDL2}, 'engineListener'{$ENDIF}, nil);
+end;
+
+procedure registerNetCallback(p: pointer; f: TIPCCallback);
+begin
+    callbackPointerN:= p;
+    callbackFunctionN:= f;
+    callbackListenerThreadN:= SDL_CreateThread(@netListener{$IFDEF SDL2}, 'netListener'{$ENDIF}, nil);
 end;
 
 procedure initIPC;
@@ -155,23 +208,30 @@
     msgFrontend.buf:= nil;
     msgEngine.str:= '';
     msgEngine.buf:= nil;
+    msgNet.str:= '';
+    msgNet.buf:= nil;
 
-    callbackPointer:= nil;
-    callbackListenerThread:= nil;
+    callbackPointerF:= nil;
+    callbackListenerThreadF:= nil;
 
     mutFrontend:= SDL_CreateMutex;
     mutEngine:= SDL_CreateMutex;
+    mutNet:= SDL_CreateMutex;
     condFrontend:= SDL_CreateCond;
     condEngine:= SDL_CreateCond;
+    condNet:= SDL_CreateCond;
 end;
 
 procedure freeIPC;
 begin
-    SDL_KillThread(callbackListenerThread);
+    SDL_KillThread(callbackListenerThreadF);
+    SDL_KillThread(callbackListenerThreadN);
     SDL_DestroyMutex(mutFrontend);
     SDL_DestroyMutex(mutEngine);
+    SDL_DestroyMutex(mutNet);
     SDL_DestroyCond(condFrontend);
     SDL_DestroyCond(condEngine);
+    SDL_DestroyCond(condNet);
 end;
 
 end.
--- a/hedgewars/uFLNet.pas	Sun May 17 00:14:30 2015 +0300
+++ b/hedgewars/uFLNet.pas	Mon May 18 00:07:52 2015 +0300
@@ -7,9 +7,9 @@
 procedure freeModule;
 
 implementation
-uses SDLh;
+uses SDLh, uFLIPC;
 
-const endCmd: array[0..1] of char = (#10, #10);
+const endCmd: string = #10 + #10;
 
 function getNextChar: char; forward;
 function getCurrChar: char; forward;
@@ -256,8 +256,13 @@
 procedure sendNet(s: shortstring);
 begin
     writeln('[NET] Send: ', s);
-    SDLNet_TCP_Send(sock, @s[1], byte(s[0]));
-    SDLNet_TCP_Send(sock, @endCmd, 2);
+    ipcToNet(s + endCmd);
+end;
+
+procedure netSendCallback(p: pointer; msg: PChar; len: Longword);
+begin
+    // W A R N I N G: totally thread-unsafe due to use of sock variable
+    SDLNet_TCP_Send(sock, msg, len);
 end;
 
 procedure connectOfficialServer;
@@ -279,6 +284,8 @@
     sock:= nil;
 
     SDLNet_Init;
+
+    registerNetCallback(nil, @netSendCallback);
 end;
 
 procedure freeModule;