powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Эффективная реализация локальных Callback-ов?
8 сообщений из 8, страница 1 из 1
Эффективная реализация локальных Callback-ов?
    #39974885
Фотография Maxim Rusov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Раньше активно использовал локальные функции в качестве 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
Эффективная реализация локальных Callback-ов?
    #39974929
Kazantsev Alexey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Maxim Rusov
Но напрягает ее неэффективность.

Умозрительная или фактическая? Если первое то забить, если второе то отрефакторить на перечислитель.
...
Рейтинг: 0 / 0
Эффективная реализация локальных Callback-ов?
    #39974931
Фотография Maxim Rusov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я, вроде, придумал решение, которое позволяет сохранить старый синтаксис и для 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
Эффективная реализация локальных Callback-ов?
    #39974938
Фотография Maxim Rusov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Реализация 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
Эффективная реализация локальных Callback-ов?
    #39974961
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я не совсем понимаю, почему нельзя сделать так?
Код: 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
Эффективная реализация локальных Callback-ов?
    #39974963
Vizit0r
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_Vasilisk_
Я не совсем понимаю, почему нельзя сделать так?

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

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

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


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