unit TagRWLong;

interface
uses
  SyncObjs,
  SysUtils,
  Tags;

type
  TTagRWLong = class(TTagRW)
  private
    FLockRd: TMREWSync;
    FLockWrLast: TMREWSync;

	  FValueRd: Int64;
	  FValueWr: Int64;
    FValueWrLast: Int64;
  protected
	  procedure copyLastWriteToRead; override;   // ???
	  procedure copyWriteToLastWrite; override;
	  procedure copyWriteToRead; override;
  public
    constructor Create(const name: string; flags: Integer = 0);override;
    destructor Destroy; override;

    function getType: TTagType; override;
    function equalsValue(tag: TTag): Boolean; override;

    function getBool: boolean; override;
    function getInt: integer; override;
    function getLong: int64; override;
    function getDouble: double; override;
    function getString: string; override;

    procedure setBool(const value: boolean); override;
    procedure setInt(const value: integer); override;
    procedure setLong(const value: int64); override;
    procedure setDouble(const value: double); override;
    procedure setString(const value: string); override;


    function getWriteValBool: boolean; override;
    function getWriteValInt: integer; override;
    function getWriteValLong: int64; override;
    function getWriteValDouble: double; override;
    function getWriteValString: string; override;

    procedure setReadValBool(const value: boolean); override;
    procedure setReadValInt(const value: integer); override;
    procedure setReadValLong(const value: int64); override;
    procedure setReadValDouble(const value: double); override;
    procedure setReadValString(const value: string); override;
  end;


implementation

{ TTagRWLong }

constructor TTagRWLong.Create(const name: string; flags: Integer);
begin
  inherited Create(name, flags);
  FLockRd := TMREWSync.Create;
  FLockWrLast := TMREWSync.Create;

  FValueRd := 0;
  FValueWr := 0;
  FValueWrLast := 0;
end;

destructor TTagRWLong.Destroy;
begin
  FLockWrLast.Free;
  FLockRd.Free;
  inherited;
end;

function TTagRWLong.getType: TTagType;
begin
  Result := ttLONG;
end;

function TTagRWLong.equalsValue(tag: TTag): Boolean;
begin
  FLockRd.BeginRead;
  Result := tag.getLong() = FValueRd;
  FLockRd.EndRead;
end;

procedure TTagRWLong.copyLastWriteToRead;
begin
  FLockRd.BeginWrite;
  FValueRd := FValueWrLast;
  FLockRd.EndWrite;
end;

procedure TTagRWLong.copyWriteToLastWrite;
begin
  FLockWrLast.BeginWrite;
  FValueWrChanged := false;
	FValueWrLast := FValueWr;
  FLockWrLast.EndWrite;
end;

procedure TTagRWLong.copyWriteToRead;
begin
  FLockRd.BeginWrite;
  FValueRd := FValueWr;
  FLockRd.EndWrite;
end;


// general getters
function TTagRWLong.getBool: boolean;
begin
  FLockRd.BeginRead;
  Result := FValueRd <> 0;
  FLockRd.EndRead;
end;

function TTagRWLong.getInt: integer;
begin
  FLockRd.BeginRead;
  Result := FValueRd and $FFFFFFFF;
  FLockRd.EndRead;
end;

function TTagRWLong.getLong: int64;
begin
  FLockRd.BeginRead;
  Result := FValueRd;
  FLockRd.EndRead;
end;

function TTagRWLong.getDouble: double;
begin
  FLockRd.BeginRead;
  Result := FValueRd;
  FLockRd.EndRead;
end;

function TTagRWLong.getString: string;
begin
  FLockRd.BeginRead;
  Result := IntToStr(FValueRd);
  FLockRd.EndRead;
end;


// general setters
procedure TTagRWLong.setBool(const value: boolean);
begin
  FMonitor.Enter;
  if value then
    FValueWr := 1
  else
    FValueWr := 0;
  FValueWrChanged := true;
  FMonitor.Leave;
end;

procedure TTagRWLong.setInt(const value: integer);
begin
  FMonitor.Enter;
  FValueWr := value;
  FValueWrChanged := true;
  FMonitor.Leave;
end;

procedure TTagRWLong.setLong(const value: int64);
begin
  FMonitor.Enter;
  FValueWr := value;
  FValueWrChanged := true;
  FMonitor.Leave;
end;

procedure TTagRWLong.setDouble(const value: double);
begin
  FMonitor.Enter;
  FValueWr := Trunc(value);
  FValueWrChanged := true;
  FMonitor.Leave;
end;

procedure TTagRWLong.setString(const value: string);
begin
  FMonitor.Enter;
  FValueWr := StrToInt64Def(value, 0);
  FValueWrChanged := true;
  FMonitor.Leave;
end;




// rw getters
function TTagRWLong.getWriteValBool: boolean;
begin
  FLockWrLast.BeginRead;
  Result := FValueWrLast <> 0;
  FLockWrLast.EndRead;
end;

function TTagRWLong.getWriteValInt: integer;
begin
  FLockWrLast.BeginRead;
  Result := FValueWrLast and $FFFFFFFF;
  FLockWrLast.EndRead;
end;

function TTagRWLong.getWriteValLong: int64;
begin
  FLockWrLast.BeginRead;
  Result := FValueWrLast;
  FLockWrLast.EndRead;
end;

function TTagRWLong.getWriteValDouble: double;
begin
  FLockWrLast.BeginRead;
  Result := FValueWrLast;
  FLockWrLast.EndRead;
end;

function TTagRWLong.getWriteValString: string;
begin
  FLockWrLast.BeginRead;
  Result := IntToStr(FValueWrLast);
  FLockWrLast.EndRead;
end;


// rw getters
procedure TTagRWLong.setReadValBool(const value: boolean);
begin
  FLockRd.BeginWrite;
  if value then
    FValueRd := 1
  else
    FValueRd := 0;
  FLockRd.EndWrite;
end;

procedure TTagRWLong.setReadValInt(const value: integer);
begin
  FLockRd.BeginWrite;
  FValueRd := value;
  FLockRd.EndWrite;
end;

procedure TTagRWLong.setReadValLong(const value: int64);
begin
  FLockRd.BeginWrite;
  FValueRd := value;
  FLockRd.EndWrite;
end;

procedure TTagRWLong.setReadValDouble(const value: double);
begin
  FLockRd.BeginWrite;
  FValueRd := Trunc(value);
  FLockRd.EndWrite;
end;

procedure TTagRWLong.setReadValString(const value: string);
begin
  FLockRd.BeginWrite;
 	FValueRd := StrToInt64Def(value, 0);
  FLockRd.EndWrite;
end;


end.
