Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / lazarus / 2012-08

timer in a console application

12 messages · 6 people ·

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Andrea Mauri

Dear all,
I have a console application that performs calculations iteratively on different objects.
I would like to set a time limit for the calculation on a single object. i.e. calculation starts on object 1, in order to start calculation on object 2 the calculations on object 1 must be finished or the time limit for the calculation on a single object is reached. if the calculation time limit is reached I would like to stop calculation on object 1 and pass to object 2 and so on for all the objects.

Someone has suggestions?
Andrea

Reply by email

Michael Schnell
to Andrea Mauri

TTimer and things like Application.QueuAsyncCall, TThread.Synchronize need an Event Queue to do their work.

Currently there is no "Widget Type" (aka interface) that does not need a GUI but provides an Event Queue.

So you can't create a Console Application (or a Daemon or a Web Service or similar stuff) a that uses TTimer or event driver inter-thread communication. Such applications do a single run-through pass and are not able to react on multiple condition at the same time.

-Michael

Reply by email

Unknown author
to Andrea Mauri: I have a console application that performs calculations iteratively on different objects.…
Andrea Mauri wrote 9 lines
Dear all, I have a console application that performs calculations iteratively on different objects. I would like to set a time limit for the calculation on a single object. i.e. calculation starts on object 1, in order to start calculation on object 2 the calculations on object 1 must be finished or the time limit for the calculation on a single object is reached. if the calculation time limit is reached I would like to stop calculation on object 1 and pass to object 2 and so on for all the objects.

The fptimer unit has a timer that can be run in the main thread of an application, in a console application.

If your main thread controls the time limits then this can be used to control another thread(s) which do(es) the calculations.

Michael.

Reply by email

Andrea Mauri
to Unknown author

Il 10/08/2012 13:01, ha scritto:

The fptimer unit has a timer that can be run in the main thread of an application, in a console application.

I tried using fptimer in my objects but it seems that it does not work as expected.
See the simple code below, a console app using a tfptimer to stop the execution of a procedure, but the ontimer event is never called.

If your main thread controls the time limits then this can be used to control another thread(s) which do(es) the calculations.

Must I use in some way the threads? I never used threads, so I don't know exactly what to do.

program Project1;
{$mode objfpc}{$H+}
uses
   {$IFDEF UNIX}{$IFDEF UseCThreads}
   cthreads,
   {$ENDIF}{$ENDIF}
   Classes, SysUtils, CustApp, fpTimer
   { you can add units after this };
type
   { TMyApplication }
   TMyApplication = class(TCustomApplication)
   protected
     procedure DoRun; override;
   private
     fStopExecution: boolean;
     fTimer: TFPTimer;
     procedure StopExecution(Sender: TObject);
     procedure DoCalculation(i: integer);
   public
     constructor Create(TheOwner: TComponent); override;
     destructor Destroy; override;
     procedure WriteHelp; virtual;
   end;

{ TMyApplication }

procedure TMyApplication.DoRun;
var
   ErrorMsg: String;
   i, n: integer;
begin
   // quick check parameters
   ErrorMsg:=CheckOptions('h','help');
   if ErrorMsg'' then begin
     ShowException(Exception.Create(ErrorMsg));
     Terminate;
     Exit;
   end;
   // parse parameters
   if HasOption('h','help') then begin
     WriteHelp;
     Terminate;
     Exit;
   end;
   { add your program here }
   n:= 10;
   for i:= 0 to n do
   begin
     fStopExecution:= False;
     fTimer.StartTimer;
     DoCalculation(i);
     fTimer.StopTimer;
   end;
   // stop program loop
   Terminate;
end;
procedure TMyApplication.StopExecution(Sender: TObject);
begin
   fStopExecution:= True;
end;
procedure TMyApplication.DoCalculation(i: integer);
begin
   write(i, '-');
   while not fStopExecution do
     inc(i);
   writeln(i);
end;
constructor TMyApplication.Create(TheOwner: TComponent);
begin
   inherited Create(TheOwner);
   StopOnException:=True;
end;
destructor TMyApplication.Destroy;
begin
   inherited Destroy;
end;
procedure TMyApplication.WriteHelp;
begin
   { add your help code here }
   writeln('Usage: ',ExeName,' -h');
end;
var
   Application: TMyApplication;
begin
   Application:=TMyApplication.Create(nil);
   Application.Title:='My Application';
   Application.fTimer:= TFPTimer.Create(nil);
   Application.fTimer.Interval:= 1000;
   Application.fTimer.OnTimer:= @Application.StopExecution;
   Application.Run;
   Application.Free;
end.

Reply by email

Michael Schnell
to Andrea Mauri
Andrea Mauri wrote
Must I use in some way the threads?

That is exactly what Michael vC said in his mail.

In a console application the main thread just starts, does some calculations and runs right until returning and with that terminates the program. If you want to so a longer living thingy, you need to hols the main thread e.g with sleep(). If during that time some "Event" needs to be handled, only a thread can do this.

-Michael

Reply by email

Unknown author
to Andrea Mauri: Il 10/08/2012 13:01, ha scritto: I tried using fptimer in my objects but it seems that…
Andrea Mauri wrote 9 lines
Il 10/08/2012 13:01, ha scritto: > > The fptimer unit has a timer that can be run in the main thread of an > application, in a console application. I tried using fptimer in my objects but it seems that it does not work as expected. See the simple code below, a console app using a tfptimer to stop the execution of a procedure, but the ontimer event is never called.

You must call checksynchronize at regular intervals in the main thread. How you do this, depends on your application.

Show quoted text 7 lines
> > If your main thread controls the time limits then this can be used to > control another thread(s) which do(es) the calculations. Must I use in some way the threads? I never used threads, so I don't know exactly what to do.

FPTimer uses a thread to generate the timer events using synchronize. The main thread needs to call checksynchronize at an interval smaller than the timer slice, obviously.

Somethin like:

  procedure TMyApplication.DoCalculation(i: integer);
  begin
   write(i, '-');
   while not fStopExecution do
     begin
     CheckSynchronize;
     inc(i);
     end;
   writeln(i);
  end;

Just add Cthreads if you are on linux. On Windows, you don't need to do anything.

Michael.

Show quoted text 114 lines
program Project1; {$mode objfpc}{$H+} uses {$IFDEF UNIX}{$IFDEF UseCThreads} cthreads, {$ENDIF}{$ENDIF} Classes, SysUtils, CustApp, fpTimer { you can add units after this }; type { TMyApplication } TMyApplication = class(TCustomApplication) protected procedure DoRun; override; private fStopExecution: boolean; fTimer: TFPTimer; procedure StopExecution(Sender: TObject); procedure DoCalculation(i: integer); public constructor Create(TheOwner: TComponent); override; destructor Destroy; override; procedure WriteHelp; virtual; end; { TMyApplication } procedure TMyApplication.DoRun; var ErrorMsg: String; i, n: integer; begin // quick check parameters ErrorMsg:=CheckOptions('h','help'); if ErrorMsg'' then begin ShowException(Exception.Create(ErrorMsg)); Terminate; Exit; end; // parse parameters if HasOption('h','help') then begin WriteHelp; Terminate; Exit; end; { add your program here } n:= 10; for i:= 0 to n do begin fStopExecution:= False; fTimer.StartTimer; DoCalculation(i); fTimer.StopTimer; end; // stop program loop Terminate; end; procedure TMyApplication.StopExecution(Sender: TObject); begin fStopExecution:= True; end; procedure TMyApplication.DoCalculation(i: integer); begin write(i, '-'); while not fStopExecution do inc(i); writeln(i); end; constructor TMyApplication.Create(TheOwner: TComponent); begin inherited Create(TheOwner); StopOnException:=True; end; destructor TMyApplication.Destroy; begin inherited Destroy; end; procedure TMyApplication.WriteHelp; begin { add your help code here } writeln('Usage: ',ExeName,' -h'); end; var Application: TMyApplication; begin Application:=TMyApplication.Create(nil); Application.Title:='My Application'; Application.fTimer:= TFPTimer.Create(nil); Application.fTimer.Interval:= 1000; Application.fTimer.OnTimer:= @Application.StopExecution; Application.Run; Application.Free; end. -- _______________________________________________ Lazarus mailing list http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus

Reply by email

Jürgen Hestermann
to Michael Schnell: That is exactly what Michael vC said in his mail. In a console application the main…
Michael Schnell wrote 7 lines
On 08/10/2012 01:47 PM, Andrea Mauri wrote: > > Must I use in some way the threads? > That is exactly what Michael vC said in his mail. In a console application the main thread just starts, does some calculations and runs right until returning and with that terminates the program. If you want to so a longer living thingy, you need to hols the main thread e.g with sleep(). If during that time some "Event" needs to be handled, only a thread can do this.

This is not necessariliy how it has to be. I have lots of programs that have a simple endless loop with a delay() that checks for something in regular time slots:

repeat
    check something;
    delay(100000);
until false;

Reply by email

Michael Schnell
to Unknown author: You must call checksynchronize at regular intervals in the main thread. How you do this,…
Show quoted text 5 lines
while not fStopExecution do begin CheckSynchronize; inc(i); end;

This results in 100 % CPU (in a single CPU system) so not a very good idea IMHO. (Even the timer thread is crippled by the main thread.)

If you can live with some latency I would do something like:

    while not fStopExecution do
      begin
      CheckSynchronize;
      sleep(Max_Latancy);
      end;

-Michael

Reply by email

Sven Barth
to Michael Schnell
Michael Schnell wrote 16 lines
On 08/10/2012 02:38 PM, wrote: > while not fStopExecution do > begin > CheckSynchronize; > inc(i); > end; This results in 100 % CPU (in a single CPU system) so not a very good idea IMHO. (Even the timer thread is crippled by the main thread.) If you can live with some latency I would do something like: while not fStopExecution do begin CheckSynchronize; sleep(Max_Latancy); end;

You know that the "inc(i)" in the above code is where the author's calculation takes place? So the "CheckSynchronize" call would just be between different calculation steps where it's safe to have the execution stopped (though it might be better to put the "CheckSynchronize" to the end of the loop).

Regards,
Sven

Reply by email

Andrea Mauri
to Sven Barth

Il 10/08/2012 14:59, Sven Barth ha scritto:

Show quoted text 21 lines
>> while not fStopExecution do >> begin >> CheckSynchronize; >> inc(i); >> end; > This results in 100 % CPU (in a single CPU system) so not a very good > idea IMHO. (Even the timer thread is crippled by the main thread.) > > If you can live with some latency I would do something like: > > while not fStopExecution do > begin > CheckSynchronize; > sleep(Max_Latancy); > end; You know that the "inc(i)" in the above code is where the author's calculation takes place? So the "CheckSynchronize" call would just be between different calculation steps where it's safe to have the execution stopped (though it might be better to put the "CheckSynchronize" to the end of the loop).

Using CheckSynchronize the OnTimer event is fired.

I will try to better explain my problem.

My app must be as fast as possible, is checksynchronize cpu demanding? Here a simplified representation of my app:

begin
   loadMoleculeFiles;
   for i:= 0 to numberofmolecules-1 do
   begin
     ok:= calculatemoleculardescriptorsonmolecule(molecule_i);
     if not ok then
       writeln('time exceeded');
   end;
end;

calculatemoleculardescriptorsonmolecule can takes a lot of time (from few milliseconds to hours, if the molecule is huge or complex), I would like to put a user defined time limit to the calculation on a single molecule, if the time limit is reached the app should pass to the next molecule.
so the timer should check, during calculations, if the time per molecule is reached, then stop the actual molecule calculation.

andrea

Reply by email

Hans-Peter Diettrich
to Andrea Mauri: Il 10/08/2012 13:01, ha scritto: I tried using fptimer in my objects but it seems that…
Show quoted text 7 lines
Il 10/08/2012 13:01, ha scritto: > > The fptimer unit has a timer that can be run in the main thread of an > application, in a console application. I tried using fptimer in my objects but it seems that it does not work as expected.

What if you start simple, with only a console app that prints something on regular intervals? When this works, you can add threads. The main loop then can e.g. output the thread states at regular intervals. When this works, add the scheduling logic for multiple threads.

DoDi

Reply by email

Hans-Peter Diettrich
to Andrea Mauri: Il 10/08/2012 14:59, Sven Barth ha scritto: Using CheckSynchronize the OnTimer event is…
Show quoted text 20 lines
My app must be as fast as possible, is checksynchronize cpu demanding? Here a simplified representation of my app: begin loadMoleculeFiles; for i:= 0 to numberofmolecules-1 do begin ok:= calculatemoleculardescriptorsonmolecule(molecule_i); if not ok then writeln('time exceeded'); end; end; calculatemoleculardescriptorsonmolecule can takes a lot of time (from few milliseconds to hours, if the molecule is huge or complex), I would like to put a user defined time limit to the calculation on a single molecule, if the time limit is reached the app should pass to the next molecule. so the timer should check, during calculations, if the time per molecule is reached, then stop the actual molecule calculation.

Why do you ever want to *stop* an thread?

Do you want to *kill* threads taking too much time, discarding all the work done so far? Or do you want to resume them later?

If you want to get *all* calculations done, and minimize the *total* time, you have to start the long running threads first. When e.g. one thread takes more time than all others together, this thread will determine the total runtime of the program. Obviously every delay of this thread will increase the total runtime, leaving idle cores when all other threads have terminated. This certainly is not desireable, instead as many cores as available should have something to do all the time.

I'd sort the molecules by complexity, and start with the most complex ones. Whenever a thread finishes, the next (less complex) thread is started. If you want to see some results soon, one thread can start at the opposite end of the list, with the least complex molecules, so that you can continue with inspecing or working on these results, while the other calculations proceed.

In the simplest case you create an thread for every molecule, in *suspended* state, and put them all into a list (TThreadList?). Determine the maximum number of threads, which should run concurrently, e.g. from the number of cores of your CPU. Then resume that number of threads, starting with the longest ones. Whenever a thread terminates, it resumes the next waiting thread, until no more pending threads remain.

You also can implement an thread pool, with the known number of concurrent threads. When such a thread starts, it gets the next molecule from the pending list and starts calculation. When finished, the same thread gets the next molecule from the list, and starts calculating this one.

DoDi

Reply by email