Многопоточные приложения и связанное с ними в Linux, MacOS

Вопросы использования сторонних (не входящих в состав FPC и Lazarus) утилит и библиотек.

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

Многопоточные приложения и связанное с ними в Linux, MacOS

Сообщение SovNarKom » 02.09.2007 02:01:05

Народ, а просвятите, как в Linux и MacOS обстоят дела с аналогами
CreateEvent;
WaitForSingleObject;
и т.д. из WinAPI.
Может RTL что нибудь реализовано, кроме критических секций и потоков?

Можно конечно запускать отдельный поток, ждать его завершения и т.д. Но вдруг есть более правильный вариант?

Где можно почитать по сабжу? (можно на C)

Зараенее спасибо.
SovNarKom
постоялец
 
Сообщения: 389
Зарегистрирован: 28.05.2005 10:37:39
Откуда: Воронеж [vrn] [36]

Сообщение *vmr » 02.09.2007 13:56:08

Погугли на тему pthread_cond_wait, pthread_cond_timedwait, pthread_cond_signal, pthread_cond_broadcast
Больше сказать ничего не могу поскольку с потоками работал только на Делфи
Аватара пользователя
*vmr
постоялец
 
Сообщения: 168
Зарегистрирован: 08.01.2007 01:46:07
Откуда: Киев

Сообщение Sergei I. Gorelkin » 02.09.2007 15:33:27

Хорошая статья в тему здесь:
http://www.ibm.com/developerworks/libra ... S_CMP=MGST

А вообще, события (events) вроде бы в RTL реализованы. Или по крайней мере имеются настойчивые попытки их реализации.
Аватара пользователя
Sergei I. Gorelkin
энтузиаст
 
Сообщения: 1395
Зарегистрирован: 24.07.2005 14:40:41
Откуда: Зеленоград

Re: Многопоточные приложения и связанное с ними в Linux, Mac

Сообщение Linus » 21.01.2017 09:36:48

Так и не ясно, в каком модуле смотреть events?

p.s. Немного раздражает, что документации по лазарю как кот наплакал

Дополнение(оставляю для потомков :wink: )
Есть модуль syncobjs (благо еще и идет комплектом)
Вместо СreateEvent() идет TEvent.Create();
Вместо WaitForSingleObject соответственно TEvent.WaitFor(time);
и т. д.
Linus
новенький
 
Сообщения: 47
Зарегистрирован: 11.01.2013 22:01:28

Re: Многопоточные приложения и связанное с ними в Linux, Mac

Сообщение wadman » 21.01.2017 17:16:49

SovNarKom можно попробовать мое решение viewtopic.php?f=10&t=11509
wadman
постоялец
 
Сообщения: 122
Зарегистрирован: 18.10.2016 15:54:28

Re: Многопоточные приложения и связанное с ними в Linux, Mac

Сообщение Linus » 21.01.2017 18:25:30

Я вот единственное что понять не могу, почему я не могу "разбудить" поток из другого потока?
Приложение консольное.

Код: Выделить всё
if ((AwakeScheduler) and (FScheduler<>nil)) then
         begin
           try
           writeln('Планировщик спит? ',FScheduler^.Suspended);

           FScheduler^.AwakeEvent.SetEvent;   //не работает
           // FScheduler^.Start;   - в наглую тоже не хочет           
           writeln('Awoke scheduler... ok');

           except
              writeln('Не удалось разбудить');
              error:=true;
           end;
         end;   


Во всех случаях ловим исключение и получаем месседж.

Если же попытаться разбудить скажем так (в главном потоке)
Код: Выделить всё
while (input<>'exit') do
  begin
    readln(input);
    ....
     if input='start' then MainElevator.Start;
  end;
  // stop program loop
  Terminate;

То поток просыпается.
В чем может быть подвох?.
Linus
новенький
 
Сообщения: 47
Зарегистрирован: 11.01.2013 22:01:28

Re: Многопоточные приложения и связанное с ними в Linux, Mac

Сообщение MysticCoder » 21.01.2017 19:26:06

Linus писал(а):В чем может быть подвох?.


а ты давай весь код, там и видно будет
MysticCoder
постоялец
 
Сообщения: 154
Зарегистрирован: 14.09.2013 00:20:28

Re: Многопоточные приложения и связанное с ними в Linux, Mac

Сообщение Linus » 21.01.2017 19:35:39

Весь конечно очень много будет кода (легко заплутать), отфильтрую.
главный:
Код: Выделить всё
program server;

{$mode objfpc}{$H+}
{$DEFINE UseCThreads}

uses
  {$IFDEF UNIX}{$IFDEF UseCThreads}
  cthreads,
  {$ENDIF}{$ENDIF}
  Classes, SysUtils, CustApp, tasks, net
  { you can add units after this };

type
  { TServer }
  TServer = class(TCustomApplication)
  protected
    procedure DoRun; override;
  public
    constructor Create(TheOwner: TComponent); override;
    destructor Destroy; override;
    procedure WriteHelp; virtual;
  end;

{ TServer }

procedure TServer.DoRun;
var
  ErrorMsg: String;
  input:string;
  MainElevator:TTaskScheduler;
begin
  // parse parameters
  if HasOption('h', 'help') then begin
    WriteHelp;
    Terminate;
    Exit;
  end;

  MainElevator:=TTaskScheduler.create(true);
  MainElevator.setup;
  MainElevator.Priority:=tpHigher;

  //LoadTasks;
  //SaveTasks;

  { add your program here }
  input:='';
  while input<>'exit' do
  begin
    readln(input);
  ....

    if input='list' then
       MainElevator.TasksDB.PrintTasks;

     if input='save' then
       if MainElevator.TasksDB.SaveTasks then writeln('успешно') else writeln('fail');

     if input='load' then
       if MainElevator.TasksDB.LoadTasks then writeln('успешно') else writeln('fail');

     if input='start' then MainElevator.Start;  //запуск процесса (который проблемно будить)
  end;
  // stop program loop
  Terminate;
end;

constructor TServer.Create(TheOwner: TComponent);
begin
  inherited Create(TheOwner);
end;

destructor TServer.Destroy;
begin
  //close files
  inherited Destroy;
end;

procedure TServer.WriteHelp;
begin
  { add your help code here }
  writeln('Usage: ', ExeName, ' -h');
end;

var
  Application: TServer;
begin
  Application:=TServer.Create(nil);
  Application.Title:='server';
  Application.Run;
  Application.Free;
end.               


Модуль tasks
Код: Выделить всё
unit tasks;
{$mode objfpc}{$H+}
interface
uses
  Classes, SysUtils, Process, LazFileUtils, syncobjs;
const
  DataFiles='./DATA';
  TaskDB='./tasks.tdb';
type
....
TTaskThread=class(TThread) //поток конкретной задачи (то откуда будем будить)
...
TTaskScheduler=class(TThread) //планировщик (его будем будить)\0
..
AwakeEvent:TEvent;\0
procedure setup;
procedure AwakeMe;\0
..
end;
...
implementation\0
...
procedure TTaskThread.execute;
var
  error:boolean;
begin
  if (TaskItem=nil)
  then writeln('Critiacal ERROR')
  else
    begin
         error:=FALSE;

         writeln('****thread log');
         //ждем (отложенный запуск)?
         TaskItem^.State:=TsSleep;
         write('whait=',Delay);
         sleep(Delay*1000);
         writeln('.......ok');

         writeln('Будить планировщик? ',AwakeScheduler);

         //"будим планировщик?"
         if ((AwakeScheduler) and (FScheduler<>nil)) then
         begin
           try
           writeln('Планировщик спит? ',FScheduler^.Suspended);
           FScheduler^.AwakeEvent.SetEvent;
           writeln('Awoke scheduler... ok');
           except
              writeln('Не удалось разбудить');
              error:=true;
           end;
         end;

          writeln('конкурирование процесса перед запуском');

         //жизнь задачи (нить висит и обслуживает текущую задачу [ожидание, управление, завершение])
        ....

       finally
         writeln('процесс умер');
         //если мы здесь, то процесс мертв
         process.Free;
         TaskItem^.State:=TsFree;
         //лог писать будем?
         writeln('****END log');
       end;
  end;
end;
...
{TTaskScheduler}
procedure TTaskScheduler.setup;
begin
  //инициализация
  TasksDB.ini;
  ReadyTasks.ini;
  AbortedTasks.ini;
  //CreateEvent

  AwakeEvent:=TEvent.Create(nil, true, false, 'AwakeScheduler');

  write('Загрузка задач....');
  if TasksDB.LoadTasks then  writeln('ok') else  writeln('failed');
....
end; 

procedure TTaskScheduler.execute;
var
  lastChkTask:TTaskItemPTR;
begin
   lastChkTask:=nil;

   while (not self.Terminated) do
   begin
        //Анализ...   
        if (lastChkTask=nil) then lastChkTask:=self.TasksDB.Root;

        lastChkTask:=AnalyzeTasks(lastChkTask);   //Эта процедура создает экземпляры TTaskThread(они будут будить)

        {ранние задачи запущены, пора спать,нас разбудит
        первая задача как только начнет выполняться,
        наша задача обратотать обновения как проснемся, если такие есть
        если нет то просто проделываем то же самое (loop)}
        writeln('Suspend Scheduler....ok');
         //Ждем событие
        AwakeEvent.WaitFor(INFINITE);  //время потом исправлю!!
        AwakeEvent.ResetEvent;

        {проснулись}
        if (self.TasksDB.modify) then
        begin
         .....
        end;
   end;
end;         

Последний раз редактировалось Linus 21.01.2017 19:46:59, всего редактировалось 1 раз.
Linus
новенький
 
Сообщения: 47
Зарегистрирован: 11.01.2013 22:01:28

Re: Многопоточные приложения и связанное с ними в Linux, Mac

Сообщение vitaly_l » 21.01.2017 19:46:38

Linus писал(а):Весь конечно очень много будет, отфильтрую.
главный:

Попробуйте чистить input:=''; перед выполнением запуска.

Код: Выделить всё
if input='start' then begin input:=''; MainElevator.Start; end;
Аватара пользователя
vitaly_l
долгожитель
 
Сообщения: 3333
Зарегистрирован: 31.01.2012 16:41:41

Re: Многопоточные приложения и связанное с ними в Linux, Mac

Сообщение Linus » 21.01.2017 19:48:33

vitaly_l писал(а):
Linus писал(а):Весь конечно очень много будет, отфильтрую.
главный:

Попробуйте чистить input:=''; перед выполнением запуска.

Код: Выделить всё
if input='start' then begin input:=''; MainElevator.Start; end;



Извините, привычка выкладывать по частям. Вся вкусность не там. Просмотрите обновление.
Linus
новенький
 
Сообщения: 47
Зарегистрирован: 11.01.2013 22:01:28

Re: Многопоточные приложения и связанное с ними в Linux, Mac

Сообщение vitaly_l » 21.01.2017 19:59:41

Linus писал(а):Извините, привычка выкладывать по частям. Вся вкусность не там. Просмотрите обновление.

Эта вкусность ничего не меняет, т.к. вы 1 000 000 раз в секунду запускаете миллион MainElevator.Start; после первых пол секунды у вас должен закипать процессор.
Аватара пользователя
vitaly_l
долгожитель
 
Сообщения: 3333
Зарегистрирован: 31.01.2012 16:41:41

Re: Многопоточные приложения и связанное с ними в Linux, Mac

Сообщение Linus » 21.01.2017 20:08:13

vitaly_l писал(а):Эта вкусность ничего не меняет, т.к. вы 1 000 000 раз в секунду запускаете миллион MainElevator.Start; после первых пол секунды у вас должен закипать процессор.


А вот и не запускает... С чего он должен запускать если выполнение далее не пройдет пока не отработает Readln();
По логам видно было бы) Проверю еще раз, отпишусь;

Проверил. Перезапусков нет что так что так.
Linus
новенький
 
Сообщения: 47
Зарегистрирован: 11.01.2013 22:01:28

Re: Многопоточные приложения и связанное с ними в Linux, Mac

Сообщение MysticCoder » 21.01.2017 20:42:31

собственно, а как
Код: Выделить всё
FScheduler^.AwakeEvent.SetEvent;


может разбудить это?
Код: Выделить всё
procedure TTaskScheduler.execute;
...
         //Ждем событие
        AwakeEvent.WaitFor(INFINITE);  //время потом исправлю!!


Upd. ага, понял, затупил)

Upd.Upd.
Вообще, тут надо просто отладить, непонятно на каком шаге AV возникает, что при этом в логах, что делает в это время поток который должен разбудиться.
Вангую, что в
Код: Выделить всё
FScheduler^.Suspended
идет попытка разыменовать невалидный указатель. Вообще, непонятно зачем здесь использовать указатель на класс, ведь он сам и есть указатель. Тогда уж проверку выше на nil надо не только FSheduler, а еще и FSheduler^ ставить.
MysticCoder
постоялец
 
Сообщения: 154
Зарегистрирован: 14.09.2013 00:20:28

Re: Многопоточные приложения и связанное с ними в Linux, Mac

Сообщение Linus » 21.01.2017 21:13:29

Для меня тоже это загадка)
Ладно, понятно что напрямую из главного потока работает.
Для теста создал поток от главного, перенес туда код. (Главный понятно спать sleep уложил, и эти строки закомментил )
Код: Выделить всё
while input<>'exit' do
  begin
    readln(input);
  ....
       if input='start' then MainElevator.Start;  //запуск процесса (который проблемно будить)
  end;

И самое главное, это тоже работает. но почему не работает именно та схема, что нужна.
Linus
новенький
 
Сообщения: 47
Зарегистрирован: 11.01.2013 22:01:28

Re: Многопоточные приложения и связанное с ними в Linux, Mac

Сообщение MysticCoder » 21.01.2017 21:21:04

так и будем в экстрасенсов играть или покажешь подробнее отладочные данные?
MysticCoder писал(а):непонятно на каком шаге AV возникает, что при этом в логах, что делает в это время поток который должен разбудиться.
Вангую, что в


плюс код присваивания FSheduler
MysticCoder
постоялец
 
Сообщения: 154
Зарегистрирован: 14.09.2013 00:20:28

След.

Вернуться в Сторонние средства

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

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

Рейтинг@Mail.ru