hedgewars/uFLIPC.pas
branchqmlfrontend
changeset 11455 0c75fa9ce340
parent 11423 091149424aa4
child 11456 6e9b12864856
equal deleted inserted replaced
11454:2bf0491d5e88 11455:0c75fa9ce340
     1 unit uFLIPC;
     1 unit uFLIPC;
     2 interface
     2 interface
     3 uses SDLh, uFLTypes;
     3 uses SDLh, uFLTypes;
     4 
       
     5 var msgFrontend, msgEngine, msgNet: TIPCMessage;
       
     6     mutFrontend, mutEngine, mutNet: PSDL_mutex;
       
     7     condFrontend, condEngine, condNet: PSDL_cond;
       
     8 
     4 
     9 procedure initIPC;
     5 procedure initIPC;
    10 procedure freeIPC;
     6 procedure freeIPC;
    11 
     7 
    12 procedure ipcToEngine(s: shortstring);
     8 procedure ipcToEngine(s: shortstring);
    31     callbackFunctionF: TIPCCallback;
    27     callbackFunctionF: TIPCCallback;
    32     callbackListenerThreadF: PSDL_Thread;
    28     callbackListenerThreadF: PSDL_Thread;
    33     callbackPointerN: pointer;
    29     callbackPointerN: pointer;
    34     callbackFunctionN: TIPCCallback;
    30     callbackFunctionN: TIPCCallback;
    35     callbackListenerThreadN: PSDL_Thread;
    31     callbackListenerThreadN: PSDL_Thread;
    36 
    32     queueFrontend, queueEngine, queueNet: PIPCQueue;
    37 procedure ipcSend(var s: TIPCMessage; var msg: TIPCMessage; mut: PSDL_mutex; cond: PSDL_cond);
    33 
    38 begin
    34 procedure ipcSend(var s: TIPCMessage; queue: PIPCQueue);
    39     SDL_LockMutex(mut);
    35 var pmsg: PIPCMessage;
    40 
    36 begin
    41     while (msg.str[0] > #0) or (msg.buf <> nil) do
    37     SDL_LockMutex(queue^.mut);
    42         SDL_CondWait(cond, mut);
    38 
    43 
    39     s.next:= nil;
    44     msg:= s;
    40 
    45     SDL_CondSignal(cond);
    41     if (queue^.msg.next = nil) and (queue^.msg.str[0] = #0) and (queue^.msg.buf = nil) then
    46     SDL_UnlockMutex(mut);
       
    47 end;
       
    48 
       
    49 function ipcRead(var msg: TIPCMessage; mut: PSDL_mutex; cond: PSDL_cond): TIPCMessage;
       
    50 var tmp: pointer;
       
    51 begin
       
    52     SDL_LockMutex(mut);
       
    53     while (msg.str[0] = #0) and (msg.buf = nil) do
       
    54         SDL_CondWait(cond, mut);
       
    55 
       
    56     if msg.buf <> nil then 
       
    57 // FIXME is this copying really needed, the buffer is in another thread already anyway?
       
    58     begin
    42     begin
    59         tmp:= msg.buf;
    43         queue^.msg:= s;
    60         msg.buf:= GetMem(msg.len);
    44     end else
    61         Move(tmp^, msg.buf^, msg.len);
    45     begin
    62         FreeMem(tmp, msg.len)
    46         new(pmsg);
       
    47         pmsg^:= s;
       
    48         queue^.last^.next:= pmsg;
       
    49         queue^.last:= pmsg;
    63     end;
    50     end;
    64 
    51     SDL_CondSignal(queue^.cond);
    65     ipcRead:= msg;
    52     SDL_UnlockMutex(queue^.mut);
    66 
    53 end;
    67     msg.str[0]:= #0;
    54 
    68     msg.buf:= nil;
    55 function ipcRead(queue: PIPCQueue): TIPCMessage;
    69 
    56 var pmsg: PIPCMessage;
    70     SDL_CondSignal(cond);
    57 begin
    71     SDL_UnlockMutex(mut)
    58     SDL_LockMutex(queue^.mut);
    72 end;
    59     while (queue^.msg.str[0] = #0) and (queue^.msg.buf = nil) and (queue^.msg.next = nil) do
    73 
    60         SDL_CondWait(queue^.cond, queue^.mut);
    74 function ipcCheck(var msg: TIPCMessage; mut: PSDL_mutex): boolean;
    61 
    75 begin
    62     if (queue^.msg.str[0] <> #0) or (queue^.msg.buf <> nil) then
    76     SDL_LockMutex(mut);
    63         begin
    77     ipcCheck:= (msg.str[0] > #0) or (msg.buf <> nil);
    64             ipcRead:= queue^.msg;
    78     SDL_UnlockMutex(mut)
    65             queue^.msg.str[0]:= #0;
       
    66             queue^.msg.buf:= nil;
       
    67         end else
       
    68         begin
       
    69             pmsg:= queue^.msg.next;
       
    70             ipcRead:= pmsg^;
       
    71             queue^.msg.next:= pmsg^.next;
       
    72             if queue^.msg.next = nil then queue^.last:= @queue^.msg;
       
    73             dispose(pmsg)
       
    74         end;
       
    75 
       
    76     SDL_UnlockMutex(queue^.mut)
       
    77 end;
       
    78 
       
    79 function ipcCheck(queue: PIPCQueue): boolean;
       
    80 begin
       
    81     SDL_LockMutex(queue^.mut);
       
    82     ipcCheck:= (queue^.msg.str[0] > #0) or (queue^.msg.buf <> nil) or (queue^.msg.next <> nil);
       
    83     SDL_UnlockMutex(queue^.mut)
    79 end;
    84 end;
    80 
    85 
    81 procedure ipcToEngine(s: shortstring);
    86 procedure ipcToEngine(s: shortstring);
    82 var msg: TIPCMessage;
    87 var msg: TIPCMessage;
    83 begin
    88 begin
    84     msg.str:= s;
    89     msg.str:= s;
    85     msg.buf:= nil;
    90     msg.buf:= nil;
    86     ipcSend(msg, msgEngine, mutEngine, condEngine)
    91     ipcSend(msg, queueEngine)
    87 end;
    92 end;
    88 
    93 
    89 procedure ipcToFrontend(s: shortstring);
    94 procedure ipcToFrontend(s: shortstring);
    90 var msg: TIPCMessage;
    95 var msg: TIPCMessage;
    91 begin
    96 begin
    92     msg.str:= s;
    97     msg.str:= s;
    93     msg.buf:= nil;
    98     msg.buf:= nil;
    94     ipcSend(msg, msgFrontend, mutFrontend, condFrontend)
    99     ipcSend(msg, queueFrontend)
    95 end;
   100 end;
    96 
   101 
    97 procedure ipcToNet(s: shortstring);
   102 procedure ipcToNet(s: shortstring);
    98 var msg: TIPCMessage;
   103 var msg: TIPCMessage;
    99 begin
   104 begin
   100     msg.str:= s;
   105     msg.str:= s;
   101     msg.buf:= nil;
   106     msg.buf:= nil;
   102     ipcSend(msg, msgNet, mutNet, condNet)
   107     ipcSend(msg, queueNet)
   103 end;
   108 end;
   104 
   109 
   105 procedure ipcToEngineRaw(p: pointer; len: Longword);
   110 procedure ipcToEngineRaw(p: pointer; len: Longword);
   106 var msg: TIPCMessage;
   111 var msg: TIPCMessage;
   107 begin
   112 begin
   108     msg.str[0]:= #0;
   113     msg.str[0]:= #0;
   109     msg.len:= len;
   114     msg.len:= len;
   110     msg.buf:= GetMem(len);
   115     msg.buf:= GetMem(len);
   111     Move(p^, msg.buf^, len);
   116     Move(p^, msg.buf^, len);
   112     ipcSend(msg, msgEngine, mutEngine, condEngine)
   117     ipcSend(msg, queueEngine)
   113 end;
   118 end;
   114 
   119 
   115 procedure ipcToFrontendRaw(p: pointer; len: Longword);
   120 procedure ipcToFrontendRaw(p: pointer; len: Longword);
   116 var msg: TIPCMessage;
   121 var msg: TIPCMessage;
   117 begin
   122 begin
   118     msg.str[0]:= #0;
   123     msg.str[0]:= #0;
   119     msg.len:= len;
   124     msg.len:= len;
   120     msg.buf:= GetMem(len);
   125     msg.buf:= GetMem(len);
   121     Move(p^, msg.buf^, len);
   126     Move(p^, msg.buf^, len);
   122     ipcSend(msg, msgFrontend, mutFrontend, condFrontend)
   127     ipcSend(msg, queueFrontend)
   123 end;
   128 end;
   124 
   129 
   125 procedure ipcToNetRaw(p: pointer; len: Longword);
   130 procedure ipcToNetRaw(p: pointer; len: Longword);
   126 var msg: TIPCMessage;
   131 var msg: TIPCMessage;
   127 begin
   132 begin
   128     msg.str[0]:= #0;
   133     msg.str[0]:= #0;
   129     msg.len:= len;
   134     msg.len:= len;
   130     msg.buf:= GetMem(len);
   135     msg.buf:= GetMem(len);
   131     Move(p^, msg.buf^, len);
   136     Move(p^, msg.buf^, len);
   132     ipcSend(msg, msgNet, mutNet, condNet)
   137     ipcSend(msg, queueNet)
   133 end;
   138 end;
   134 
   139 
   135 function ipcReadFromEngine: TIPCMessage;
   140 function ipcReadFromEngine: TIPCMessage;
   136 begin
   141 begin
   137     ipcReadFromEngine:= ipcRead(msgFrontend, mutFrontend, condFrontend)
   142     ipcReadFromEngine:= ipcRead(queueFrontend)
   138 end;
   143 end;
   139 
   144 
   140 function ipcReadFromFrontend: shortstring;
   145 function ipcReadFromFrontend: shortstring;
   141 begin
   146 begin
   142     ipcReadFromFrontend:= ipcRead(msgEngine, mutEngine, condEngine).str
   147     ipcReadFromFrontend:= ipcRead(queueEngine).str
   143 end;
   148 end;
   144 
   149 
   145 function ipcReadToNet: TIPCMessage;
   150 function ipcReadToNet: TIPCMessage;
   146 begin
   151 begin
   147     ipcReadToNet:= ipcRead(msgNet, mutNet, condNet)
   152     ipcReadToNet:= ipcRead(queueNet)
   148 end;
   153 end;
   149 
   154 
   150 function ipcCheckFromEngine: boolean;
   155 function ipcCheckFromEngine: boolean;
   151 begin
   156 begin
   152     ipcCheckFromEngine:= ipcCheck(msgFrontend, mutFrontend)
   157     ipcCheckFromEngine:= ipcCheck(queueFrontend)
   153 end;
   158 end;
   154 
   159 
   155 function ipcCheckFromFrontend: boolean;
   160 function ipcCheckFromFrontend: boolean;
   156 begin
   161 begin
   157     ipcCheckFromFrontend:= ipcCheck(msgEngine, mutEngine)
   162     ipcCheckFromFrontend:= ipcCheck(queueEngine)
   158 end;
   163 end;
   159 
   164 
   160 function  engineListener(p: pointer): Longint; cdecl; export;
   165 function  engineListener(p: pointer): Longint; cdecl; export;
   161 var msg: TIPCMessage;
   166 var msg: TIPCMessage;
   162 begin
   167 begin
   201     callbackPointerN:= p;
   206     callbackPointerN:= p;
   202     callbackFunctionN:= f;
   207     callbackFunctionN:= f;
   203     callbackListenerThreadN:= SDL_CreateThread(@netListener, 'netListener', nil);
   208     callbackListenerThreadN:= SDL_CreateThread(@netListener, 'netListener', nil);
   204 end;
   209 end;
   205 
   210 
       
   211 function createQueue: PIPCQueue;
       
   212 var q: PIPCQueue;
       
   213 begin
       
   214     new(q);
       
   215     q^.msg.str:= '';
       
   216     q^.msg.buf:= nil;
       
   217     q^.mut:= SDL_CreateMutex;
       
   218     q^.cond:= SDL_CreateCond;
       
   219     q^.msg.next:= nil;
       
   220     q^.last:= @q^.msg;
       
   221     createQueue:= q
       
   222 end;
       
   223 
       
   224 procedure destroyQueue(queue: PIPCQueue);
       
   225 begin
       
   226     SDL_DestroyCond(queue^.cond);
       
   227     SDL_DestroyMutex(queue^.mut);
       
   228     dispose(queue);
       
   229 end;
       
   230 
   206 procedure initIPC;
   231 procedure initIPC;
   207 begin
   232 begin
   208     msgFrontend.str:= '';
   233     queueFrontend:= createQueue;
   209     msgFrontend.buf:= nil;
   234     queueEngine:= createQueue;
   210     msgEngine.str:= '';
   235     queueNet:= createQueue;
   211     msgEngine.buf:= nil;
       
   212     msgNet.str:= '';
       
   213     msgNet.buf:= nil;
       
   214 
   236 
   215     callbackPointerF:= nil;
   237     callbackPointerF:= nil;
   216     callbackListenerThreadF:= nil;
   238     callbackListenerThreadF:= nil;
   217 
       
   218     mutFrontend:= SDL_CreateMutex;
       
   219     mutEngine:= SDL_CreateMutex;
       
   220     mutNet:= SDL_CreateMutex;
       
   221     condFrontend:= SDL_CreateCond;
       
   222     condEngine:= SDL_CreateCond;
       
   223     condNet:= SDL_CreateCond;
       
   224 end;
   239 end;
   225 
   240 
   226 procedure freeIPC;
   241 procedure freeIPC;
   227 begin
   242 begin
   228     //FIXME SDL_KillThread(callbackListenerThreadF);
   243     //FIXME SDL_KillThread(callbackListenerThreadF);
   229     //FIXME SDL_KillThread(callbackListenerThreadN);
   244     //FIXME SDL_KillThread(callbackListenerThreadN);
   230     SDL_DestroyMutex(mutFrontend);
   245     destroyQueue(queueFrontend);
   231     SDL_DestroyMutex(mutEngine);
   246     destroyQueue(queueEngine);
   232     SDL_DestroyMutex(mutNet);
   247     destroyQueue(queueNet);
   233     SDL_DestroyCond(condFrontend);
       
   234     SDL_DestroyCond(condEngine);
       
   235     SDL_DestroyCond(condNet);
       
   236 end;
   248 end;
   237 
   249 
   238 end.
   250 end.