пятница, 3 апреля 2015 г.

Коротко. Слабая ссылка на интерфейс

Иногда надо хранить СЛАБЫЕ ссылки на интерфейсы (без подсчёта ссылок).

Аналог атрибута [Weak].

Например для publisher/subscriber.

"Определяет зависимость типа «один ко многим» между объектами таким образом, что при изменении состояния одного объекта все зависящие от него оповещаются об этом событии."

Так вот вам решение:

type
 TmsWeakInterfaceRef = record
 // Слабая ссылка на интерфейс
  rShape : Pointer;
  constructor Create(const aShape: T);
  function AsShape: ImsShape;
  class operator Equal(const A: TmsWeakInterfaceRef; const B: TmsWeakInterfaceRef): Boolean;
  class operator Equal(const A: TmsWeakInterfaceRef; const B: T): Boolean;
  class operator Implicit(const aShape: T): TmsWeakInterfaceRef;
 end;//TmsWeakInterfaceRef

 TmsWeakShapeRef = TmsWeakInterfaceRef;
...
// TmsWeakInterfaceRef

constructor TmsWeakInterfaceRef.Create(const aShape: T);
begin
 Assert(SizeOf(T) = SizeOf(IUnknown));
 Move(aShape, Self.rShape, SizeOf(T));
end;

function TmsWeakInterfaceRef.AsShape: ImsShape;
begin
 Result := ImsShape(Self.rShape);
end;

class operator TmsWeakInterfaceRef.Equal(const A: TmsWeakInterfaceRef; const B: TmsWeakInterfaceRef): Boolean;
begin
 Result := (A.rShape = B.rShape);
end;

class operator TmsWeakInterfaceRef.Equal(const A: TmsWeakInterfaceRef; const B: T): Boolean;
var
 l_P : Pointer;
begin
 Assert(SizeOf(T) = SizeOf(Pointer));
 Move(B, l_P, SizeOf(T));
 Result := (A.rShape = l_P);
end;

class operator TmsWeakInterfaceRef.Implicit(const aShape: T): TmsWeakInterfaceRef;
begin
 Result := TmsWeakInterfaceRef.Create(aShape);
end;

Ссылка на коммит - https://bitbucket.org/lulinalex/mindstream/commits/825ca7487905ce786aa9f44b6a0d95e570b06b71

Ещё коммит - https://bitbucket.org/lulinalex/mindstream/commits/861e56e0bff2613b652d633f0183c93fde75601e

Окончательная версия:
type
 TmsWeakInterfaceRef = record
 // Слабая ссылка на интерфейс
  rRef : Pointer;
  constructor Create(const aShape: T);
  function AsRef: T; inline;
  class operator Equal(const A: TmsWeakInterfaceRef; const B: TmsWeakInterfaceRef): Boolean;
  class operator Equal(const A: TmsWeakInterfaceRef; const B: T): Boolean;
  class operator Implicit(const aShape: T): TmsWeakInterfaceRef;
  class operator Implicit(const aValue: TmsWeakInterfaceRef): T; inline;
 end;//TmsWeakInterfaceRef

 TmsWeakShapeRef = TmsWeakInterfaceRef;
...
// TmsWeakInterfaceRef

constructor TmsWeakInterfaceRef.Create(const aShape: T);
begin
 Assert(SizeOf(T) = SizeOf(IUnknown));
 Move(aShape, Self.rRef, SizeOf(T));
end;

function TmsWeakInterfaceRef.AsRef: T;
begin
 Result := nil;
 Assert(SizeOf(T) = SizeOf(Result));
 Move(Self.rRef, Result, SizeOf(T));
 Result._AddRef;
end;

class operator TmsWeakInterfaceRef.Implicit(const aValue: TmsWeakInterfaceRef): T;
begin
 Result := aValue.AsRef;
end;

class operator TmsWeakInterfaceRef.Equal(const A: TmsWeakInterfaceRef; const B: TmsWeakInterfaceRef): Boolean;
begin
 Result := (A.rRef = B.rRef);
end;

class operator TmsWeakInterfaceRef.Equal(const A: TmsWeakInterfaceRef; const B: T): Boolean;
var
 l_P : Pointer;
begin
 Assert(SizeOf(T) = SizeOf(Pointer));
 Move(B, l_P, SizeOf(T));
 Result := (A.rRef = l_P);
end;

class operator TmsWeakInterfaceRef.Implicit(const aShape: T): TmsWeakInterfaceRef;
begin
 Result := TmsWeakInterfaceRef.Create(aShape);
end;

2 комментария:

  1. Здравствуйте, правильно ли я понял что ваш TmsWeakInterfaceRef это аналог [unsafe] а не [weak]? Я не увидел автоматического заниливания переменной rRef : Pointer; К слову в XE10.1 Berlin это все уже стало не актуально, там [unsafe] и [weak] заработали для классических компиляторов. Александр.

    ОтветитьУдалить
    Ответы
    1. Здравствуйте.

      Ну есть такое понятие "слабая ссылка", так вот это оно и есть. Ну и Unsafe конечно. Ну ему вообще говоря незачем быть Safe. Оно же не используется, как выходит из области видимости.

      Ну а то что Эмбаркадера сделала своё понятие Weak - это конечно отдельный разговор.

      bq. Berlin это все уже стало не актуально, там [unsafe] и [weak] заработали для классических компиляторов.

      Отрадно слышать, спасибо :-)

      Жаль что мне пришлось ждать абракадабру годика так два.

      Удалить