Skip to content

Latest commit

 

History

History
113 lines (82 loc) · 3.5 KB

File metadata and controls

113 lines (82 loc) · 3.5 KB

ShiftAndRelease<T> class method

Project: Array Utilities Unit

Unit: DelphiDabbler.Lib.ArrayUtils

Record: TArrayUtils

Applies to: ~>0.1

type
  TCallback<T> = reference to procedure (const AElem: T);

class procedure ShiftAndRelease<T>(var A: TArray<T>;
  const AReleaser: TCallback<T>);
  static;

Description

Deletes the first element of a non-empty array and releases any resources associated with the deleted element.

The length of the array is reduced by one.

Parameters:

  • A - Array from which the element is to be removed and its associated resource released. The array is updated in place.

  • AReleaser - Procedure called for the deleted element that must release any resource associated with the element.

    Parameter(s):

    • AElem - Element whose associated resource is to be released.

Preconditions:

  • A must not be empty. An EAssertionFailed exception is raised otherwise.

Note

  1. If it is not necessary release a resource associated with an element that is shifted off an array then Shift<T> should be used instead of ShiftAndRelease<T>.

  2. There is no corresponding version of UnShift<T> for use with ShiftAndRelease<T>. This is not necessary since un-shifting an element with an associated resource requires no special handling. Just use UnShift<T>.

Example

The example below use a custom TMockResource record that emulates a resource that must be released. The record keeps track of the number of records currently instantiated.

type
  TMockResource = record
  public
    constructor Create(const AField: Integer);
    procedure Release;
    var Field: Integer;
    class var InstanceCount: Cardinal;
  end;

{ TMockResource }

constructor TMockResource.Create(const AField: Integer);
begin
  Field := AField;
  Inc(InstanceCount);
end;

procedure TMockResource.Release;
begin
  Dec(InstanceCount);
end;

procedure ShiftAndRelease_Eg;
var
  R, R0, R1, R2: TMockResource;
  RA, Expected: TArray<TMockResource>;
begin
  // create array of 3 "resources"
  R0 := TMockResource.Create(0);
  R1 := TMockResource.Create(1);
  R2 := TMockResource.Create(2);
  RA := TArray<TMockResource>.Create(R0, R1, R2);
  Assert(Length(RA) = 3, '3 element array expected');
  Assert(TMockResource.InstanceCount = 3, 'Expected 3 "resources" allocated');
  Assert(TArrayUtils.First<TMockResource>(RA).Field = 0, '0 1st elem expected');

  // pop and release element at end of array
  TArrayUtils.ShiftAndRelease<TMockResource>(
    RA,
    procedure (const AElem: TMockResource) begin AElem.Release end
  );

  // check array after popping
  Assert(TArrayUtils.First<TMockResource>(RA).Field = 1, '1 1st elem expected');
  Assert(Length(RA) = 2, '2 element array expected following deletion');
  Assert(TMockResource.InstanceCount = 2, 'Expected 2 "resources" allocated');
  Expected := TArray<TMockResource>.Create(R1, R2);
  Assert(TArrayUtils.Equal<TMockResource>(Expected, RA),
    'updated array content not as expected');

  // clear up remaining allocations
  for R in RA do R.Release;
  Assert(TMockResource.InstanceCount = 0, 'Expected all "resources" released');
end;

See Also