unit TagRWDouble;

interface
uses
  SyncObjs,
  SysUtils,
  Tags;

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

	  FValueRd: double;
	  FValueWr: double;
    FValueWrLast: double;
  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

{ TTagRWDouble }

constructor TTagRWDouble.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 TTagRWDouble.Destroy;
begin
  FLockWrLast.Free;
  FLockRd.Free;
  inherited;
end;


function TTagRWDouble.getType: TTagType;
begin
  Result := ttDOUBLE;
end;

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

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

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

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


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

function TTagRWDouble.getInt: integer;
begin
  FLockRd.BeginRead;
  Result := Trunc(FValueRd);
  FLockRd.EndRead;
end;

function TTagRWDouble.getLong: int64;
begin
  FLockRd.BeginRead;
  Result := Trunc(FValueRd);
  FLockRd.EndRead;
end;

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

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


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

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

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

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

procedure TTagRWDouble.setString(const value: string);
begin
  FMonitor.Enter;
	FValueWr := StrToFloatDef(value, 0.0);
	FValueWrChanged := true;
  FMonitor.Leave;
end;




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

function TTagRWDouble.getWriteValInt: integer;
begin
  FLockWrLast.BeginRead;
  Result := Trunc(FValueWrLast);
  FLockWrLast.EndRead;
end;

function TTagRWDouble.getWriteValLong: int64;
begin
  FLockWrLast.BeginRead;
  Result := Trunc(FValueWrLast);
  FLockWrLast.EndRead;
end;

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

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


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

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

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

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

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

end.
