Re: [fpc-devel] simpleipc issues
On 11.11.2015 17:47, Michael Van Canneyt wrote: I have several remarks: a) Your TBaseSingleInstance class contains too many methods. It assumes you are using advancedipc. I refactored TBaseSingleInstance so that it doesn't depend on advancedipc. I suggest refactoring such a way that advancedipc is in the implementation section of the class. This is unfortunately not possible now because there are no interfaces (nor abstract classes) for TIPCServer and TIPCClient. IMO this is not a problem, if you don't want singleinstance.pp to be dependent on advancedipc.pp at all, TAdvancedSingleInstance can be easily moved into another unit - e.g. "advancedsingleinstance.pp". CustApp.pp will need to use "advancedsingleinstance.pp" in implementation section then. If you want to have abstract classes for TIPCServer and TIPCClient, advancedipc.pp would need a bigger refactoring. Adding interfaces for them seems to be a simpler and better solution for me. - But as I said before, IMO neither interfaces nor abstract classes are needed for now. TBaseSingleInstance already introduces the bare minimum of methods needed. or introduce TAbstractSingleInstance as a parent of TBaseSingleInstance with the bare minimum of methods/properties. TBaseSingleInstance is now such "TAbstractSingleInstance". You can rename it to TAbstractSingleInstance if you like. b) There is no way to have TCustomApplication create a different singleinstance class, for 2 reasons: 1. Your property is declared as TCustomSingleInstance. It should be TBaseSingleInstance (or TAbstractSingleInstance) That means that the 'enabled' property should be in TBaseSingleInstance or TAbstractSingleInstance. The Enabled property doesn't belong into TBaseSingleInstance - it has a meaning only in TCustomApplication. I solved it by introducing SingleInstanceEnabled in TCustomApplication. 2. You create the instance as TCustomSingleInstance.Create in the constructor. It should be a function CreateSingleinstance : TCustomSingleInstance; I solved it by introducing SingleInstanceClass. IMO it's better because SingleInstanceClass can be easily changed without the need to create a new TCustomApplication descendant and override a virtual function. Feel free to comment on my changes. BTW, there are some compiler hints/warnings in CustApp.pp. At least the one warning should be solved, IMO: Compile Project, Target: sitest.exe: Success, Warnings: 1, Hints: 8 custapp.pp(175,6) Note: Local variable "l" is assigned but never used custapp.pp(57,21) Hint: Parameter "EventType" not used custapp.pp(57,51) Hint: Parameter "Msg" not used custapp.pp(391,25) Hint: Local variable "B" does not seem to be initialized custapp.pp(408,29) Warning: Local variable "I" does not seem to be initialized custapp.pp(408,27) Hint: Local variable "B" does not seem to be initialized custapp.pp(453,30) Hint: Local variable "B" does not seem to be initialized custapp.pp(502,31) Hint: Local variable "B" does not seem to be initialized custapp.pp(524,8) Note: Local variable "SO" is assigned but never used Ondrej Index: packages/fcl-base/examples/sitest.pp === --- packages/fcl-base/examples/sitest.pp(revision 32548) +++ packages/fcl-base/examples/sitest.pp(working copy) @@ -40,7 +40,7 @@ WriteLn('Sending response to client.'); xStringStream := TStringStream.Create('my response'); try - Sender.ServerPostCustomResponse(MsgID, MsgType_Response, xStringStream); + (Sender as TAdvancedSingleInstance).ServerPostCustomResponse(MsgID, MsgType_Response, xStringStream); finally xStringStream.Free; end; @@ -66,9 +66,9 @@ begin xApp := TMyCustomApplication.Create(nil); try -xApp.SingleInstance.Enabled := True; +xApp.SingleInstanceEnabled := True; xApp.SingleInstance.OnServerReceivedParams := @xApp.ServerReceivedParams; -xApp.SingleInstance.OnServerReceivedCustomRequest := @xApp.ServerReceivedCustomRequest; +(xApp.SingleInstance as TAdvancedSingleInstance).OnServerReceivedCustomRequest := @xApp.ServerReceivedCustomRequest; xApp.Initialize; Writeln(xApp.SingleInstance.StartResult); xApp.Run; @@ -79,15 +79,15 @@ begin xStream := TStringStream.Create('hello'); try - xApp.SingleInstance.ClientSendCustomRequest(MsgType_Request_No_Response, xStream); + (xApp.SingleInstance as TAdvancedSingleInstance).ClientSendCustomRequest(MsgType_Request_No_Response, xStream); finally xStream.Free; end; xStream := TStringStream.Create('I want a response'); try - xApp.SingleInstance.ClientSendCustomRequest(MsgType_Request_With_Response, xStream); + (xApp.SingleInstance as TAdvancedSingleInstance).ClientSendCustomRequest(MsgType_Request_With_Response, xStream); xStream.Size := 0; -
Re: [fpc-devel] simpleipc issues
On 29.09.2015 12:52, Michael Van Canneyt wrote: Juha, if you want to implement the single IDE instance, then I would like to ask you to implement this in custapp.pp. This is useful functionality for all kinds of applications, and is since very long on my todo list. On 30.09.2015 18:50, Ondrej Pokorny wrote: On 29.09.2015 22:47, Michael Van Canneyt wrote: Let's first see how Ondrej does it. See the patch attached. A simple demo program is attached as well (SITest.lpr). Hello Michael, you asked for implementing "single instance" in custapp.pp. I did it and sent a patch on Sept 28th. Did you have the time to check it and find eventual issues? I am resending the patch against current trunk and a testing application. Ondrej Index: packages/fcl-base/src/custapp.pp === --- packages/fcl-base/src/custapp.pp(revision 32284) +++ packages/fcl-base/src/custapp.pp(working copy) @@ -18,12 +18,15 @@ Interface -uses SysUtils,Classes; +uses SysUtils,Classes,singleinstance; Type TExceptionEvent = Procedure (Sender : TObject; E : Exception) Of Object; TEventLogTypes = Set of TEventType; + TCustomApplication = Class; + TCustomSingleInstance = Class; + { TCustomApplication } TCustomApplication = Class(TComponent) @@ -30,6 +33,7 @@ Private FEventLogFilter: TEventLogTypes; FOnException: TExceptionEvent; +FSingleInstance: TCustomSingleInstance; FTerminated : Boolean; FHelpFile, FTitle : String; @@ -86,8 +90,17 @@ Property CaseSensitiveOptions : Boolean Read FCaseSensitiveOptions Write FCaseSensitiveOptions; Property StopOnException : Boolean Read FStopOnException Write FStopOnException; Property EventLogFilter : TEventLogTypes Read FEventLogFilter Write FEventLogFilter; +Property SingleInstance: TCustomSingleInstance read FSingleInstance; end; + TCustomSingleInstance = class(TBaseSingleInstance) + private +FEnabled: Boolean; + public +//you must set Enabled before CustomApplication.Initialize +property Enabled: Boolean read FEnabled write FEnabled; + end; + var CustomApplication : TCustomApplication = nil; Implementation @@ -228,7 +241,10 @@ procedure TCustomApplication.DoRun; begin - // Do nothing. Override in descendent classes. + if FSingleInstance.IsServer then +FSingleInstance.ServerCheckMessages; + + // Override in descendent classes. end; procedure TCustomApplication.DoLog(EventType: TEventType; const Msg: String); @@ -250,6 +266,7 @@ FOptionChar:='-'; FCaseSensitiveOptions:=True; FStopOnException:=False; + FSingleInstance := TCustomSingleInstance.Create(Self); end; destructor TCustomApplication.Destroy; @@ -276,6 +293,18 @@ procedure TCustomApplication.Initialize; begin FTerminated:=False; + if FSingleInstance.Enabled then + begin +case FSingleInstance.Start of + siClient: + begin +FSingleInstance.ClientPostParams; +FTerminated:=True; + end; + siNotResponding: +FTerminated:=True; +end; + end; end; procedure TCustomApplication.Run; @@ -442,11 +471,11 @@ end; Procedure AddToResult(Const Msg : string); - + begin If (Result<>'') then Result:=Result+sLineBreak; -Result:=Result+Msg; +Result:=Result+Msg; end; begin program SITest; {$mode objfpc} {$h+} uses Classes, CustApp, advancedipc, singleinstance; type TMyCustomApplication = class(TCustomApplication) private procedure ServerReceivedParams(Sender: TBaseSingleInstance; aParams: TStringList); procedure ServerReceivedCustomRequest(Sender: TBaseSingleInstance; {%H-}MsgID: Integer; aMsgType: TMessageType; MsgData: TStream); end; const MsgType_Request_No_Response = 1; MsgType_Request_With_Response = 2; MsgType_Response = 3; { TMyCustomApplication } procedure TMyCustomApplication.ServerReceivedCustomRequest( Sender: TBaseSingleInstance; MsgID: Integer; aMsgType: TMessageType; MsgData: TStream); var xData: string; xStringStream: TStringStream; begin MsgData.Position := 0; SetLength(xData, MsgData.Size div SizeOf(Char)); if MsgData.Size > 0 then MsgData.ReadBuffer(xData[1], MsgData.Size); WriteLn('Request: ', xData); if aMsgType = MsgType_Request_With_Response then begin WriteLn('Sending response to client.'); xStringStream := TStringStream.Create('my response'); try Sender.ServerPostCustomResponse(MsgID, MsgType_Response, xStringStream); finally xStringStream.Free; end; end; end; procedure TMyCustomApplication.ServerReceivedParams(Sender: TBaseSingleInstance; aParams: TStringList); var I: Integer; begin Writeln('-'); Writeln('Params:'); for I := 0 to aParams.Count-1 do Writeln(aParams[I]); Writeln('-'); end; var xApp: TMyCustomApplication; xStream: TStringStream; xMsgType: TMessageType; begin xApp := TMyCustomApplication.Create(nil);
Re: [fpc-devel] simpleipc issues
On Wed, 11 Nov 2015, Ondrej Pokorny wrote: On 29.09.2015 12:52, Michael Van Canneyt wrote: Juha, if you want to implement the single IDE instance, then I would like to ask you to implement this in custapp.pp. This is useful functionality for all kinds of applications, and is since very long on my todo list. On 30.09.2015 18:50, Ondrej Pokorny wrote: On 29.09.2015 22:47, Michael Van Canneyt wrote: Let's first see how Ondrej does it. See the patch attached. A simple demo program is attached as well (SITest.lpr). Hello Michael, you asked for implementing "single instance" in custapp.pp. I did it and sent a patch on Sept 28th. Did you have the time to check it and find eventual issues? I am resending the patch against current trunk and a testing application. Well, I had an uncommitted patch for custapp.pp at the time (better non-options and multiple-options support), which made applying and testing quite difficult. So I waited, but forgot about it. I checked the patch and applied it, so people can try it. I have several remarks: a) Your TBaseSingleInstance class contains too many methods. It assumes you are using advancedipc. I suggest refactoring such a way that advancedipc is in the implementation section of the class. or introduce TAbstractSingleInstance as a parent of TBaseSingleInstance with the bare minimum of methods/properties. b) There is no way to have TCustomApplication create a different singleinstance class, for 2 reasons: 1. Your property is declared as TCustomSingleInstance. It should be TBaseSingleInstance (or TAbstractSingleInstance) That means that the 'enabled' property should be in TBaseSingleInstance or TAbstractSingleInstance. 2. You create the instance as TCustomSingleInstance.Create in the constructor. It should be a function CreateSingleinstance : TCustomSingleInstance; Can you have a look at these remarks ? If something is not clear, let me know. Michael. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel
Re: [fpc-devel] simpleipc issues
On 11.11.2015 17:47, Michael Van Canneyt wrote: I checked the patch and applied it, so people can try it. I have several remarks: a) Your TBaseSingleInstance class contains too many methods. It assumes you are using advancedipc. I suggest refactoring such a way that advancedipc is in the implementation section of the class. or introduce TAbstractSingleInstance as a parent of TBaseSingleInstance with the bare minimum of methods/properties. b) There is no way to have TCustomApplication create a different singleinstance class, for 2 reasons: 1. Your property is declared as TCustomSingleInstance. It should be TBaseSingleInstance (or TAbstractSingleInstance) That means that the 'enabled' property should be in TBaseSingleInstance or TAbstractSingleInstance. 2. You create the instance as TCustomSingleInstance.Create in the constructor. It should be a function CreateSingleinstance : TCustomSingleInstance; Can you have a look at these remarks ? If something is not clear, let me know. Great! Your remarks are reasonable. I'll rewrite the code so that it supports modifications! Ondrej ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel
Re: [fpc-devel] simpleipc issues
On 03.10.2015 19:21, Tomas Hajny wrote: Thanks, I tested it under OS/2 now. Both the "simple" and "advanced" test programs work, well done! I noticed two issues when running the "advanced" tests, though. First, the server increases the CPU considerably. There seems to be a loop permanently searching for a file FindFirst without any sleep in between. Maybe related to PeekRequest calls? The solution is simple and is only a problem of the demo application (not advancedipc.pp code). Just add an "ELSE SLEEP(XYZ)" block into the server while-loop. Ondrej program TestIPC_Server; {$MODE ObjFPC}{$H+} uses Classes, SysUtils, AdvancedIPC; const STRINGMESSAGE_WANTS_RESPONSE = 3; STRINGMESSAGE_NO_RESPONSE = 2; MESSAGE_STOP = 4; var xServer: TIPCServer; xStream, xResponseStream: TStringStream; xMsgID: Integer; xMsgType: TMessageType; xNotRunningMessagesCount: Integer; begin xServer := nil; xStream := nil; xResponseStream := nil; try xStream := TStringStream.Create(''); xResponseStream := TStringStream.Create('OK'); //first get all messages from the hello server xServer := TIPCServer.Create(nil); xServer.ServerID := 'hello'; xServer.StartServer; WriteLn('Server ', xServer.ServerID, ' started.'); WriteLn('-'); while True do begin if xServer.PeekRequest(xMsgID{%H-}, xMsgType{%H-}) then begin case xMsgType of STRINGMESSAGE_WANTS_RESPONSE, STRINGMESSAGE_NO_RESPONSE: begin xServer.ReadRequest(xMsgID, xStream); WriteLn('Received string message:'); WriteLn(xStream.DataString); if xMsgType = STRINGMESSAGE_WANTS_RESPONSE then begin xResponseStream.Position := 0; xServer.PostResponse(xMsgID, STRINGMESSAGE_NO_RESPONSE, xResponseStream); WriteLn('Posting response.'); end; WriteLn('-'); end; MESSAGE_STOP: begin WriteLn('Stopping '+xServer.ServerID+' server.'); WriteLn('-'); Break; end; end; end else Sleep(50); end; FreeAndNil(xServer); //now try to get all unhandled messages from the not_running server //please see that the messages are not peeked in the order they have been posted (this is correct/designed behavior). xServer := TIPCServer.Create(nil); xServer.ServerID := 'not_running'; xServer.StartServer(False); WriteLn(''); WriteLn('Server ', xServer.ServerID, ' started.'); WriteLn('-'); xNotRunningMessagesCount := 0; while xServer.PeekRequest(xStream, xMsgID, xMsgType) do begin if xMsgType = STRINGMESSAGE_NO_RESPONSE then begin WriteLn('Received message: ', xStream.DataString); Inc(xNotRunningMessagesCount); end else WriteLn('ERROR: Wrong message type: ', xMsgType); WriteLn('-'); end; if xNotRunningMessagesCount <> 10 then begin WriteLn('ERROR: Wrong message count: ', xNotRunningMessagesCount); WriteLn('-'); end; WriteLn('Stopping '+xServer.ServerID+' server.'); WriteLn('-'); FreeAndNil(xServer); finally xServer.Free; xStream.Free; xResponseStream.Free; end; end. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel
Re: [fpc-devel] simpleipc issues
On 03.10.2015 19:21, Tomas Hajny wrote: Thanks, I tested it under OS/2 now. Both the "simple" and "advanced" test programs work, well done! I noticed two issues when running the "advanced" tests, though. First, the server increases the CPU considerably. There seems to be a loop permanently searching for a file FindFirst without any sleep in between. Maybe related to PeekRequest calls? Second, I noticed that unlike the "simple" test, the "advanced" leaves a temporary file 'hello--t' in the temporary directory after finishing. First - Yes that's true, I didn't add any sleep into the code for testing purposes. Second - I'll check that! Apart from that, I replaced the hard-coded '*' with a reference to AllFilesMask constant defined in unit System, because some of FPC targets need a different mask when searching for all files (that is not the case of OS/2, but e.g. GO32v2 would need that if not running on a LFN enabled system) - committed in svn trunk. Thanks! I found some smaller bugs that I send over to the temporary copy in Lazarus trunk. I'll sync both files and send patches back. Ondrej ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel
Re: [fpc-devel] simpleipc issues
On 03.10.2015 19:21, Tomas Hajny wrote: Thanks, I tested it under OS/2 now. Both the "simple" and "advanced" test programs work, well done! I noticed two issues when running the "advanced" tests, though. First, the server increases the CPU considerably. There seems to be a loop permanently searching for a file FindFirst without any sleep in between. Maybe related to PeekRequest calls? Second, I noticed that unlike the "simple" test, the "advanced" leaves a temporary file 'hello--t' in the temporary directory after finishing. Apart from that, I replaced the hard-coded '*' with a reference to AllFilesMask constant defined in unit System, because some of FPC targets need a different mask when searching for all files (that is not the case of OS/2, but e.g. GO32v2 would need that if not running on a LFN enabled system) - committed in svn trunk. Attached patched for FPC and Lazarus to sync advancedipc.pp. The current version in FPC trunk is out-dated (the Lazarus trunk version just misses the AllFilesMask constant). I could not reproduce the "temporary file 'hello--t' was not deleted" problem. Actually all files should be deleted in StopServer(True) or Free -> DeletePendingRequests. What demo did you observe the problem in? TestIPC_Server/TestIPC_Client? Ondrej Index: packages/fcl-base/src/advancedipc.pp === --- packages/fcl-base/src/advancedipc.pp(revision 31926) +++ packages/fcl-base/src/advancedipc.pp(working copy) @@ -30,7 +30,11 @@ {$IFDEF UNIX} baseunix, {$endif} - sysutils, Classes; + sysutils, Classes + {$IF FPC_FULLVERSION<20701} + ,LazUTF8SysUtils + {$ENDIF} + ; const HEADER_VERSION = 2; @@ -60,13 +64,14 @@ FMessageVersion: Integer; protected class function ServerIDToFileName(const aServerID: string; const aGlobal: Boolean): string; -function GetResponseFileName(const aMsgID: Integer): string; +function GetResponseFileName(const aRequestID: Integer): string; function GetResponseFileName(const aRequestFileName: string): string; -function GetPeekedRequestFileName(const aMsgID: Integer): string; +function GetPeekedRequestFileName(const aRequestID: Integer): string; function GetPeekedRequestFileName(const aRequestFileName: string): string; function GetRequestPrefix: string; -function GetRequestFileName(const aMsgID: Integer): string; -function RequestFileNameToMsgID(const aFileName: string): Integer; +function GetRequestFileName(const aRequestID: Integer): string; +function RequestFileNameToID(const aFileName: string): Integer; +function RequestExists(const aRequestFileName: string): Boolean; function GetUniqueRequest(out outFileName: string): Integer; procedure SetServerID(const aServerID: string); virtual; @@ -122,19 +127,19 @@ public //peek request and read the message into a stream function PeekRequest(const aStream: TStream; out outMsgType: TMessageType): Boolean; overload; -function PeekRequest(const aStream: TStream; out outMsgID: Integer; out outMsgType: TMessageType): Boolean; overload; -function PeekRequest(const aStream: TStream; out outMsgID: Integer; out outMsgType: TMessageType; const aTimeOut: Integer): Boolean; overload; +function PeekRequest(const aStream: TStream; out outRequestID: Integer; out outMsgType: TMessageType): Boolean; overload; +function PeekRequest(const aStream: TStream; out outRequestID: Integer; out outMsgType: TMessageType; const aTimeOut: Integer): Boolean; overload; //only peek request, you have to read/delete the request manually with ReadRequest/DeleteRequest function PeekRequest(out outMsgType: TMessageType): Boolean; overload; -function PeekRequest(out outMsgID: Integer; out outMsgType: TMessageType): Boolean; overload; -function PeekRequest(out outMsgID: Integer; out outMsgType: TMessageType; const aTimeOut: Integer): Boolean; overload; +function PeekRequest(out outRequestID: Integer; out outMsgType: TMessageType): Boolean; overload; +function PeekRequest(out outRequestID: Integer; out outMsgType: TMessageType; const aTimeOut: Integer): Boolean; overload; //read a peeked request (that hasn't been read yet) -function ReadRequest(const aMsgID: Integer; const aStream: TStream): Boolean; +function ReadRequest(const aRequestID: Integer; const aStream: TStream): Boolean; //delete a peeked request (that hasn't been read yet) -procedure DeleteRequest(const aMsgID: Integer); +procedure DeleteRequest(const aRequestID: Integer); //post response to a request -procedure PostResponse(const aMsgID: Integer; const aMsgType: TMessageType; const aStream: TStream); +procedure PostResponse(const aRequestID: Integer; const aMsgType: TMessageType; const aStream: TStream); //find the highest request ID from all pending requests function FindHighestPendingRequestId:
Re: [fpc-devel] simpleipc issues
On 21 Sep 15, at 14:03, Ondrej Pokorny wrote: . . > Michael Van Canneyt & Tomas Hajny & everybody who wants to test: > > I prepared a fully compatible AdvancedIPC unit. See the attachment. > There is a unit mysimpleipc.pp that should replace the simpleipc.pp in > FPC sources. I renamed it in order to prevent file name problems and to > be able to check the compatibility without recompiling FPC sources > (basically just use "mysimpleipc" in the uses instead of "simpleipc"). . . Thanks, I tested it under OS/2 now. Both the "simple" and "advanced" test programs work, well done! I noticed two issues when running the "advanced" tests, though. First, the server increases the CPU considerably. There seems to be a loop permanently searching for a file FindFirst without any sleep in between. Maybe related to PeekRequest calls? Second, I noticed that unlike the "simple" test, the "advanced" leaves a temporary file 'hello--t' in the temporary directory after finishing. Apart from that, I replaced the hard-coded '*' with a reference to AllFilesMask constant defined in unit System, because some of FPC targets need a different mask when searching for all files (that is not the case of OS/2, but e.g. GO32v2 would need that if not running on a LFN enabled system) - committed in svn trunk. Tomas ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel
Re: [fpc-devel] simpleipc issues
On Sat, October 3, 2015 19:59, Ondrej Pokorny wrote: > On 03.10.2015 19:21, Tomas Hajny wrote: >> Thanks, I tested it under OS/2 now. Both the "simple" and "advanced" >> test programs work, well done! I noticed two issues when running the >> "advanced" tests, though. First, the server increases the CPU >> considerably. There seems to be a loop permanently searching for a >> file FindFirst without any sleep in between. Maybe related to >> PeekRequest calls? > The solution is simple and is only a problem of the demo application > (not advancedipc.pp code). Just add an "ELSE SLEEP(XYZ)" block into the > server while-loop. Yes, indeed, that fixed it, thanks. I've added the test / example to FPC SVN under the directory examples. Tomas ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel
Re: [fpc-devel] simpleipc issues
On Sat, October 3, 2015 19:54, Ondrej Pokorny wrote: > On 03.10.2015 19:21, Tomas Hajny wrote: . . > Attached patched for FPC and Lazarus to sync advancedipc.pp. The current > version in FPC trunk is out-dated (the Lazarus trunk version just misses > the AllFilesMask constant). Thanks, I applied a modified version of your patch to FPC SVN; since we put the file to FPC trunk, the modifications related to support of FPC 2.6.4 would be superfluous there and I skipped them. > I could not reproduce the "temporary file 'hello--t' was not > deleted" problem. Actually all files should be deleted in > StopServer(True) or Free -> DeletePendingRequests. > > What demo did you observe the problem in? TestIPC_Server/TestIPC_Client? Yes. I cannot reproduce it either, though. I guess that it must have resulted from me killing the server at some point (due to the high CPU load), i.e. apparently a false alarm - sorry. :-( Tomas ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel
Re: [fpc-devel] simpleipc issues
On 29.09.2015 22:47, Michael Van Canneyt wrote: Let's first see how Ondrej does it. See the patch attached. A simple demo program is attached as well (SITest.lpr). advancedipc.pp: refactoring MsgID -> RequestID and some smaller issues solved. API hasn't changed. singleinstance.pp: class implementing single instance. custapp.pp: added singleinstance property. Set Enabled to True (before CustomApplication.Initialize) and it does everything for you. You can also set more properties like ID and Global. You can talk to the server single instance after Application.Initialize if you want to (see SITest.lpr). + I am now travelling so I have only MS Windows to check. There is a workaround for UNIX to solve the filelock problem. The problem is that if you execute more files from the explorer, the instances are started at the same time so there could be problems with creating the file lock (double file locks can occur). The clue is that you wait for other instances to start (timeout 100ms) and then use the highest instance as server. If there are some pending wait-requests (if the program collapsed or something like that) there is a random sleep to decide what instance should be the server. This approach is very bullet-proof, as my tests showed (the random sleep is not needed in normal situations). + A small issue is that checking for new messages in CustomApplication.DoRun too often uses a lot of CPU power. The check should be made only about every 50ms (then the CPU needed is at ~0%). I don't know how to do it the best way, because eg. using GetTickCount needs also a lot of CPU. I don't know how it behaves with TApplication (maybe there is no such problem). + I had a problem with random numbers (I checked windows implementation only). If randomize is executed from 2 different processes at exactly same moment, it returns the same randseed (GetTickCount). This is a big problem with processors with multithreading. In this case you can have exactly same random sequences for 2 different threads/processes. I suggest to include GetCurrentThreadID into randomize somehow. Something like: procedure randomize; begin randseed:=Integer(Int64(GetTickCount)+GetCurrentThreadID); end; Addition is maybe not the best operation, but you should get the idea. I solved this problem by adding GetCurrentThreadID to the random result, so advancedipc is not affected by this problem any more. + Juha, I will upload a new patch for Lazarus IDEInstances. Probably nothing changed, but just to be sure. Ondrej Index: packages/fcl-base/src/advancedipc.pp === --- packages/fcl-base/src/advancedipc.pp(revision 31890) +++ packages/fcl-base/src/advancedipc.pp(working copy) @@ -60,13 +60,14 @@ FMessageVersion: Integer; protected class function ServerIDToFileName(const aServerID: string; const aGlobal: Boolean): string; -function GetResponseFileName(const aMsgID: Integer): string; +function GetResponseFileName(const aRequestID: Integer): string; function GetResponseFileName(const aRequestFileName: string): string; -function GetPeekedRequestFileName(const aMsgID: Integer): string; +function GetPeekedRequestFileName(const aRequestID: Integer): string; function GetPeekedRequestFileName(const aRequestFileName: string): string; function GetRequestPrefix: string; -function GetRequestFileName(const aMsgID: Integer): string; -function RequestFileNameToMsgID(const aFileName: string): Integer; +function GetRequestFileName(const aRequestID: Integer): string; +function RequestFileNameToID(const aFileName: string): Integer; +function RequestExists(const aRequestFileName: string): Boolean; function GetUniqueRequest(out outFileName: string): Integer; procedure SetServerID(const aServerID: string); virtual; @@ -122,19 +123,19 @@ public //peek request and read the message into a stream function PeekRequest(const aStream: TStream; out outMsgType: TMessageType): Boolean; overload; -function PeekRequest(const aStream: TStream; out outMsgID: Integer; out outMsgType: TMessageType): Boolean; overload; -function PeekRequest(const aStream: TStream; out outMsgID: Integer; out outMsgType: TMessageType; const aTimeOut: Integer): Boolean; overload; +function PeekRequest(const aStream: TStream; out outRequestID: Integer; out outMsgType: TMessageType): Boolean; overload; +function PeekRequest(const aStream: TStream; out outRequestID: Integer; out outMsgType: TMessageType; const aTimeOut: Integer): Boolean; overload; //only peek request, you have to read/delete the request manually with ReadRequest/DeleteRequest function PeekRequest(out outMsgType: TMessageType): Boolean; overload; -function PeekRequest(out outMsgID: Integer; out outMsgType: TMessageType): Boolean; overload; -function PeekRequest(out outMsgID: Integer; out
Re: [fpc-devel] simpleipc issues
On Tue, Sep 29, 2015 at 2:50 PM, Michael Van Canneytwrote: > I am not proposing to make a new class. > I want a property "SingeInstance" in CustApp which activates this > automatically. I had the very same idea when this was discussed a long time ago in Lazarus list. Martin Friebe noted that every application would then depend on this single-instance IPC code. It was a valid point. There should not be such a dependency. The right way is to use a drag-and-drop LCL component like the one from Luiz Américo. The question is should we replace his component with a better one based on Ondrej's AdvancedIPC. I think we should because SimpleIPC apparently has limitations. Michael, an LCL component is as beginner friendly as your SingeInstance property would be. Regards, Juha ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel
Re: [fpc-devel] simpleipc issues
On 29.09.2015 14:42, Michael Van Canneyt wrote: On Tue, 29 Sep 2015, Ondrej Pokorny wrote: OK, I see your point. Yes, I think it is possible and even not that much work to do. I programmed "multiple instances" handling into Lazarus IDE. It's the same like e.g. Adobe Photoshop or VLC player work - if you start the IDE without files in cmd parameters, the IDE is started. If you start IDE with files, the files are opened in already running instance. You can enable a truly "single instance" (always only single instance allowed) with an environment setting option. IMO, we should keep the code in CustApp simple and don't do this advanced stuff. Only single/multiple instances option. If single instance is selected, allow to talk with the one single instance through IPC. If there are multiple instances, you cannot talk to other instances. This should be doable. What do you think? Exactly what I had in mind, simple yet functional :-) OK, I'll prepare this one as well. But the Lazarus IDE won't take advantage of CustApp (it will use AdvancedIPC directly with the custom advanced possibilities I already programmed). Ondrej ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel
Re: [fpc-devel] simpleipc issues
On Tue, 29 Sep 2015, Ondrej Pokorny wrote: On 29.09.2015 12:52, Michael Van Canneyt wrote: I added it to fpc/packages/fcl-base. It compiles OK, there are no dangerous dependencies except sysutils and classes. Michael, you added the wrong (old) unit from the bug report, not the latest simpleipc-compatible one from the mailing list. Please apply the patch from the attachment! Strange. I took the one from the mail ? Maybe some name mixup :( My apologies. Applied the patch, rev. 31890. Thanks ! Michael. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel
Re: [fpc-devel] simpleipc issues
On 29.09.2015 12:52, Michael Van Canneyt wrote: I added it to fpc/packages/fcl-base. It compiles OK, there are no dangerous dependencies except sysutils and classes. Michael, you added the wrong (old) unit from the bug report, not the latest simpleipc-compatible one from the mailing list. Please apply the patch from the attachment! Thanks Ondrej Index: packages/fcl-base/src/advancedipc.pp === --- packages/fcl-base/src/advancedipc.pp(revision 31886) +++ packages/fcl-base/src/advancedipc.pp(working copy) @@ -2,7 +2,13 @@ This file is part of the Free Component Library (FCL) Copyright (c) 2015 by Ondrej Pokorny -Unit implementing two-way (request/response) IPC between 1 server and more clients, based on files. +Unit implementing two-way (request/response) IPC between 1 server and more +clients, based on files. +The order of message processing is not deterministic (if there are more +pending messages, the server won't process them in the order they have +been sent to the server. +SendRequest and PostRequest+PeekResponse sequences from 1 client are +blocking and processed in correct order. See the file COPYING.FPC, included in this distribution, for details about the copyright. @@ -27,13 +33,14 @@ sysutils, Classes; const - HEADER_VERSION = 1; + HEADER_VERSION = 2; type + TMessageType = LongInt; TMessageHeader = packed record -HeaderVersion: Integer; +HeaderVersion: Byte; FileLock: Byte;//0 = unlocked, 1 = locked -MsgType: Integer; +MsgType: TMessageType; MsgLen: Integer; MsgVersion: Integer; end; @@ -45,47 +52,58 @@ destructor Destroy; override; end; - TIPCBase = class + TIPCBase = class(TComponent) private FGlobal: Boolean; FFileName: string; -FServerName: string; +FServerID: string; FMessageVersion: Integer; protected -class function ServerNameToFileName(const aServerName: string; const aGlobal: Boolean): string; +class function ServerIDToFileName(const aServerID: string; const aGlobal: Boolean): string; function GetResponseFileName(const aMsgID: Integer): string; function GetResponseFileName(const aRequestFileName: string): string; +function GetPeekedRequestFileName(const aMsgID: Integer): string; +function GetPeekedRequestFileName(const aRequestFileName: string): string; function GetRequestPrefix: string; function GetRequestFileName(const aMsgID: Integer): string; function RequestFileNameToMsgID(const aFileName: string): Integer; function GetUniqueRequest(out outFileName: string): Integer; -procedure SetServerName(const aServerName: string); virtual; +procedure SetServerID(const aServerID: string); virtual; procedure SetGlobal(const aGlobal: Boolean); virtual; -function CanReadMessage(const aFileName: string; out outStream: TStream; out outMsgType, outMsgLen: Integer): Boolean; -procedure DoPostMessage(const aFileName: string; const aMsgType: Integer; const aStream: TStream); +function CanReadMessage(const aFileName: string; out outStream: TStream; out outMsgType: TMessageType; out outMsgLen: Integer): Boolean; +procedure DoPostMessage(const aFileName: string; const aMsgType: TMessageType; const aStream: TStream); property FileName: string read FFileName; public -constructor Create; virtual; +class procedure FindRunningServers(const aServerIDPrefix: string; + const outServerIDs: TStrings; const aGlobal: Boolean = False); +class function ServerRunning(const aServerID: string; const aGlobal: Boolean = False): Boolean; overload; public -class procedure FindRunningServers(const aServerNamePrefix: string; - const outServerNames: TStrings; const aGlobal: Boolean = False); -class function ServerIsRunning(const aServerName: string; const aGlobal: Boolean = False): Boolean; -property ServerName: string read FServerName write SetServerName; +//ServerID: name/ID of the server. Use only ['a'..'z', 'A'..'Z', '_'] characters +property ServerID: string read FServerID write SetServerID; +//Global: if true, processes from different users can communicate; false, processes only from current users can communicate property Global: Boolean read FGlobal write SetGlobal; +//MessageVersion: only messages with the same MessageVersion can be delivered between server/client property MessageVersion: Integer read FMessageVersion write FMessageVersion; end; TIPCClient = class(TIPCBase) - var + private FLastMsgFileName: string; public -function PostRequest(const aMsgType: Integer; const aStream: TStream): Integer;//returns ID -function PeekResponse(const aStream: TStream; var outMsgType: Integer; const aTimeOut: Integer): Boolean; +//post request to server, do not wait until request is peeked; returns request ID +
Re: [fpc-devel] simpleipc issues
On 29.09.2015 15:42, Ondrej Pokorny wrote: On 29.09.2015 12:52, Michael Van Canneyt wrote: I added it to fpc/packages/fcl-base. It compiles OK, there are no dangerous dependencies except sysutils and classes. Michael, you added the wrong (old) unit from the bug report, not the latest simpleipc-compatible one from the mailing list. Please apply the patch from the attachment! Thanks Ondrej Sorry for the double email, I am using mobile internet now and it reported mail send error. Thanks for committing the patch, maybe it was my mistake, no problem anyway. It's OK now! Ondrej ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel
Re: [fpc-devel] simpleipc issues
On Tue, Sep 29, 2015 at 2:35 PM, Ondrej Pokornywrote: > Juha, I changed the advancedipc.pas unit (this one from the mailing list is > newer than from the bug report). I can prepare a new patch for the bug > report. No need for a new patch if it did not change otherwise. I only would like to move the AdvancedIPC unit to somewhere else from ide directory. I can ask opinions at Lazarus developer list. Juha ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel
Re: [fpc-devel] simpleipc issues
On 29.09.2015 15:01, Juha Manninen wrote: On Tue, Sep 29, 2015 at 2:35 PM, Ondrej Pokornywrote: Juha, I changed the advancedipc.pas unit (this one from the mailing list is newer than from the bug report). I can prepare a new patch for the bug report. No need for a new patch if it did not change otherwise. I only would like to move the AdvancedIPC unit to somewhere else from ide directory. I can ask opinions at Lazarus developer list. Juha The API may have changed a little bit. I'll recheck it. Ondrej ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel
Re: [fpc-devel] simpleipc issues
On Tue, 29 Sep 2015, Juha Manninen wrote: On Tue, Sep 29, 2015 at 2:50 PM, Michael Van Canneytwrote: I am not proposing to make a new class. I want a property "SingeInstance" in CustApp which activates this automatically. I had the very same idea when this was discussed a long time ago in Lazarus list. Martin Friebe noted that every application would then depend on this single-instance IPC code. It was a valid point. There should not be such a dependency. For simpleIPC, yes. But the new implementation has no dependencies except sysutils, classes. So the argument becomes void. That's why I was glad with Ondrej's implementation. The right way is to use a drag-and-drop LCL component like the one from Luiz Américo. That is IMHO a completely wrong implementation for 2 reasons: 1. Using a LCL component means that you must instantiate a form/datamodule first. By that time, a database connection may already have been made (just to name something), which is exactly what you want to avoid. The check for single instance should be done before the first form is created. 2. Then it is only available in visually designed applications. Services, website servers and custom console apps are non-visual. I am specificially thinking FastCGI processes. All these have in common that they descend from TCustomApplication. That is why I think TCustomApplication is the only good location; So if Ondrej does not do it, I will add it myself anyway. Lazarus is free not to use it, obviously. Michael.___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel
Re: [fpc-devel] simpleipc issues
On Tue, Sep 29, 2015 at 4:35 PM, Michael Van Canneytwrote: > For simpleIPC, yes. But the new implementation has no dependencies except > sysutils, classes. So the argument becomes void. It adds extra code to every application. Maybe not too much though. > ... > That is why I think TCustomApplication is the only good location; > So if Ondrej does not do it, I will add it myself anyway. Ok, I see your point. I am not arguing against it. > Lazarus is free not to use it, obviously. TApplication inherits from TCustomApplication, thus it will be included in every LCL application. Juha ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel
Re: [fpc-devel] simpleipc issues
On Tue, 29 Sep 2015, Ondrej Pokorny wrote: On 29.09.2015 15:35, Michael Van Canneyt wrote: 1. Using a LCL component means that you must instantiate a form/datamodule first. By that time, a database connection may already have been made (just to name something), which is exactly what you want to avoid. The check for single instance should be done before the first form is created. 2. Then it is only available in visually designed applications. Services, website servers and custom console apps are non-visual. I am specificially thinking FastCGI processes. Actually, you could create the LCL component manually in the LPR and use it non-visually before any code is run (except initialization sections). The visual component could be only for the hobbyists. So for me both CustApp or LCL component are OK. You decide :) Both are OK. Use of one does not exclude use of the other. I was going to add it in CustApp anyway as soon as I had looked at your implementation. Michael. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel
Re: [fpc-devel] simpleipc issues
On 29.09.2015 15:35, Michael Van Canneyt wrote: 1. Using a LCL component means that you must instantiate a form/datamodule first. By that time, a database connection may already have been made (just to name something), which is exactly what you want to avoid. The check for single instance should be done before the first form is created. 2. Then it is only available in visually designed applications. Services, website servers and custom console apps are non-visual. I am specificially thinking FastCGI processes. Actually, you could create the LCL component manually in the LPR and use it non-visually before any code is run (except initialization sections). The visual component could be only for the hobbyists. So for me both CustApp or LCL component are OK. You decide :) Ondrej ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel
Re: [fpc-devel] simpleipc issues
On Tue, 29 Sep 2015, Ondrej Pokorny wrote: On 29.09.2015 13:50, Michael Van Canneyt wrote: You may not think this is important, but for beginners, this can be a tremendous aid. The easier we make it, the better. Lazarus is a RAD environment, after all. Michael. OK, I see your point. Yes, I think it is possible and even not that much work to do. I programmed "multiple instances" handling into Lazarus IDE. It's the same like e.g. Adobe Photoshop or VLC player work - if you start the IDE without files in cmd parameters, the IDE is started. If you start IDE with files, the files are opened in already running instance. You can enable a truly "single instance" (always only single instance allowed) with an environment setting option. IMO, we should keep the code in CustApp simple and don't do this advanced stuff. Only single/multiple instances option. If single instance is selected, allow to talk with the one single instance through IPC. If there are multiple instances, you cannot talk to other instances. This should be doable. What do you think? Exactly what I had in mind, simple yet functional :-) Michael. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel
Re: [fpc-devel] simpleipc issues
On 29.09.2015 12:52, Michael Van Canneyt wrote: I added it to fpc/packages/fcl-base. It compiles OK, there are no dangerous dependencies except sysutils and classes. Michael, you added the wrong (old) unit from the bug report, not the latest simpleipc-compatible one from the mailing list. Please apply the patch from the attachment! Thanks Ondrej Index: packages/fcl-base/src/advancedipc.pp === --- packages/fcl-base/src/advancedipc.pp(revision 31886) +++ packages/fcl-base/src/advancedipc.pp(working copy) @@ -2,7 +2,13 @@ This file is part of the Free Component Library (FCL) Copyright (c) 2015 by Ondrej Pokorny -Unit implementing two-way (request/response) IPC between 1 server and more clients, based on files. +Unit implementing two-way (request/response) IPC between 1 server and more +clients, based on files. +The order of message processing is not deterministic (if there are more +pending messages, the server won't process them in the order they have +been sent to the server. +SendRequest and PostRequest+PeekResponse sequences from 1 client are +blocking and processed in correct order. See the file COPYING.FPC, included in this distribution, for details about the copyright. @@ -27,13 +33,14 @@ sysutils, Classes; const - HEADER_VERSION = 1; + HEADER_VERSION = 2; type + TMessageType = LongInt; TMessageHeader = packed record -HeaderVersion: Integer; +HeaderVersion: Byte; FileLock: Byte;//0 = unlocked, 1 = locked -MsgType: Integer; +MsgType: TMessageType; MsgLen: Integer; MsgVersion: Integer; end; @@ -45,47 +52,58 @@ destructor Destroy; override; end; - TIPCBase = class + TIPCBase = class(TComponent) private FGlobal: Boolean; FFileName: string; -FServerName: string; +FServerID: string; FMessageVersion: Integer; protected -class function ServerNameToFileName(const aServerName: string; const aGlobal: Boolean): string; +class function ServerIDToFileName(const aServerID: string; const aGlobal: Boolean): string; function GetResponseFileName(const aMsgID: Integer): string; function GetResponseFileName(const aRequestFileName: string): string; +function GetPeekedRequestFileName(const aMsgID: Integer): string; +function GetPeekedRequestFileName(const aRequestFileName: string): string; function GetRequestPrefix: string; function GetRequestFileName(const aMsgID: Integer): string; function RequestFileNameToMsgID(const aFileName: string): Integer; function GetUniqueRequest(out outFileName: string): Integer; -procedure SetServerName(const aServerName: string); virtual; +procedure SetServerID(const aServerID: string); virtual; procedure SetGlobal(const aGlobal: Boolean); virtual; -function CanReadMessage(const aFileName: string; out outStream: TStream; out outMsgType, outMsgLen: Integer): Boolean; -procedure DoPostMessage(const aFileName: string; const aMsgType: Integer; const aStream: TStream); +function CanReadMessage(const aFileName: string; out outStream: TStream; out outMsgType: TMessageType; out outMsgLen: Integer): Boolean; +procedure DoPostMessage(const aFileName: string; const aMsgType: TMessageType; const aStream: TStream); property FileName: string read FFileName; public -constructor Create; virtual; +class procedure FindRunningServers(const aServerIDPrefix: string; + const outServerIDs: TStrings; const aGlobal: Boolean = False); +class function ServerRunning(const aServerID: string; const aGlobal: Boolean = False): Boolean; overload; public -class procedure FindRunningServers(const aServerNamePrefix: string; - const outServerNames: TStrings; const aGlobal: Boolean = False); -class function ServerIsRunning(const aServerName: string; const aGlobal: Boolean = False): Boolean; -property ServerName: string read FServerName write SetServerName; +//ServerID: name/ID of the server. Use only ['a'..'z', 'A'..'Z', '_'] characters +property ServerID: string read FServerID write SetServerID; +//Global: if true, processes from different users can communicate; false, processes only from current users can communicate property Global: Boolean read FGlobal write SetGlobal; +//MessageVersion: only messages with the same MessageVersion can be delivered between server/client property MessageVersion: Integer read FMessageVersion write FMessageVersion; end; TIPCClient = class(TIPCBase) - var + private FLastMsgFileName: string; public -function PostRequest(const aMsgType: Integer; const aStream: TStream): Integer;//returns ID -function PeekResponse(const aStream: TStream; var outMsgType: Integer; const aTimeOut: Integer): Boolean; +//post request to server, do not wait until request is peeked; returns request ID +
Re: [fpc-devel] simpleipc issues
On Mon, Sep 21, 2015 at 3:03 PM, Ondrej Pokornywrote: > Michael Van Canneyt & Tomas Hajny & everybody who wants to test: > > I prepared a fully compatible AdvancedIPC unit. See the attachment. > ... Michael and Tomas, I am planning to copy AdvancedIPC temporarily to Lazarus sources. If you are planning changes for it, I can wait. The temporary copy does not need to be identical but it should be API compatible. With it we can finally implement the single IDE instance feature without depending on the latest FPC libs. http://bugs.freepascal.org/view.php?id=8051 Regards, Juha ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel
Re: [fpc-devel] simpleipc issues
On 29.09.2015 13:50, Michael Van Canneyt wrote: You may not think this is important, but for beginners, this can be a tremendous aid. The easier we make it, the better. Lazarus is a RAD environment, after all. Michael. OK, I see your point. Yes, I think it is possible and even not that much work to do. I programmed "multiple instances" handling into Lazarus IDE. It's the same like e.g. Adobe Photoshop or VLC player work - if you start the IDE without files in cmd parameters, the IDE is started. If you start IDE with files, the files are opened in already running instance. You can enable a truly "single instance" (always only single instance allowed) with an environment setting option. IMO, we should keep the code in CustApp simple and don't do this advanced stuff. Only single/multiple instances option. If single instance is selected, allow to talk with the one single instance through IPC. If there are multiple instances, you cannot talk to other instances. This should be doable. What do you think? Ondrej ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel
Re: [fpc-devel] simpleipc issues
On Tue, 29 Sep 2015, Ondrej Pokorny wrote: On 29.09.2015 12:52, Michael Van Canneyt wrote: I added it to fpc/packages/fcl-base. It compiles OK, there are no dangerous dependencies except sysutils and classes. Thanks! Juha, if you want to implement the single IDE instance, then I would like to ask you to implement this in custapp.pp. This is useful functionality for all kinds of applications, and is since very long on my todo list. I don't think it is needed (see comments further down). I think it is very much needed. I think the functionality can be split out in 2 parts: - Make sure a single instance is running. The IPC does it by design - you start a server and you have the check, so you get it. IMO it's not needed to make another component above AdvancedIPC with exactly the same functionality but different name. I am not proposing to make a new class. I want a property "SingeInstance" in CustApp which activates this automatically. - Sending messages to running instance. Again, IPC does it. I know that, I simply want it integrated in CustApp. By doing this, 'Single instance' can be a simple flag in the project options. You may not think this is important, but for beginners, this can be a tremendous aid. The easier we make it, the better. Lazarus is a RAD environment, after all. Michael. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel
Re: [fpc-devel] simpleipc issues
On Tue, September 29, 2015 12:30, Juha Manninen wrote: > On Mon, Sep 21, 2015 at 3:03 PM, Ondrej Pokornywrote: >> Michael Van Canneyt & Tomas Hajny & everybody who wants to test: >> >> I prepared a fully compatible AdvancedIPC unit. See the attachment. >> ... > > Michael and Tomas, I am planning to copy AdvancedIPC temporarily to > Lazarus sources. > If you are planning changes for it, I can wait. > The temporary copy does not need to be identical but it should be API > compatible. > With it we can finally implement the single IDE instance feature > without depending on the latest FPC libs. > http://bugs.freepascal.org/view.php?id=8051 Unfortunately, I didn't have time for testing it yet, sorry. :-( If you can wait until end of this week, I'll make sure to do so during the weekend at the latest. Tomas ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel
Re: [fpc-devel] simpleipc issues
On 29.09.2015 12:52, Michael Van Canneyt wrote: I added it to fpc/packages/fcl-base. It compiles OK, there are no dangerous dependencies except sysutils and classes. Thanks! Juha, if you want to implement the single IDE instance, then I would like to ask you to implement this in custapp.pp. This is useful functionality for all kinds of applications, and is since very long on my todo list. I don't think it is needed (see comments further down). I think the functionality can be split out in 2 parts: - Make sure a single instance is running. The IPC does it by design - you start a server and you have the check, so you get it. IMO it's not needed to make another component above AdvancedIPC with exactly the same functionality but different name. - Sending messages to running instance. Again, IPC does it. Actually, you can achieve "single instance" with AdvancedIPC with only a few lines of code (I think the simplest code would be under 10 lines). Every application can have different needs about the "single" instance so a customization is needed anyway (e.g. passing over other command line parameters etc.) Juha, I changed the advancedipc.pas unit (this one from the mailing list is newer than from the bug report). I can prepare a new patch for the bug report. Ondrej ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel
Re: [fpc-devel] simpleipc issues
On Tue, 29 Sep 2015, Tomas Hajny wrote: On Tue, September 29, 2015 12:30, Juha Manninen wrote: On Mon, Sep 21, 2015 at 3:03 PM, Ondrej Pokornywrote: Michael Van Canneyt & Tomas Hajny & everybody who wants to test: I prepared a fully compatible AdvancedIPC unit. See the attachment. ... Michael and Tomas, I am planning to copy AdvancedIPC temporarily to Lazarus sources. If you are planning changes for it, I can wait. The temporary copy does not need to be identical but it should be API compatible. With it we can finally implement the single IDE instance feature without depending on the latest FPC libs. http://bugs.freepascal.org/view.php?id=8051 Unfortunately, I didn't have time for testing it yet, sorry. :-( If you can wait until end of this week, I'll make sure to do so during the weekend at the latest. I added it to fpc/packages/fcl-base. It compiles OK, there are no dangerous dependencies except sysutils and classes. Juha, if you want to implement the single IDE instance, then I would like to ask you to implement this in custapp.pp. This is useful functionality for all kinds of applications, and is since very long on my todo list. I think the functionality can be split out in 2 parts: - Make sure a single instance is running. - Sending messages to running instance. The first can be implemented in custapp, I am not sure about the second. At first sight, I think that this should be possible. Michael. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel
Re: [fpc-devel] simpleipc issues
On Tue, 29 Sep 2015, Luiz Americo Pereira Camara wrote: 2015-09-29 11:50 GMT-03:00 Luiz Americo Pereira Camara < luizameri...@gmail.com>: It can be used without the component. The component is just a convenience. See the examples https://github.com/blikblum/luipack/blob/master/uniqueinstance/testraw/project1.lpr unit uniqueinstance; interface uses Forms, Classes, SysUtils, simpleipc, ExtCtrls; Forms, ExtCtrls ?? This disqualifies your component fully for anything but GUI apps. Michael. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel
Re: [fpc-devel] simpleipc issues
2015-09-29 10:35 GMT-03:00 Michael Van Canneyt: > > > On Tue, 29 Sep 2015, Juha Manninen wrote: > > On Tue, Sep 29, 2015 at 2:50 PM, Michael Van Canneyt >> wrote: >> >>> I am not proposing to make a new class. >>> I want a property "SingeInstance" in CustApp which activates this >>> automatically. >>> >> >> I had the very same idea when this was discussed a long time ago in >> Lazarus list. >> Martin Friebe noted that every application would then depend on this >> single-instance IPC code. >> It was a valid point. There should not be such a dependency. >> > > For simpleIPC, yes. But the new implementation has no dependencies except > sysutils, classes. So the argument becomes void. > > That's why I was glad with Ondrej's implementation. > > >> The right way is to use a drag-and-drop LCL component like the one >> from Luiz Américo. >> > > That is IMHO a completely wrong implementation for 2 reasons: > > It can be used without the component. The component is just a convenience. See the examples > 1. Using a LCL component means that you must instantiate a form/datamodule > first. >By that time, a database connection may already have been made (just >to name something), which is exactly what you want to avoid. > > >The check for single instance should be done before the first form is > created. > It can be done > > 2. Then it is only available in visually designed applications. >Services, website servers and custom console apps are non-visual. >I am specificially thinking FastCGI processes. > > See above >All these have in common that they descend from TCustomApplication. > > And console apps without TCustomApplication? Luiz ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel
Re: [fpc-devel] simpleipc issues
On Tue, 29 Sep 2015, Luiz Americo Pereira Camara wrote: 2. Then it is only available in visually designed applications. Services, website servers and custom console apps are non-visual. I am specificially thinking FastCGI processes. See above I didn't say it could not be done with that component. But IMHO you should have gone the extra mile and implement it in TCustomApplication. Ondrej's class has the advantage that it introduces no extra dependencies. It builds on classes and sysutils. All these have in common that they descend from TCustomApplication. And console apps without TCustomApplication? They can use advancedipc directly if they want. I rarely make those any more for production, - Because the command-line handling of TCustomApplication is convenient. - Most often you need a class anyway for event handling or to use as owner. We must assume something. The minimum shared code is in TCustomApplication, it is the most logical place. Michael. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel
Re: [fpc-devel] simpleipc issues
2015-09-29 11:50 GMT-03:00 Luiz Americo Pereira Camara < luizameri...@gmail.com>: > > > It can be used without the component. The component is just a convenience. > See the examples > https://github.com/blikblum/luipack/blob/master/uniqueinstance/testraw/project1.lpr Luiz ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel
Re: [fpc-devel] simpleipc issues
Unit uniqueinstanceraw Please look carefully Luiz Em 29/09/2015 12:01, "Michael Van Canneyt"escreveu: > > > On Tue, 29 Sep 2015, Luiz Americo Pereira Camara wrote: > > 2015-09-29 11:50 GMT-03:00 Luiz Americo Pereira Camara < >> luizameri...@gmail.com>: >> >> >>> >>> It can be used without the component. The component is just a >>> convenience. >>> See the examples >>> >>> >> >> https://github.com/blikblum/luipack/blob/master/uniqueinstance/testraw/project1.lpr >> > > unit uniqueinstance; > > interface > > uses > Forms, Classes, SysUtils, simpleipc, ExtCtrls; > > Forms, ExtCtrls ?? > > This disqualifies your component fully for anything but GUI apps. > > Michael. > ___ > fpc-devel maillist - fpc-devel@lists.freepascal.org > http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel > ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel
Re: [fpc-devel] simpleipc issues
On 29.09.2015 16:09, Michael Van Canneyt wrote: Both are OK. Use of one does not exclude use of the other. I was going to add it in CustApp anyway as soon as I had looked at your implementation. I started working on the CustApp variant. It's even simpler than the LCL component because you can handle the check in DoRun() and so you don't need any timer or watch thread, if I am correct. Ondrej ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel
Re: [fpc-devel] simpleipc issues
On Tue, 29 Sep 2015, Luiz Americo Pereira Camara wrote: On the other side, i still think that should be kept out of TCustomApplication. Well, I have already explained why I want it exactly there :) While the simple requirement of checking another instance is easy to implement into TCustomApplication, others may want more features / control (See bug report for examples). Those that need it would duplicate part of the code. Yes and no, it depends on how you expose the feature. When I said I want a single property, I meant of course that it can be enabled in it's most basic form with just property. That does not exclude that more properties can be exposed to offer more functionality. The big advantage of Ondrej's functionality is that it will work on all platforms. SimpleIPC will not work on all platforms. Maybe create fpUniqueInstance on top of Ondrej work, making extensible and plugabble? Yes. I had thought about this too, we are of the same idea :-) Let's first see how Ondrej does it. Michael. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel
Re: [fpc-devel] simpleipc issues
On Tue, 29 Sep 2015, Ondrej Pokorny wrote: On 29.09.2015 16:09, Michael Van Canneyt wrote: Both are OK. Use of one does not exclude use of the other. I was going to add it in CustApp anyway as soon as I had looked at your implementation. I started working on the CustApp variant. It's even simpler than the LCL component because you can handle the check in DoRun() and so you don't need any timer or watch thread, if I am correct. That was what I thought too. What I failed to see were provisions for per-user and global instances, maybe I missed them. If not, these can be addressed later on. Michael. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel
Re: [fpc-devel] simpleipc issues
On Tue, 29 Sep 2015, Luiz Americo Pereira Camara wrote: Unit uniqueinstanceraw Please look carefully My sincere apologies, I was too fast and indeed opened the wrong unit. uniqueinstance, and uniqueinstancebase, not uniqueinstanceraw :( So, it could be used as well, if we can sort out the dependency on simpleipc. Michael. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel
Re: [fpc-devel] simpleipc issues
2015-09-29 16:12 GMT-03:00 Michael Van Canneyt: > > > On Tue, 29 Sep 2015, Luiz Americo Pereira Camara wrote: > > Unit uniqueinstanceraw >> > > >> Please look carefully >> > > My sincere apologies, > > No problem. To be clear, i don't plead to uniqueinstance be used by fpc or Lazarus at all. This is the message i sent to Lazarus dev list when discussing the possibility of using in Lazarus IDE: " See https://github.com/blikblum/luipack/blob/master/uniqueinstance/uniqueinstanceraw.pas and https://github.com/blikblum/luipack/blob/master/uniqueinstance/uniqueinstancebase.pas This all the code that is needed to implement unique instance feature on top of simpleipc. Such simple logic could even be copied to IDE instead of using the package itself " On the other side, i still think that should be kept out of TCustomApplication. While the simple requirement of checking another instance is easy to implement into TCustomApplication, others may want more features / control (See bug report for examples). Those that need it would duplicate part of the code. Maybe create fpUniqueInstance on top of Ondrej work, making extensible and plugabble? Luiz ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel
Re: [fpc-devel] simpleipc issues
On 09/15/2015 12:07 PM, Tomas Hajny wrote: On Tue, September 15, 2015 10:04, Michael Van Canneyt wrote: On Tue, 15 Sep 2015, Ondrej Pokorny wrote: . . Are there some high level crossplatform semaphore functions in the FCL? The cthreads/cIntSemaphoreOpen etc. seem to be available on unix only. What about OS/2? Careful, these are thread semaphores, I think. I am talking about cross-process semaphores. They are in the baseunix/unix units. I suppose OS/2 has semaphores, but Tomas will need to confirm. OS/2 certainly has semaphores (three types of them, in fact ;-) - event semaphores, mutex semaphores and muxwait semaphores). and there's also file based semaphores still used by a huge number of programs to signal needed actions between disparate programs that may be pressed into operation together ;) -- NOTE: No off-list assistance is given without prior approval. *Please keep mailing list traffic on the list* unless private contact is specifically requested and granted. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel
[fpc-devel] simpleipc issues
I've developed a "single/multiple instances" feature for the Lazarus IDE. For this feature I need an IPC. First I tried to use simpleipc but I have struggled on bugs and missing functionality. Particularly what I found: 1.) BUG: You can register multiple servers on Windows with the same name (with StartServer procedure). 2.) Small issue: simpleipc uses exceptions if something fails (e.g. in StartServer procedure). I would prefer using a function with boolean result (true = OK, false = fail). 3.) MISSING: Multiple clients (from different processes) talk to one server. 4.) MISSING: Client is able to receive a response on a request. 5.) MISSING: (Optionally, not default) client sends a request to a server that isn't running. The server is able to handle these requests when it is started. So I developed "advancedipc.pas" that does what I need. It can do everything that is in simpleirc but a little bit differently (I changed the exception behavior and also method names). The question is now what to do? 1.) Include advancedipc.pas into FCL as a standalone unit. 2.) Make advancedipc.pas backwards compatible to simpleipc.pas and use the new code in simpleipc.pas. I attached the advancedipc.pas file. The discussion about "multiple instances" is here: http://bugs.freepascal.org/view.php?id=8051 Ondrej { *** Please use appropriate header *** License standard LCL (GPL/LGPL ?) Author: Ondrej Pokorny Abstract: Unit implementing two-way (request/response) IPC between 1 server and more clients **} unit AdvancedIPC; {$mode objfpc}{$H+} interface uses {$IFDEF UNIX} baseunix, {$endif} sysutils, Classes; const HEADER_VERSION = 1; type TMessageHeader = packed record HeaderVersion: Integer; FileLock: Byte;//0 = unlocked, 1 = locked MsgType: Integer; MsgLen: Integer; MsgVersion: Integer; end; TFileHandle = Classes.THandle; TReleaseHandleStream = class(THandleStream) public destructor Destroy; override; end; TIPCBase = class private FGlobal: Boolean; FFileName: string; FServerName: string; FMessageVersion: Integer; protected class function ServerNameToFileName(const aServerName: string; const aGlobal: Boolean): string; function GetResponseFileName(const aMsgID: Integer): string; function GetResponseFileName(const aRequestFileName: string): string; function GetRequestPrefix: string; function GetRequestFileName(const aMsgID: Integer): string; function RequestFileNameToMsgID(const aFileName: string): Integer; function GetUniqueRequest(out outFileName: string): Integer; procedure SetServerName(const aServerName: string); virtual; procedure SetGlobal(const aGlobal: Boolean); virtual; function CanReadMessage(const aFileName: string; out outStream: TStream; out outMsgType, outMsgLen: Integer): Boolean; procedure DoPostMessage(const aFileName: string; const aMsgType: Integer; const aStream: TStream); property FileName: string read FFileName; public constructor Create; virtual; public class procedure FindRunningServers(const aServerNamePrefix: string; const outServerNames: TStrings; const aGlobal: Boolean = False); class function ServerIsRunning(const aServerName: string; const aGlobal: Boolean = False): Boolean; property ServerName: string read FServerName write SetServerName; property Global: Boolean read FGlobal write SetGlobal; property MessageVersion: Integer read FMessageVersion write FMessageVersion; end; TIPCClient = class(TIPCBase) var FLastMsgFileName: string; public function PostRequest(const aMsgType: Integer; const aStream: TStream): Integer;//returns ID function PeekResponse(const aStream: TStream; var outMsgType: Integer; const aTimeOut: Integer): Boolean; procedure DeleteRequest; function ServerRunning: Boolean; end; TIPCServer = class(TIPCBase) private FFileHandle: TFileHandle; FActive: Boolean; function FindFirstRequest(out outFileName: string; out outStream: TStream; out outMsgType, outMsgLen: Integer): Integer; protected procedure SetServerName(const aServerName: string); override; procedure SetGlobal(const aGlobal: Boolean); override; public constructor Create; override; destructor Destroy; override; public function PeekRequest(const aStream: TStream; var outMsgType: Integer): Boolean; overload; function PeekRequest(const aStream: TStream; var outMsgID, outMsgType: Integer): Boolean; overload; function PeekRequest(const aStream: TStream; var outMsgID, outMsgType: Integer; const aTimeOut: Integer): Boolean; overload; procedure PostResponse(const aMsgID: Integer; const aMsgType: Integer; const aStream: TStream); function FindHighestPendingRequestId: Integer; function GetPendingRequestCount: Integer; function StartServer(const
Re: [fpc-devel] simpleipc issues
On Tue, September 15, 2015 08:58, Michael Van Canneyt wrote: > On Mon, 14 Sep 2015, Ondrej Pokorny wrote: > >> I've developed a "single/multiple instances" feature for the Lazarus >> IDE. For >> this feature I need an IPC. First I tried to use simpleipc but I have >> struggled on bugs and missing functionality. >> >> Particularly what I found: >> 1.) BUG: You can register multiple servers on Windows with the same name >> (with StartServer procedure). >> 2.) Small issue: simpleipc uses exceptions if something fails (e.g. in >> StartServer procedure). I would prefer using a function with boolean >> result >> (true = OK, false = fail). >> 3.) MISSING: Multiple clients (from different processes) talk to one >> server. >> 4.) MISSING: Client is able to receive a response on a request. >> 5.) MISSING: (Optionally, not default) client sends a request to a >> server >> that isn't running. The server is able to handle these requests when it >> is >> started. >> >> So I developed "advancedipc.pas" that does what I need. It can do >> everything >> that is in simpleirc but a little bit differently (I changed the >> exception >> behavior and also method names). The question is now what to do? >> 1.) Include advancedipc.pas into FCL as a standalone unit. >> 2.) Make advancedipc.pas backwards compatible to simpleipc.pas and use >> the >> new code in simpleipc.pas. > > Well, both 1 and 2 are the way to go if you want it included in FPC :-) > > I see no point in including duplicate functionality, it means duplicate > maintenance. > You can keep it as separate units, just make sure simpleipc runs on top of > advancedipc. . . One additional remark - it would be useful to have a test/example using advancedipc directly, so that users can base their code on it and platform maintainers can test easily and reliably whether the code works correctly on their platform (e.g. me on OS/2 ;-) ). Tomas ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel
Re: [fpc-devel] simpleipc issues
On Mon, 14 Sep 2015, Ondrej Pokorny wrote: I've developed a "single/multiple instances" feature for the Lazarus IDE. For this feature I need an IPC. First I tried to use simpleipc but I have struggled on bugs and missing functionality. Particularly what I found: 1.) BUG: You can register multiple servers on Windows with the same name (with StartServer procedure). 2.) Small issue: simpleipc uses exceptions if something fails (e.g. in StartServer procedure). I would prefer using a function with boolean result (true = OK, false = fail). 3.) MISSING: Multiple clients (from different processes) talk to one server. 4.) MISSING: Client is able to receive a response on a request. 5.) MISSING: (Optionally, not default) client sends a request to a server that isn't running. The server is able to handle these requests when it is started. So I developed "advancedipc.pas" that does what I need. It can do everything that is in simpleirc but a little bit differently (I changed the exception behavior and also method names). The question is now what to do? 1.) Include advancedipc.pas into FCL as a standalone unit. 2.) Make advancedipc.pas backwards compatible to simpleipc.pas and use the new code in simpleipc.pas. Well, both 1 and 2 are the way to go if you want it included in FPC :-) I see no point in including duplicate functionality, it means duplicate maintenance. You can keep it as separate units, just make sure simpleipc runs on top of advancedipc. As for no semaphores on linux: of course there are semaphores, they exist since many many years, they are part of POSIX: "man sem_overview". Michael. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel
Re: [fpc-devel] simpleipc issues
On 15.09.2015 08:58, Michael Van Canneyt wrote: On Mon, 14 Sep 2015, Ondrej Pokorny wrote: I've developed a "single/multiple instances" feature for the Lazarus IDE. For this feature I need an IPC. First I tried to use simpleipc but I have struggled on bugs and missing functionality. Particularly what I found: 1.) BUG: You can register multiple servers on Windows with the same name (with StartServer procedure). 2.) Small issue: simpleipc uses exceptions if something fails (e.g. in StartServer procedure). I would prefer using a function with boolean result (true = OK, false = fail). 3.) MISSING: Multiple clients (from different processes) talk to one server. 4.) MISSING: Client is able to receive a response on a request. 5.) MISSING: (Optionally, not default) client sends a request to a server that isn't running. The server is able to handle these requests when it is started. So I developed "advancedipc.pas" that does what I need. It can do everything that is in simpleirc but a little bit differently (I changed the exception behavior and also method names). The question is now what to do? 1.) Include advancedipc.pas into FCL as a standalone unit. 2.) Make advancedipc.pas backwards compatible to simpleipc.pas and use the new code in simpleipc.pas. Well, both 1 and 2 are the way to go if you want it included in FPC :-) I see no point in including duplicate functionality, it means duplicate maintenance. You can keep it as separate units, just make sure simpleipc runs on top of advancedipc. As for no semaphores on linux: of course there are semaphores, they exist since many many years, they are part of POSIX: "man sem_overview". Michael. Thanks a lot Michael! I'll prepare it, write (unit) tests and some demo and then send them over! Thanks also for the semaphore information. I couldn't find anything on the internet, therefore I thought Lazarus doesn't support them. Are there some high level crossplatform semaphore functions in the FCL? The cthreads/cIntSemaphoreOpen etc. seem to be available on unix only. What about OS/2? What about Windows? It looks like semaphores are supported only since XP: https://msdn.microsoft.com/en-us/library/windows/desktop/ms682438(v=vs.85).aspx . Is this a problem for the FCL? (Basically, semaphores are only needed on unix due to the file locking. But I am still interested.) If I'll have more questions, I'll write them here. Ondrej ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel
Re: [fpc-devel] simpleipc issues
On Tue, 15 Sep 2015, Ondrej Pokorny wrote: On 15.09.2015 08:58, Michael Van Canneyt wrote: On Mon, 14 Sep 2015, Ondrej Pokorny wrote: I've developed a "single/multiple instances" feature for the Lazarus IDE. For this feature I need an IPC. First I tried to use simpleipc but I have struggled on bugs and missing functionality. Particularly what I found: 1.) BUG: You can register multiple servers on Windows with the same name (with StartServer procedure). 2.) Small issue: simpleipc uses exceptions if something fails (e.g. in StartServer procedure). I would prefer using a function with boolean result (true = OK, false = fail). 3.) MISSING: Multiple clients (from different processes) talk to one server. 4.) MISSING: Client is able to receive a response on a request. 5.) MISSING: (Optionally, not default) client sends a request to a server that isn't running. The server is able to handle these requests when it is started. So I developed "advancedipc.pas" that does what I need. It can do everything that is in simpleirc but a little bit differently (I changed the exception behavior and also method names). The question is now what to do? 1.) Include advancedipc.pas into FCL as a standalone unit. 2.) Make advancedipc.pas backwards compatible to simpleipc.pas and use the new code in simpleipc.pas. Well, both 1 and 2 are the way to go if you want it included in FPC :-) I see no point in including duplicate functionality, it means duplicate maintenance. You can keep it as separate units, just make sure simpleipc runs on top of advancedipc. As for no semaphores on linux: of course there are semaphores, they exist since many many years, they are part of POSIX: "man sem_overview". Michael. Thanks a lot Michael! I'll prepare it, write (unit) tests and some demo and then send them over! Thanks also for the semaphore information. I couldn't find anything on the internet, therefore I thought Lazarus doesn't support them. Are there some high level crossplatform semaphore functions in the FCL? The cthreads/cIntSemaphoreOpen etc. seem to be available on unix only. What about OS/2? Careful, these are thread semaphores, I think. I am talking about cross-process semaphores. They are in the baseunix/unix units. I suppose OS/2 has semaphores, but Tomas will need to confirm. But if OS/2 currently does not support simpleIPC, then the point is moot anyway. What about Windows? It looks like semaphores are supported only since XP: https://msdn.microsoft.com/en-us/library/windows/desktop/ms682438(v=vs.85).aspx . Is this a problem for the FCL? (Basically, semaphores are only needed on unix due to the file locking. But I am still interested.) Officially, FPC no longer supports Windows 95. The compiler and most parts of the RTL will function on Windows 95, so it will do some basic stuff. For the FCL, I really do not see this as a problem. If you need advanced IPC such as this, you will no longer be using Windows 95. We must be practical in such matters. Michael. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel
Re: [fpc-devel] simpleipc issues
On 15/09/15 13:33, Ondrej Pokorny wrote: This is because Michael Van Canneyt pointed me to "man sem_overview". The first Google search pointed me to http://linux.die.net/man/7/sem_overview where I found the "Named semaphores" with functions sem_open, sem_close etc. with the description that they can be used across processes. A quick search in FPC sources pointed me again to the cthreads unit. All semaphore use has been removed from the cthreads unit in the mean time. They also should not be used on OS X anymore, because Apple forbids their use in applications submitted to their appstore (I guess because it is difficult for system frameworks to automatically determine whether they are only used in safe way; i.e., in a way that doesn't make the codesigned host application into a proxy for any other application to carry out operations on their behalf). Jonas ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel
Re: [fpc-devel] simpleipc issues
On 15.09.2015 13:22, Michael Schnell wrote: On 09/15/2015 01:09 PM, Michael Van Canneyt wrote: IPC = Inter PROCESS Communication. I know that you know this, but Ondrej is talking about cthreads in one of his message, so I tried to politely set a trigger. -Michael This is because Michael Van Canneyt pointed me to "man sem_overview". The first Google search pointed me to http://linux.die.net/man/7/sem_overview where I found the "Named semaphores" with functions sem_open, sem_close etc. with the description that they can be used across processes. A quick search in FPC sources pointed me again to the cthreads unit. I haven't done any Linux development with semaphores, so sorry if I am completely wrong here. I will also welcome if you correct me. BUT semaphores are not directly needed by the IPC. simpleipc doesn't use them either. It would be nice to have solved the issue with double file locks on unix, but this is not the core problem. Ondrej ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel
Re: [fpc-devel] simpleipc issues
On Tue, 15 Sep 2015, Michael Schnell wrote: On 09/14/2015 03:56 PM, Ondrej Pokorny wrote: 3.) MISSING: Multiple clients (from different processes) talk to one server. 4.) MISSING: Client is able to receive a response on a request. 5.) MISSING: (Optionally, not default) client sends a request to a server that isn't running. The server is able to handle these requests when it is started. Do I understand correctly that you are talking about "real" inter-Process communication and not inter-Tread-Communication within the same project ? (IMHO, this would require completely different paradigms.) IPC = Inter PROCESS Communication. Michael. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel
Re: [fpc-devel] simpleipc issues
On 09/15/2015 01:09 PM, Michael Van Canneyt wrote: IPC = Inter PROCESS Communication. I know that you know this, but Ondrej is talking about cthreads in one of his message, so I tried to politely set a trigger. -Michael ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel
Re: [fpc-devel] simpleipc issues
On Tue, September 15, 2015 10:04, Michael Van Canneyt wrote: > On Tue, 15 Sep 2015, Ondrej Pokorny wrote: . . >> Are there some high level crossplatform semaphore functions in the FCL? >> The >> cthreads/cIntSemaphoreOpen etc. seem to be available on unix only. What >> about >> OS/2? > > Careful, these are thread semaphores, I think. > I am talking about cross-process semaphores. They are in the baseunix/unix > units. > > I suppose OS/2 has semaphores, but Tomas will need to confirm. OS/2 certainly has semaphores (three types of them, in fact ;-) - event semaphores, mutex semaphores and muxwait semaphores). > But if OS/2 currently does not support simpleIPC, then the point is moot > anyway. See packages/fcl-process/src/os2/simpleipc.inc. Moreover, the code posted by Ondrej does not contain anything that should not compile on OS/2 at the first sight, that's why I wanted to have a test allowing to check whether it really works. The fact that sending messages across processes would be usually implemented differently if using OS/2 API features directly may not be so important. Tomas ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel
Re: [fpc-devel] simpleipc issues
On Tue, 15 Sep 2015, Tomas Hajny wrote: On Tue, September 15, 2015 10:04, Michael Van Canneyt wrote: On Tue, 15 Sep 2015, Ondrej Pokorny wrote: . . Are there some high level crossplatform semaphore functions in the FCL? The cthreads/cIntSemaphoreOpen etc. seem to be available on unix only. What about OS/2? Careful, these are thread semaphores, I think. I am talking about cross-process semaphores. They are in the baseunix/unix units. I suppose OS/2 has semaphores, but Tomas will need to confirm. OS/2 certainly has semaphores (three types of them, in fact ;-) - event semaphores, mutex semaphores and muxwait semaphores). Excellent ! But if OS/2 currently does not support simpleIPC, then the point is moot anyway. See packages/fcl-process/src/os2/simpleipc.inc. Moreover, the code posted by Ondrej does not contain anything that should not compile on OS/2 at the first sight, that's why I wanted to have a test allowing to check whether it really works. The fact that sending messages across processes would be usually implemented differently if using OS/2 API features directly may not be so important. Well, the implementation looks as if it will work on all platforms. Michael. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel
Re: [fpc-devel] simpleipc issues
On 09/14/2015 03:56 PM, Ondrej Pokorny wrote: 3.) MISSING: Multiple clients (from different processes) talk to one server. 4.) MISSING: Client is able to receive a response on a request. 5.) MISSING: (Optionally, not default) client sends a request to a server that isn't running. The server is able to handle these requests when it is started. Do I understand correctly that you are talking about "real" inter-Process communication and not inter-Tread-Communication within the same project ? (IMHO, this would require completely different paradigms.) I understand that IPC is done with non-Lazarus projects in mind. Hence it is done to be used "straight forward" independent of the Lazarus Event Queue. If doing something on top of SimpleIPC it might be viable to consider Event Queue integration for Lazarus users, as well (but If you don't consider Lazarus this might be a completely unrelated issue). -Michael ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel
Re: [fpc-devel] simpleipc issues
On 09/15/2015 02:43 PM, Michael Van Canneyt wrote: With my paranoid mind I of course assumed you were hijacking the thread... Of course I was eagerly waiting on Ondrej to confirm that he was looking for thread support :-) :-) :-) -Michael ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel
Re: [fpc-devel] simpleipc issues
On Tue, 15 Sep 2015, Michael Schnell wrote: On 09/15/2015 01:09 PM, Michael Van Canneyt wrote: IPC = Inter PROCESS Communication. I know that you know this, but Ondrej is talking about cthreads in one of his message, so I tried to politely set a trigger. With my paranoid mind I of course assumed you were hijacking the thread... Michael. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel