unit GraphQue;
{$IFDEF FPC}
  {$MODE DELPHI}{$H+}
{$ENDIF}
interface
uses
  Classes, SysUtils, Graphics,
  GraphSys;

procedure GraphOutExec;

Type
  TBaseGraphCommand=class
    class function NewInstance: TObject;override;
    procedure FreeInstance;override;
    procedure execute;virtual;abstract;
  end;

  TGraphCommand=Class(TBaseGraphCommand)
  end;

   TGraphCommand2=class(TGraphCommand)
     prev:TGraphCommand;
     constructor create(p:TGraphCommand);overload;
     destructor destroy;override;
  end;

type
  pBoolean=^Boolean;
  TReSetBoolean=class(TBaseGraphCommand)
    s:pBoolean;
    procedure register(var b:boolean);
    procedure execute;override;
    destructor destroy;override;
  end;

procedure AddQueue(s:TGraphCommand);
procedure AddQueueWait(s:TResetBoolean);


implementation
uses base,base2,affine;

function GetQMemory(size:PtrUInt):pointer;Forward;
procedure FreeQMemory(ptr:pointer;size:PtrUInt);Forward;

class function TBaseGraphCommand.NewInstance: TObject;
begin
   result:=InitInstance(getQMemory(instancesize));
end;

procedure TBaseGraphCommand.FreeInstance;
begin
   FillChar(pointer(self)^,instanceSize,0);
  // freeQMemory(pointer(self),instanceSize)
end;


constructor TGraphCommand2.create(p:TGraphCommand);
begin
   inherited create;
   prev:=p;
  end;

destructor TGraphCommand2.destroy;
begin
    if prev<>nil then prev.free;
    inherited destroy;
  end;

procedure  TReSetBoolean.register(var b:boolean);
begin
  s:=@b;
end;
procedure  TReSetBoolean.execute;
begin
  //s^:=false;
end;

destructor TReSetBoolean.destroy;
begin
  s^:=false;
  inherited destroy;
end;



var
queue:array[0..65535]of TBaseGraphCommand;
point0:word=0;
point1:word=0;

procedure GraphOutExec;
begin
   while queue[point1]<>nil do
   begin
      with queue[point1] do
         begin
            execute;
            free;
         end;
      queue[point1]:=nil;
      inc(point1);
      if point1=0 then exit; //描画する
   end;

end;

//var AddQueueCriticalSection: TRTLCriticalSection;

procedure AddQueue(s:TGraphCommand);
begin
    //EnterCriticalSection(AddQueueCriticalSection);
    while queue[point0]<>nil do
                               (TThread.CurrentThread).Yield;
    queue[point0]:=s;
    inc(point0);
    //LeaveCriticalSection(AddQueueCriticalSection);
end;

procedure AddQueueWait(s:TResetBoolean);
var
  b:boolean;
begin
    b:=true;
    s.register(b);
    //EnterCriticalSection(AddQueueCriticalSection);
    //while word(point0+1)=point1 do (TThread.CurrentThread).Yield;
    while queue[point0]<>nil do
                               (TThread.CurrentThread).Yield;
    queue[point0]:=s;
    inc(point0);
    //LeaveCriticalSection(AddQueueCriticalSection);
    while b do (TThread.CurrentThread).Yield  ;
end;

const
  QSize=8*65536*sizeof(pointer);
var
  QMemory:pointer;
  QHead:pointer;

function GetQMemory(size:PtrUInt):pointer;
var
  testPoint:Pointer;
begin
    result:=QHead;
    QHead:=result+Size;
    if QHead>QMemory+Qsize then
      begin
        result:=QMemory;
        QHead:=result+Size;
      end;
    TestPoint:=result;
    while TestPoint<QHead do
    begin
        while PtrUint(TestPoint^)<>0 do
                                (TThread.CurrentThread).Yield;
        inc(TestPoint,sizeof(Pointer));
    end;

end;

procedure FreeQMemory(ptr:pointer;size:PtrUInt);
begin
  FillChar(ptr^,size,0);
end;

initialization
//InitCriticalSection(AddQueueCriticalSection);
FillChar(queue,65536*sizeof(TObject),0);
QMemory:=AllocMem(QSize);
QHead:=Qmemory;



finalization
//DoneCriticalSection(AddQueueCriticalSection);
FreeMem(Qmemory,QSize);




end.

