Синхронизация потоков

Вопросы программирования на Free Pascal, использования компилятора и утилит.

Модератор: Модераторы

Сообщение ssl » 17.05.2005 12:42:36

Идея в следующем: часто бывает нужен "Synchronize с параметрами", т.е. из потока надо вызвать некий метод, передать ему параметры, дождаться, пока метод отработает в основном потоке, получить результат и продолжить работу. На native Delphi приходится где-то запоминать параметры, вызывать Synchronize(Method), а Method, в свою очередь, вызовет требуемое, вынув параметры из этого "где-то". Я попытался упростить код. Получилось красиво даже на Delphi, но без поддержки компиллятора приходится соблюдать ограничения, несовместимые с удобством. :(
Как выглядит:
класс TThread получил метод Fork: boolean, который надо вызвать в требующем синхронизации методе:

TMyThread.MainThreadMethod(ParamList): AnyType;
begin
if Fork then exit;
.....
end;

Fork проверяет, в каком потоке он выполняется, и возвращает false, если это MainThread. В противном случае fork выполняет переключение в MainThread, копирует параметры из стека потока в стек MainThread и повторно вызывает этот же метод. Затем возвращает true.
Вызов получается абсолютно корректным как с точки зрения reference count, так и с точки зрения обработки exceptions. Всё, чего не хватает при реализации на Delphi: метод не должен быть register (все параметры нужны в стеке) и, находясь в Fork, невозможно определить точку входа в обрамляющий метод - приходится передавать её как параметр:

if Fork(@TMyThread.MainThreadMethod) then exit;

Компилятору это, естественно, не проблема. B)
ssl
новенький
 
Сообщения: 59
Зарегистрирован: 17.05.2005 11:27:01

Сообщение Иван Шихалев » 17.05.2005 12:56:31

Что именно не проблема компилятору?
Аватара пользователя
Иван Шихалев
энтузиаст
 
Сообщения: 1140
Зарегистрирован: 15.05.2006 11:26:13
Откуда: Екатеринбург

Сообщение ssl » 17.05.2005 13:05:39

Наверное, реализовать Fork как встроенную функцию; вызывающую функцию всегда компилировать как pascal (или stdcall, можно вынести в опции) и передавать в Fork адрес вызывающей функции как скрытый параметр.
?
ssl
новенький
 
Сообщения: 59
Зарегистрирован: 17.05.2005 11:27:01

Сообщение Иван Шихалев » 17.05.2005 13:08:40

Не думаю, что это хорошая идея. Тем более, что на уровне TThread логичней покопать его исходники.
Аватара пользователя
Иван Шихалев
энтузиаст
 
Сообщения: 1140
Зарегистрирован: 15.05.2006 11:26:13
Откуда: Екатеринбург

Сообщение ssl » 17.05.2005 13:19:43

Эх..
Сделано, на Delphi 7 конкретно сделано. Работает. Напрягают как раз эти два момента:
- не забыть вызывающий метод объявить stdcall
- в fork передавать адрес вызывающго метода.
Причём второе не лечится никак: если адрес возврата я ещё могу вынуть из стека, то вычислить точку входа в вызывающую... тут дизасемблер нужен!
А ведь при таком подходе можно вызывать методы хоть из потока, хоть из MainThread. Например, в некоей компоненте завёл property ShadowExec: boolean; и всё что нужно: поставить
if Fork then exit;
в критических методах. Если ShadowExec = false и всё происходит в MainThread, все затраты - только на проверку MainThreadID = CurrentThreadID в Fork'е.
А что конкретно не нравится? Может, обсудим?
ssl
новенький
 
Сообщения: 59
Зарегистрирован: 17.05.2005 11:27:01


Вернуться в Free Pascal Compiler

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 2

Рейтинг@Mail.ru