unit imgjobs;

{$mode objfpc}{$H+}

interface

uses
  Classes,
  SysUtils,
  Forms,
  contnrs,
  syncobjs,
  process,
  imglog;

type

  { TQueuedJob }

  TQueuedJob = class
    Callback: TDataEvent;
    constructor Create( CB: TDataEvent);
    procedure Execute; virtual; abstract;
  end;

  { TJobQueue }

  TJobQueue = class(TThread)
  strict private
    //Event: TEvent;
    Wait: Boolean;
    Queue: TQueue;
  public
    constructor Create();
    destructor Destroy; override;
    procedure Execute; override;
    procedure WakeUp;
    procedure Terminate; reintroduce;
    procedure Enqueue(Job: TQueuedJob);
  end;

procedure JobsInit;
procedure JobsFinalize;


var
  JobQueue: TJobQueue;


implementation

{ TJobQueue }

constructor TJobQueue.Create;
begin
  inherited Create( True );

//  Event := TEvent.Create(nil, False, False, '');
  Wait:= False;
  Queue := TQueue.Create;
  FreeOnTerminate := True;
  Start;
end;

destructor TJobQueue.Destroy;
begin
//  Event.Free;
  Queue.Free;
  inherited Destroy;
end;

procedure TJobQueue.Execute;
var
  Item: TQueuedJob;
begin
  while ( not Terminated ) do
    begin
      //if Queue.Count = 0 then
      //  Event.WaitFor( INFINITE );
      Wait:= Queue.Count = 0;
      //while (( Wait ) AND ( not Terminated )) do;
      if (( Wait ) AND ( not Terminated )) then
        Suspend;
      Item := TQueuedJob( Queue.Pop );
      if ( Item <> nil ) then
        begin
          try
            Item.Execute;
          except
            on E: Exception do
              LogErrorThread( E.Message );
          end;
          Item.Free;
        end;
    end;
end;

procedure TJobQueue.WakeUp;
begin
  Wait:= False;
  Resume;
  Start;
//  Event.SetEvent;
end;

procedure TJobQueue.Terminate;
begin
  inherited Terminate;
  while Queue.Count > 0 do
    TQueuedJob( Queue.Pop ).Free;
  WakeUp;
end;

procedure TJobQueue.Enqueue(Job: TQueuedJob);
begin
  Queue.Push( Job );
  WakeUp;
end;

{ TQueuedJob }

constructor TQueuedJob.Create(CB: TDataEvent);
begin
  Callback := CB;
  inherited Create;
end;

procedure JobsInit;
begin
  JobQueue:= TJobQueue.Create();
end;

procedure JobsFinalize;
begin
  if ( Assigned( JobQueue )) then
    begin
      JobQueue.Terminate;
      JobQueue.WaitFor;
    end;
end;

end.

