Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Эффективная реализация локальных Callback-ов? / 8 сообщений из 8, страница 1 из 1
01.07.2020, 13:20
    #39974885
Maxim Rusov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Эффективная реализация локальных Callback-ов?
Раньше активно использовал локальные функции в качестве Callback-ов. Типа:

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
  procedure SomeProc;

    procedure LocIterator(Index :Integer; Item :Pointer);
    begin
    end;

  begin
    vList.Each(LocalAddr(@LocIterator));
  end;



Эффективно реализуется с помощью пары аsm-вставок, не суть. При портировании на Linux нупрямую сконветировавть не удается. Возможна более-менее равноценная замена, типа:

Код: pascal
1.
2.
3.
4.
5.
6.
7.
  procedure SomeProc;
  begin
    vList.Each(
      procedure(Index :Integer; Item :Pointer)
      begin
      end);
  end;



Но напрягает ее неэффективность. Создается полноценное замыкание, аллокация памяти, захват стека, все дела. Но по сути - ничего этого не нужно, нужен только Callback с доступом к внешнему stack-frame'у.

Any idea?
...
Рейтинг: 0 / 0
01.07.2020, 15:36
    #39974929
Kazantsev Alexey
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Эффективная реализация локальных Callback-ов?
Maxim Rusov
Но напрягает ее неэффективность.

Умозрительная или фактическая? Если первое то забить, если второе то отрефакторить на перечислитель.
...
Рейтинг: 0 / 0
01.07.2020, 15:39
    #39974931
Maxim Rusov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Эффективная реализация локальных Callback-ов?
Я, вроде, придумал решение, которое позволяет сохранить старый синтаксис и для LLVM компилятора.

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
  procedure SomeProc;

  {$ifdef LINUX64}
    var
      _TopStack_ :Pointer;

    function LocalAddr(Proc :Pointer) :TMethod;
    begin
      Result.Data := @_TopStack_;
      Result.Code := Proc;
    end;
  {$endif}

    procedure LocIterator(Index :Integer; Item :Pointer);
    begin
    end;

  begin
    vList.Each(LocalAddr(@LocIterator));
  end;



Если вынести ifdef в include, то все ограничивается одной строкой в каждой такой функции:


Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
  procedure SomeProc;
  {$I LocalAddr.inc}

    procedure LocIterator(Index :Integer; Item :Pointer);
    begin
    end;

  begin
    vList.Each(LocalAddr(@LocIterator));
  end;



Вроде, все тесты проходит. Будем наблюдать...
...
Рейтинг: 0 / 0
01.07.2020, 15:52
    #39974938
Maxim Rusov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Эффективная реализация локальных Callback-ов?
Реализация Each, если кому интересно:


Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
  
  type
    TListEnumProc = procedure(Index :Integer; Item :Pointer)
      {$ifndef CPUX86}of object{$endif};


  procedure CallListEnum(const Proc :TMethod; Index :Integer; Item :Pointer); inline;
 {$ifdef CPUX86}
  var
    Tmp :Pointer;
  begin
    Tmp := Proc.Data;
    asm push Tmp; end;
    TListEnumProc(Proc.Code)(Index, Item);
    asm pop ECX; end;
 {$else}
  begin
    TListEnumProc(Proc)(Index, Item);
 {$endif}
  end;


  procedure TMyList.Each(const AProc :TMethod);
  var
    i :Integer;
  begin
    for i := 0 to Count - 1 do
      CallListEnum(AProc, i, Items[i]);
  end;
...
Рейтинг: 0 / 0
01.07.2020, 16:28
    #39974961
_Vasilisk_
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Эффективная реализация локальных Callback-ов?
Я не совсем понимаю, почему нельзя сделать так?
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
  type
    TListEnumProc = procedure(Index :Integer; Item :Pointer);


  procedure TMyList.Each(const AProc: TListEnumProc);
  var
    i :Integer;
  begin
    for i := 0 to Count - 1 do
      AProc(i, Items[i]);
  end;


и соответственно вызов не любой платформе
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
  procedure SomeProc;

    procedure LocIterator(Index :Integer; Item :Pointer);
    begin
    end;

  begin
    vList.Each(LocIterator);
  end;
...
Рейтинг: 0 / 0
01.07.2020, 16:33
    #39974963
Vizit0r
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Эффективная реализация локальных Callback-ов?
_Vasilisk_
Я не совсем понимаю, почему нельзя сделать так?

это слишком просто.
...
Рейтинг: 0 / 0
01.07.2020, 16:35
    #39974964
Maxim Rusov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Эффективная реализация локальных Callback-ов?
_Vasilisk_,

Потому что это не скомпилируется? Локальные процедуры не совпадают по формату вызова с глобальными. Они получают еще один неявный параметр - указатель на stack frame внешней процедуры.
...
Рейтинг: 0 / 0
01.07.2020, 17:53
    #39974999
delphinotes
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Эффективная реализация локальных Callback-ов?
Maxim Rusov,

1й вариант из самого первого комментария скомпилируется и под win64, но не будет работать (в отличии от win32). Но достаточно вынести procedure LocIterator за пределы procedure SomeProc (т.е. повысив область видимости), как такой callback начинает работать. Возможно под Linux так же?
...
Рейтинг: 0 / 0
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Эффективная реализация локальных Callback-ов? / 8 сообщений из 8, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]