Jump to content

t2000

Members
  • Content Count

    18
  • Joined

  • Last visited

Community Reputation

0 Neutral

Technical Information

  • Delphi-Version
    Delphi 10.4 Sydney
  1. Hello Primož I need a (possibly slimmed down) version for Linux (console server apps for web servers). Very short-term. Are there parts that I could use? I am currently using Units: OTLCommon, Otl Parallel, Otlsync, OtlCollections Types: TOmniValue, TOmniBlockingCollection, IOmniBackgroundworker, IOmniWorkitem, IOmniTaskControl, TOmniMessage Would be important No. 1: TOmniValue No. 2.1: parallel tasks for background work No. 2.2: a simple pipeline to be able to perform tasks in a serial one after the other If not, I would probably have to switch completely to Delphi Original Parallel Programming Library. Would be a pity. Kind regards Thomas
  2. Maybe someone else has Linux experience?
  3. Are there any approaches to compile OTL under Linux 64? We don't need everything from the Omnithreadlibrary, but it would be nice if the first things could be compiled. TOmniValue IOmniCriticalSection TOmniBlockingCollection IOmniBackgroundWorker Parallel.Async Async .Await and everything else that is easy to implement for the first Many thanks, Thomas
  4. The reason is, I have to use a hardware with a DLL/TLB/ActiveX (I cannot use DLL directly) for getting a code on every receipt, that I create. And this works only one by one, but I want to use this with my REST Microservice. Thank you all
  5. Ok, that was my first approach. (see 1st post) Only that I have to use TEvent and MsgWaitFor... instead of TWaitFor
  6. Windows API WaitMessage here: WaitMessage
  7. I have a command line application. Here are then Synchronize Test, the application loop and the ProcessMessage function function TServerApp.SynchronizeAndWait( AFuncToCall: TFunc<TOmniValue,TOmniValue>; AData: TOmniValue): TOmniValue; var CallRec : TFuncAndDataRec; oValue : TOmniValue; begin oValue := TOmniValue.Null; // TThread.Queue( nil, procedure TThread.Synchronize( nil, procedure begin //oValue := AFuncToCall( AData); oValue := TOmniValue.Create(['dhfljhadskjfasdkjfh']); end); Result := oValue; end; repeat try if not ProcessMessage(Msg) then WaitMessage; except on e: Exception do writeln(e.Message); end; until Terminated function TServerApp.ProcessMessage(var Msg: TMsg): Boolean; var Handled: Boolean; begin Result := False; //if PeekMessage(Msg, 0, 0, 0, PM_REMOVE) then begin if PeekMessage(Msg, NativeUInt(-1), 0, 0, PM_REMOVE) then begin Result := True; if Msg.Message <> WM_QUIT then begin Handled := False; case Msg.Message of sms_Processing : ; sms_Quit : FCloseTimer.Enabled := true; sms_Synchronize : SyncExecute; sms_Workerthread : CreateWorkItem; end; // case //if Assigned(FOnMessage) then // FOnMessage(Msg, Handled); if not Handled then begin TranslateMessage(Msg); DispatchMessage(Msg); end; end else begin FTerminate := True; end; end; end;
  8. Yes, that could work. TThread.Queue doesn't work, because I need the result. TThread.Synchronize doesn't work at all. I do not know why. I have a BackgroundWorker for some things to do (parallel and without a function result) Now I can try to create a Worker Thread. But the most important is, I need the result. I need it IN the communication thread. The communication thread has to wait.
  9. @Lars Fosdal Is CoInitialize fast enough? This is a communication thread (of a REST Microservice), which is called very often. I will test the TThread.Queue approach. It looks way too easy But I have to use: res := ProcessInMainThread(para);
  10. I am in a (foreign) communication thread. I must call a function in the MainThread and send the result back. My approach: I put a record with TFunc, Para in a TOmniValue and then in a TOmniBlockingCollection. I call: PostThreadMessage( System.MainThreadID, sms_Synchronize, 0, 0); And here (in the comm thread) I have to wait. Wait for a signal. ?? perhaps CreateEvent ?? In the main thread main messageloop I get the message. I take the record from the TOmniBlockingCollection and execute the function TFunc(para). Now I have to put the result in ... what? And signal the origin thread Is TWaitFor the right choice? Can you give me a sample? The WaitFor-Example from OmniThreadLibrary (test_59_TWaitFor) is too complex. Or is there a better way? Without use (my own) main thread message loop? Many thanks Thomas (The function must be run in the main thread, because it uses a windows com server object and this don't work in any threads. I have synchronize/serialize the calls from the communication thread)
  11. It doesn't work for me at all. No comment are shown Are there settings for it?
  12. t2000

    Problem with memory leak

    My mistake. I have used a TJSONObject with another TJSONObject in it. In the create function I added the second TJSONObject instead of TJSONObject.Clone. The inner TJSONObject was releasd twice. And then, and then, and then ... I thinkt there were all side effects.
  13. t2000

    Problem with memory leak

    I have used FastMM4. Pretty hard, but now I know the most important things about FastMM4. I think, I have a side effect from my REST Server thread that works with TMS XData. I use a function with TJSONObject as parameter. (over REST). And there is a hidden Exception in a JSON converter. I haven't seen these exception before. If I change the (REST-) function result to an integer, I can't reproduce the memory leak. With the build in tools, I couldn't get a stack trace. Thanks for the first. I keep an eye on it. The WM_QUIT. Thanks for the note. But I don't have windows here. This is a command line application and later I build a service. The messaging system is only for my own. Perhaps, I can use a WM_USER message number for quit the program internally.
  14. Hello I have a command line program and a memory leak after closing But not always. Only 10-15% of starts are ending with the memory leak. Unexpected Memory Leak An unexpected memory leak has occurred. The unexpected small block leaks are: 41 - 56 bytes: TOmniCriticalSection x 1 137 - 152 bytes: TFixedCriticalSection x 1 This is the code of a unit that works like Application in VCL or FMX. The important positions are: constructor create : make Backgroundworker from outside comes a call to the procedure TServerApp.Call I put a record into the BlockingCollection and send a message the message comes to ProcessMessage and I call CreateWorkItem for the BackgroundWorker In my test, I start the program, I'm in the "Run" procedure, I send a call with WM_QUIT (from outside) and the program ends. Where and how can I try to find the problem? Has anybody an idea? Many thanks, Thomas unit sng.ServerApp; interface uses System.Classes, System.SysUtils, System.Generics.Collections, Winapi.Windows, Winapi.Messages, OtlCommon, OtlParallel, OtlCollections; type TWorkItemCallRec = record ProcToCall: TProc<TOmniValue>; Data: TOmniValue; end; TModules = TList<TComponent>; TServerApp = class( TComponent) private FRunning: Boolean; FTerminate: Boolean; FServerAppName : String; FServerModules : TModules; FMsgDataColl : TOmniBlockingCollection; FWorker : IOmniBackgroundWorker; function ProcessMessage(var Msg: TMsg): Boolean; procedure ProcessMessages; procedure CreateWorkItem; procedure ProcessWorkItem(const workItem: IOmniWorkItem); procedure HandleRequestDone(const Sender: IOmniBackgroundWorker; const workItem: IOmniWorkItem); public constructor Create(AOwner: TComponent); override; destructor Destroy; override; procedure Run; procedure Shutdown; procedure SendQuit; procedure Call( AMsgCode: Cardinal; AProcToCall: TProc<TOmniValue>; AData: TOmniValue); property ServerAppName: String read FServerAppName; property Terminated: Boolean read FTerminate; end; var ServerApp: TServerApp; implementation uses OtlTaskControl, OtlComm; { TServerApp } function TServerApp.ProcessMessage(var Msg: TMsg): Boolean; var Handled: Boolean; begin Result := False; if PeekMessage(Msg, NativeUInt(-1), 0, 0, PM_REMOVE) then begin Result := True; if Msg.Message <> WM_QUIT then begin Handled := False; if Msg.Message > sms_OFFSET then CreateWorkItem; if not Handled then begin TranslateMessage(Msg); DispatchMessage(Msg); end; end else begin FTerminate := True; end; end; end; procedure TServerApp.ProcessMessages; var Msg: TMsg; begin while ProcessMessage(Msg) do {loop}; end; procedure TServerApp.CreateWorkItem; var LWorkItem : IOmniWorkItem; LOmniValue : TOmniValue; begin if not FMsgDataColl.Take( LOmniValue) then raise Exception.Create('Internal Error. ServerApp FMsgDataColl.Take'); LWorkItem := FWorker.CreateWorkItem( LOmniValue); FWorker.Schedule( LWorkItem); end; procedure TServerApp.ProcessWorkItem(const workItem: IOmniWorkItem); var CallRec: TWorkItemCallRec; begin CallRec := workItem.Data.CastTo<TWorkItemCallRec>; CallRec.ProcToCall( CallRec.Data); workItem.Result := 0; end; procedure TServerApp.HandleRequestDone(const Sender: IOmniBackgroundWorker; const workItem: IOmniWorkItem); var eClass: string; exc : Exception; begin if workItem.IsExceptional then begin eClass := workItem.FatalException.ClassName; exc := workItem.DetachException; DoLog( loaError, 'Exception: WorkItem: '+workItem.UniqueID.ToString+': '+eClass+':'+exc.Message); FreeAndNil(exc); end else DoLog( 'HandleRequestDone: '+workItem.UniqueID.ToString+': '+workItem.Result.AsString); end; constructor TServerApp.Create(AOwner: TComponent); begin inherited; FServerModules := TModules.Create; FMsgDataColl := TOmniBlockingCollection.Create; FWorker := Parallel.BackgroundWorker .NumTasks( cServerAppBackgroundTasks) .OnRequestDone( HandleRequestDone) .TaskConfig( Parallel.TaskConfig.OnMessage( sms_Processing, procedure (const task: IOmniTaskControl; const msg: TOmniMessage) begin DoLog('OnMessage: '+msg.MsgData.AsString); end)) .Execute( ProcessWorkItem); end; destructor TServerApp.Destroy; var i: Integer; begin FMsgDataColl.Free; for i := FServerModules.Count-1 downto 0 do FServerModules[i].Free; FServerModules.Free; inherited; end; procedure TServerApp.Run; var Msg: TMsg; v: TProc; begin FRunning := True; try // evtl. Exitproc setzen repeat try if not ProcessMessage(Msg) then WaitMessage; except on e: Exception do writeln(e.Message); end; until Terminated; finally FRunning := False; end; end; procedure TServerApp.Shutdown; begin // Stoppen aller Dienste FWorker.CancelAll; end; procedure TServerApp.SendQuit; begin FWorker.CancelAll; PostThreadMessage( System.MainThreadID, WM_QUIT, 0, 0); end; procedure TServerApp.Call(AMsgCode: Cardinal; AProcToCall: TProc<TOmniValue>; AData: TOmniValue); var CallRec : TWorkItemCallRec; oValue : TOmniValue; begin CallRec.ProcToCall := AProcToCall; CallRec.Data := AData; oValue := TOmniValue.FromRecord(CallRec); FMsgDataColl.Add( oValue); PostThreadMessage( System.MainThreadID, AMsgCode, 0, 0); end; initialization ServerApp := TServerApp.Create(nil); finalization ServerApp.Free; end.
  15. It works. I don't know why I didn't try it right away. I have taken the TOmniBlockingCollection (created in my ServerApp.MainObject) to write the data from the foreign thread and read it in MainThread. Is this ok or would you take the TOmniMessageQueue? (My data is a record with a reference to a procedure and a string variable)
×