Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Delphi Новый топик    Ответить
Топик располагается на нескольких страницах: 1 2 3 4      [все]
 Глобальный reference counter для нескольких процессов?  [new]
Квейд
Member

Откуда: Kyiv, Ukraine
Сообщений: 5406
Delphi-приложение может быть запущенно в нескольких экземлярах.
Например, запущено три.
Хочу решить такую задачу - мне нужно отреагировать в момент, когда пользователь закрывает два экземляра, и остается только один (последний).
Посоветуйте, в какую сторону копать? Хочется что-то вроде сабжа.

Сообщение было отредактировано: 31 май 21, 11:33
31 май 21, 11:41    [22329207]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
Мимопроходящий
Member

Откуда: бурятский тундрюк, эсквайр
Сообщений: 32387

семафоры

Posted via ActualForum NNTP Server 1.5

31 май 21, 11:56    [22329222]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
Dimitry Sibiryakov
Member

Откуда:
Сообщений: 53436

Квейд
Посоветуйте, в какую сторону копать?

MMF из свапа. Это даст тебе общую память, где ты можешь держать атомарный счётчик или
чёрта с рогами.

Posted via ActualForum NNTP Server 1.5

31 май 21, 12:34    [22329256]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
makhaon
Member

Откуда: A galaxy far far away
Сообщений: 3862
семафоры, у них есть счетчик, глобальные на всю систему.
31 май 21, 23:54    [22329612]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
Dimitry Sibiryakov
Member

Откуда:
Сообщений: 53436

makhaon
семафоры, у них есть счетчик, глобальные на всю систему

У них совсем плохо с сигнализацией достижения единицы. Да и с нулём не очень.

Posted via ActualForum NNTP Server 1.5

1 июн 21, 00:33    [22329619]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
kealon(Ruslan)
Member

Откуда: Нижневартовск
Сообщений: 6366
Квейд,

а у MMF плохо с завершением - выпала программа, а твой счётчик не обновился.
1 июн 21, 11:20    [22329725]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
ziv-2014
Member

Откуда:
Сообщений: 599
Квейд,
OpenThread и WaitForObject. В каждой копии программы открываешь главный поток и ждешь его завершения. Как главный поток завершился, уменьшаешь счетчик. Таким образом каждая копия программы мониторит друг друга.
1 июн 21, 11:32    [22329732]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
Fr0sT-Brutal
Member

Откуда:
Сообщений: 755
Надо именно ловить момент, когда экземпляр остается в одиночестве? Чтобы из реплики стать мастером? Может, event поможет? В мастере создается, реплики мониторят. Как только мастер закрывается, реплика создает event и становится мастером
1 июн 21, 11:38    [22329739]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
Dimitry Sibiryakov
Member

Откуда:
Сообщений: 53436

kealon(Ruslan)
выпала программа, а твой счётчик не обновился.

Поэтому нормальные программисты стараются писать программы, которые не выпадают.

Posted via ActualForum NNTP Server 1.5

1 июн 21, 13:27    [22329805]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
ziv-2014
Member

Откуда:
Сообщений: 599
Dimitry Sibiryakov,
Пользователь прибил приложение и все счетчик не обновился.
1 июн 21, 14:47    [22329859]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
Dimitry Sibiryakov
Member

Откуда:
Сообщений: 53436

При обычном прибитии приложению сначала посылается штатный WM_CLOSE. Чтобы счётчик не
обновился приложение должно либо зависнуть, либо прибитие нужно жёсткое, с
TerminateProcess, каковое для обычных пользователей слишком сложно, ибо делается с
"нипанятной" страница таскменеджера.

Ну и последующие глюки - тоже на его, пользователя, совести.

Posted via ActualForum NNTP Server 1.5

1 июн 21, 14:53    [22329868]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
alekcvp
Member

Откуда:
Сообщений: 2870
Dimitry Sibiryakov

Ну и последующие глюки - тоже на его, пользователя, совести.

Приложение которое не защищено от нештатного завершения - это кривые руки программиста.

Сообщение было отредактировано: 1 июн 21, 16:22
1 июн 21, 16:31    [22329934]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
Fr0sT-Brutal
Member

Откуда:
Сообщений: 755
А цель-то какая?
1 июн 21, 16:42    [22329940]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
kealon(Ruslan)
Member

Откуда: Нижневартовск
Сообщений: 6366
Dimitry Sibiryakov

kealon(Ruslan)
выпала программа, а твой счётчик не обновился.

Поэтому нормальные программисты стараются писать программы, которые не выпадают.
стараться и написать - разные вещи, а вот спустить ответственность на пользователя - это непроффесионализм
1 июн 21, 19:01    [22330037]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
YuRock
Member

Откуда: Донецк
Сообщений: 4653
Электричество закончилось - тоже проблема пользователя?
1 июн 21, 19:36    [22330051]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
X-Cite
Member

Откуда: Минск
Сообщений: 1834
YuRock
Электричество закончилось - тоже проблема пользователя?

Тогда счетчик уже не важен :)
1 июн 21, 19:40    [22330052]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
YuRock
Member

Откуда: Донецк
Сообщений: 4653
У меня идея такая, как вариант.
1. Пытаемся создать серверный сокет на определенный порт.
2. Если получилось - ты единственная (главная) программа.
3. Если не получилось - пытаемся подключиться к такому серверу. Подключились, и начинаем вечно чего-то ждать от сервера. Как придет ошибка (сервер закрылся) - возвращаемся в п. 1.
На локальных сокетах должно всё мгновенно отрабатывать по идее, даже если жОстко снять процесс сервера.
1 июн 21, 19:42    [22330054]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
YuRock
Member

Откуда: Донецк
Сообщений: 4653
X-Cite
YuRock
Электричество закончилось - тоже проблема пользователя?

Тогда счетчик уже не важен :)
А, ну да))
1 июн 21, 19:43    [22330055]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
GunSmoker
Member

Откуда:
Сообщений: 3231
1. Первый запущенный экземпляр открывает MMF и становится "главным".
2. Все последующие - проверяют MMF и регистрируют в главном экземпляре себя (например, отправкой сообщений в окно, указанное в MMF). Хэндл на MMF не держат открытым.
3. Главный экземпляр ждёт завершения всех зарегистрированных вторичных процессов.
4. Если главный процесс закрывается пользователем раньше вторичных - нужно себя отфинализировать полностью, но MMF не закрывать, ждать завершения всех вторичных, а потом грохнуться.
5. Событие "остается только один (последний) экземпляр" наступает, когда главный процесс дожидается завершения всех зарегистрированных вторичных. В этом случае последний экземпляр - главный. Либо, если главный уже логически финализирован, то когда он дождётся завершения всех, кроме одного вторичного. В этом случае последний экземпляр - оставшийся вторичный.

В качестве главного процесса можно использовать вспомогательный exe, чтобы не было необходимости закрывать его раньше вторичных.

Если вторичный процесс терминируется - главный об этом узнает. Если терминируется главный - ой. Как вариант: вторичные процессы тоже могут ждать завершения главного, и если он закрылся раньше вторичного - переизбрать главного среди вторичных (например, кто первее переоткроет MMF - того и тапки).
1 июн 21, 20:45    [22330067]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
alekcvp
Member

Откуда:
Сообщений: 2870
GunSmoker,

А если тупо создать два глобальных Mutex'a причём один захватывает первый запущенный экземпляр приложения, а следующий - отпускает. После чего все экземпляры приложения в отдельном потоке ждут на этих Mutex'ах. И если у какого-то экземпляра они оказываются оба, то он проверяет наличие других экземпляров (неважно как) и если не находит - профит. Ну и снова отпускает один Mutex. Только при запуске нового экземпляра надо сообщить об этом всем остальным, чтобы они начали ждать.

Сообщение было отредактировано: 1 июн 21, 21:00
1 июн 21, 21:07    [22330083]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
kealon(Ruslan)
Member

Откуда: Нижневартовск
Сообщений: 6366
GunSmoker

В качестве главного процесса можно использовать вспомогательный exe, чтобы не было необходимости закрывать его раньше вторичных.
а рабочие процессы, как вариант, запускать в job-е
там много что можно настроить
1 июн 21, 22:12    [22330111]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
alekcvp
Member

Откуда:
Сообщений: 2870
+ Уголок извращенца
unit loMain;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs;

type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    FMutex: array [0..1] of THandle;
    FEvent: THandle;
    FThread: TThread;
  public
    procedure WaitSingleInstance;
    procedure DoSingleInstance;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.DoSingleInstance;
begin
  ShowMessage('Single Instance!');
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  FEvent := CreateEvent(nil, True, False, nil);
  FMutex[0] := CreateMutex(nil, False, 'TLO_A');
  FMutex[1] := CreateMutex(nil, False, 'TLO_B');
  WaitSingleInstance;
end;

procedure TForm1.FormDestroy(Sender: TObject);
var
  ThreadHandle: Thandle;
begin
  ThreadHandle := FThread.Handle;
  SetEvent(FEvent); //Killing thread
  WaitForSingleObject(ThreadHandle, INFINITE);
  CloseHandle(FEvent);
  { !!! Не закрываем хэндлы мьютексов! }
end;

procedure TForm1.WaitSingleInstance;
begin
  FThread := TThread.CreateAnonymousThread(

    procedure
    var
      IsSingleInstance: Boolean;
      hObjects: array of THandle;
    begin
      IsSingleInstance := True;
      hObjects := [FMutex[0], FMutex[1], FEvent];

      { Ждём получения первого мьютекса }
      case WaitForMultipleObjects(3, @hObjects[0], False, INFINITE) of

        WAIT_OBJECT_0,
        WAIT_ABANDONED_0:
          hObjects := [FMutex[1], FEvent];

        WAIT_OBJECT_0 + 1,
        WAIT_ABANDONED_0 + 1:
          hObjects := [FMutex[0], FEvent];

      else
        Exit;
      end;

      while WaitForSingleObject(FEvent, 0) = WAIT_TIMEOUT do
      begin

        { Ждём получения второго мьютекса }
        case WaitForMultipleObjects(2, @hObjects[0], False, 100) of

          WAIT_OBJECT_0,
          WAIT_ABANDONED_0:
            begin
              ReleaseMutex(hObjects[0]);
              if IsSingleInstance then
              begin
                Sleep(100);
                Continue;
              end;
            end;

          WAIT_TIMEOUT:
            begin
              IsSingleInstance := False;
              Continue;
            end

        else
          Exit;
        end;

        { Проверяем - перехватил ли кто-нибудь мьютекс? }
        if WaitForSingleObject(hObjects[0], 0) = WAIT_OBJECT_0 then
        begin
          IsSingleInstance := True;
          ReleaseMutex(hObjects[0]);
          TThread.Synchronize(nil, DoSingleInstance);
        end;

      end;
    end);

  FThread.Start;
end;

end.


Сообщение было отредактировано: 2 июн 21, 02:10
2 июн 21, 02:17    [22330137]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
Barmaley57
Member

Откуда: Москва
Сообщений: 5866
Каждый процесс создаёт в заведомо известном каталоге временный файл (флаг FILE_FLAG_DELETE_ON_CLOSE) и подписывается на изменения содержимого каталога.
Всё. Телемаркет.
2 июн 21, 12:06    [22330245]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
softwarer
Member

Откуда: 127.0.0.1
Сообщений: 65922
Блог
Квейд
Посоветуйте, в какую сторону копать? Хочется что-то вроде сабжа.

Лично я, во-первых, посмотрел бы алгоритмы выбора мастера (ведущего из кучи равноправных нод итп), а во-вторых, намонстрячил бы небольшой протокол на RegisterWindowMessage/HWND_BROADCAST. Что-нибудь типа того:

а) сдыхающий мастер делает рассылку о выборах
б) каждый получивший отвечает рассылкой свежесгенерированного guid-а, выдавший наименьший считает себя мастером
в) усомнившийся в существовании других опять же делает рассылку о выборах (на случай тихо сдохшего мастера)
2 июн 21, 12:28    [22330254]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
Кроик Семён
Member

Откуда: СПб --> Dortmund
Сообщений: 6743
А вот если организовать что-то такое:

1) простенькой COM-объект
2) и пусть каждое приложение создаёт себе его экземпляр
3) у COM-объекта пусть будет событие (не знаю, возможно такое), связанное с изменением числа инстансов и обработчик этого события и есть искомая фишка
2 июн 21, 13:12    [22330281]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
kealon(Ruslan)
Member

Откуда: Нижневартовск
Сообщений: 6366
Кроик Семён
А вот если организовать что-то такое:

1) простенькой COM-объект
2) и пусть каждое приложение создаёт себе его экземпляр
3) у COM-объекта пусть будет событие (не знаю, возможно такое), связанное с изменением числа инстансов и обработчик этого события и есть искомая фишка
тоже самое что и в 22329725
2 июн 21, 13:37    [22330299]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
Мимопроходящий
Member

Откуда: бурятский тундрюк, эсквайр
Сообщений: 32387
а где ТС?
2 июн 21, 13:53    [22330307]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
Barmaley57
Member

Откуда: Москва
Сообщений: 5866
Barmaley57
Каждый процесс создаёт в заведомо известном каталоге временный файл (флаг FILE_FLAG_DELETE_ON_CLOSE) и подписывается на изменения содержимого каталога.
Всё. Телемаркет.
Возможно, надо дополнить мысль: каждый процесс создает уникальный файл и, получая уведомления об изменении в ФС, считает кол-во файлов. Все форс-мажоры отдаются на откуп ОСи.
2 июн 21, 14:09    [22330317]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
Virtual Student
Member

Откуда: Belarus
Сообщений: 347
Мимопроходящий

семафоры

+1
2 июн 21, 14:16    [22330323]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
Dimitry Sibiryakov
Member

Откуда:
Сообщений: 53436

Мне уже интересно: как это реализовать на семафорах? Раз плюсуют, значит знают способ...

Posted via ActualForum NNTP Server 1.5

2 июн 21, 14:20    [22330328]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
Гаджимурадов Рустам
Member

Откуда:
Сообщений: 62803
Автор невовремя пропал, конечно.
Квейд
Хочу решить такую задачу - мне нужно отреагировать в момент,
когда пользователь закрывает два экземляра, и остается только один (последний).

Для этого reference counter не нужен.
2 июн 21, 14:28    [22330339]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
YuRock
Member

Откуда: Донецк
Сообщений: 4653
Мимопроходящий
а где ТС?
Он своё дело сделал
2 июн 21, 14:33    [22330344]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
Гаджимурадов Рустам
Member

Откуда:
Сообщений: 62803
Не, это стародавний товарищ, а не тролль-новобранец. :)

Posted via ActualForum NNTP Server 1.5

2 июн 21, 14:36    [22330347]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
YuRock
Member

Откуда: Донецк
Сообщений: 4653
Barmaley57
Barmaley57
Каждый процесс создаёт в заведомо известном каталоге временный файл (флаг FILE_FLAG_DELETE_ON_CLOSE) и подписывается на изменения содержимого каталога.
Всё. Телемаркет.
Возможно, надо дополнить мысль: каждый процесс создает уникальный файл и, получая уведомления об изменении в ФС, считает кол-во файлов. Все форс-мажоры отдаются на откуп ОСи.
Ситуация. Папка пустая. Два процесса запускаются одновременно.
Если будут считать файлы перед созданием своего - будут считать себя главными оба.
Если после - то оба будут считать себя НЕглавными (с большой вероятностью).
Каша какая-то, по нотификации изменений следить...
2 июн 21, 14:37    [22330348]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
softwarer
Member

Откуда: 127.0.0.1
Сообщений: 65922
Блог
Мимопроходящий
а где ТС?

Сделал всё на семафорах после первого коммента :)
2 июн 21, 14:37    [22330349]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
Virtual Student
Member

Откуда: Belarus
Сообщений: 347
Dimitry Sibiryakov,
Да, вроде, ничего сложного.
https://delphi.cjcsoft.net/viewthread.php?tid=47350
Семафор, он же именованный и уникальный для всей системы.
2 июн 21, 14:37    [22330350]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
Virtual Student
Member

Откуда: Belarus
Сообщений: 347
Хотя я бы еще проще поступил (для твоей задачи). Возможно, это тупо...
Но просто писал бы реестр нужную циферку. А реестр, один фиг в памяти болтается. Так, что все весьма шустро.
2 июн 21, 14:40    [22330354]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
Dimitry Sibiryakov
Member

Откуда:
Сообщений: 53436

Virtual Student
Да, вроде, ничего сложного.

Только тамошний пример не имеет ничего общего с задачей топика...

Posted via ActualForum NNTP Server 1.5

2 июн 21, 14:43    [22330357]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
Barmaley57
Member

Откуда: Москва
Сообщений: 5866
YuRock
Ситуация. Папка пустая. Два процесса запускаются одновременно.
Ну и пусть запускаются, хоть три. В чем проблема?
Потом ТС ничего не говорил про главный/не главный.
2 июн 21, 14:45    [22330360]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
alekcvp
Member

Откуда:
Сообщений: 2870
А если сделать dll-библиотеку со счётчиком и делать InterlockedIncrement() при DLL_PROCESS_ATTACH и InterlockedDecrement() при DLL_PROCESS_DETACH. А когда он станет равен 1 взводить какой-нибудь Event?..
2 июн 21, 14:55    [22330369]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
Dimitry Sibiryakov
Member

Откуда:
Сообщений: 53436

alekcvp
А если сделать dll-библиотеку со счётчиком

У библиотеки, загруженной в разные процессы, уже лет 25 как нет общего сегмента данных.

Posted via ActualForum NNTP Server 1.5

2 июн 21, 14:56    [22330373]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
Barmaley57
Member

Откуда: Москва
Сообщений: 5866
alekcvp
InterlockedIncrement()
чего?
2 июн 21, 14:58    [22330374]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
Barmaley57
Member

Откуда: Москва
Сообщений: 5866
Dimitry Sibiryakov

alekcvp
А если сделать dll-библиотеку со счётчиком

У библиотеки, загруженной в разные процессы, уже лет 25 как нет общего сегмента данных.
Они то как раз общие, пока читаешь. А потом COPY_ON_WRITE и усё
2 июн 21, 15:00    [22330376]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
Fr0sT-Brutal
Member

Откуда:
Сообщений: 755
YuRock
У меня идея такая, как вариант.
1. Пытаемся создать серверный сокет на определенный порт.
2. Если получилось - ты единственная (главная) программа.
3. Если не получилось - пытаемся подключиться к такому серверу. Подключились, и начинаем вечно чего-то ждать от сервера. Как придет ошибка (сервер закрылся) - возвращаемся в п. 1.
На локальных сокетах должно всё мгновенно отрабатывать по идее, даже если жОстко снять процесс сервера.

Лучше заменить на именованный пайп.
Плюс в том, что нет коллизии с другим софтом, который вдруг будет слушать именно этот порт.
Либо можно бродкастить UDP сообщения по типу UPNP протокола. Или сообщения рассылать (периодически пингуя главного)

Сообщение было отредактировано: 2 июн 21, 14:54
2 июн 21, 15:01    [22330378]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
Virtual Student
Member

Откуда: Belarus
Сообщений: 347
Dimitry Sibiryakov

Virtual Student
Да, вроде, ничего сложного.

Только тамошний пример не имеет ничего общего с задачей топика...

Там и с mutex'ом пример в конце...
2 июн 21, 15:01    [22330379]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
Dimitry Sibiryakov
Member

Откуда:
Сообщений: 53436

Virtual Student
Там и с mutex'ом пример в конце...

Да хоть с чёртом с рогами. Покажите на пальцах как на семафоре и/или мутексе сделать
счётчик ссылок с сигнализацией достижения единицы или хотя бы нуля, устойчивый к
TerminateProcess.

Posted via ActualForum NNTP Server 1.5

2 июн 21, 15:03    [22330382]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
Virtual Student
Member

Откуда: Belarus
Сообщений: 347
Fr0sT-Brutal
YuRock
У меня идея такая, как вариант.
1. Пытаемся создать серверный сокет на определенный порт.
2. Если получилось - ты единственная (главная) программа.
3. Если не получилось - пытаемся подключиться к такому серверу. Подключились, и начинаем вечно чего-то ждать от сервера. Как придет ошибка (сервер закрылся) - возвращаемся в п. 1.
На локальных сокетах должно всё мгновенно отрабатывать по идее, даже если жОстко снять процесс сервера.

Лучше заменить на именованный пайп.
Плюс в том, что нет коллизии с другим софтом, который вдруг будет слушать именно этот порт.
Либо можно бродкастить UDP сообщения по типу UPNP протокола.

Мдя...
2 июн 21, 15:03    [22330383]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
Virtual Student
Member

Откуда: Belarus
Сообщений: 347
Dimitry Sibiryakov,
Создаем мьютекс:
Mutex:=OpenMutex(MUTEX_MODIFY_STATE,false,'Имя мьютекса');

Проверяем его владельца:
if Mutex = 0 then
  begin
    CloseHandle(Mutex);
    ShowMessage('Вместо этого делаем что хотим.');
    exit;
  end;

Или тебе необходимо точное количество запущенных копий приложения?
Вот еще ресурс по теме: https://streletzcoder.ru/rabota-s-myuteksami-v-stile-oop-delphi-tmutex/
2 июн 21, 15:16    [22330394]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
softwarer
Member

Откуда: 127.0.0.1
Сообщений: 65922
Блог
Virtual Student, и как это поможет прореагировать в тот момент, когда горец отрубит предпоследнюю голову?
2 июн 21, 15:19    [22330398]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
YuRock
Member

Откуда: Донецк
Сообщений: 4653
Virtual Student

if Mutex = 0 then
  begin
    CloseHandle(Mutex);
  end;

Так да, всё будет работать прекрасно, согласен.
2 июн 21, 15:21    [22330402]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
alekcvp
Member

Откуда:
Сообщений: 2870
Dimitry Sibiryakov
У библиотеки, загруженной в разные процессы, уже лет 25 как нет общего сегмента данных.

+ Уголок извращенца #2

library instcounter;

uses
  WinAPI.Windows;

{$R *.res}

const
  S_EVENT = 'SI_CHECK';
  S_MEMORY = 'SI_COUNTER';

var
  InstanceCount: PInteger = nil;
  hSignalEvent: THandle = 0;
  hMapFile: THandle = 0;

procedure DllMain(Reason: Integer);
var
  Count: Integer;
begin
  if Reason = DLL_PROCESS_ATTACH then
  begin
    hMapFile := CreateFileMapping(INVALID_HANDLE_VALUE, nil, PAGE_READWRITE, 0, SizeOf(Integer), S_MEMORY);
    if hMapFile <> 0 then
      InstanceCount := MapViewOfFile(hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, SizeOf(Integer));
    if InstanceCount <> nil then
      InterlockedIncrement(InstanceCount^);
  end else if Reason = DLL_PROCESS_DETACH then
  begin
    if InstanceCount <> nil then
    begin
      Count := InterlockedDecrement(InstanceCount^);
      UnmapViewOfFile(InstanceCount);
      if Count = 1 then
        SetEvent(hSignalEvent);
    end;
    CloseHandle(hMapFile);
  end;
end;

begin
  DllProc := DllMain;
  if hSignalEvent = 0 then
    hSignalEvent := CreateEvent(nil, False, False, S_EVENT);
  DllMain(DLL_PROCESS_ATTACH);
end.

unit siMain;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs;

type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
  private
    FEvent: THandle;
    procedure AppIdle(Sender: TObject; var Done: Boolean);
    procedure DoSingleInstance;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.AppIdle(Sender: TObject; var Done: Boolean);
begin
  if WaitForSingleObject(FEvent, 0) = WAIT_OBJECT_0 then
    DoSingleInstance;
end;

procedure TForm1.DoSingleInstance;
begin
  ShowMessage('Single Instance!');
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  FEvent := CreateEvent(nil, False, False, 'SI_CHECK');
  if LoadLibrary(Pointer(ExtractFilePath(Application.ExeName) + 'instcounter.dll')) = 0 then
    RaiseLastOSError;
  Application.OnIdle := AppIdle;
end;

end.
2 июн 21, 15:38    [22330409]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
Barmaley57
Member

Откуда: Москва
Сообщений: 5866
alekcvp,
MSDN
If you terminate a process by calling TerminateProcess or TerminateJobObject, the DLLs of that process do not receive DLL_PROCESS_DETACH notifications. If you terminate a thread by calling TerminateThread, the DLLs of that thread do not receive DLL_THREAD_DETACH notifications.
2 июн 21, 15:43    [22330410]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
alekcvp
Member

Откуда:
Сообщений: 2870
Barmaley57,

Мда, печалько. Тогда первый вариант остаётся в силе 😃
2 июн 21, 15:45    [22330412]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
Barmaley57
Member

Откуда: Москва
Сообщений: 5866
alekcvp
procedure TForm1.AppIdle(Sender: TObject; var Done: Boolean);
begin
  if WaitForSingleObject(FEvent, 0) = WAIT_OBJECT_0 then
    DoSingleInstance;
end;
Шик-модерн!
2 июн 21, 15:45    [22330413]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
Гаджимурадов Рустам
Member

Откуда:
Сообщений: 62803
DS> счётчик ссылок с сигнализацией

Для начала нужно уточнить, нужен ли этот счётчик.
Ибо для обозначенной в первом посте задачи он
нафиг не сдался.

Posted via ActualForum NNTP Server 1.5

2 июн 21, 15:46    [22330414]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
Virtual Student
Member

Откуда: Belarus
Сообщений: 347
YuRock,
Извиняйте господа, с форума другого стащил.
P.S.: Пивной выходной у меня сегодня... :)
2 июн 21, 15:47    [22330416]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
Barmaley57
Member

Откуда: Москва
Сообщений: 5866
Гаджимурадов Рустам
DS> счётчик ссылок с сигнализацией

Для начала нужно уточнить, нужен ли этот счётчик.
Ибо для обозначенной в первом посте задачи он
нафиг не сдался.
Расшифруй мысль.
2 июн 21, 15:50    [22330419]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
Гаджимурадов Рустам
Member

Откуда:
Сообщений: 62803
Barmaley57> Расшифруй мысль.

Что там расшифровывать? Для решения задачи
"последнего выжившего оставшегося" счётчик
не нужен, совсем. Если, конечно, не хочется
где-нибудь в уголочке светить красненьким
"запущено 7 экз-в" и чтобы эта 7 была "живой".

Posted via ActualForum NNTP Server 1.5

2 июн 21, 16:19    [22330441]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
Barmaley57
Member

Откуда: Москва
Сообщений: 5866
Гаджимурадов Рустам
Barmaley57> Расшифруй мысль.

Что там расшифровывать? Для решения задачи
"последнего выжившего оставшегося" счётчик
не нужен, совсем. Если, конечно, не хочется
где-нибудь в уголочке светить красненьким
"запущено 7 экз-в" и чтобы эта 7 была "живой".
Мысль не ясна. Процессу надо узнать, что он остался один. Каков твой вариант?
2 июн 21, 16:23    [22330447]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
Гаджимурадов Рустам
Member

Откуда:
Сообщений: 62803
Barmaley57> Процессу надо узнать, что он остался один. Каков твой вариант?

Именно, что один, а не "сдох предпредпоследний".

Например, захватываешь мьютекс и доволен, ты один.
Остальные (в отдельном потоке) ждут этого мьютекса.
Когда захватчик отпускает (или помирает) - просыпается
один из спящих, захватывает. Требований к очередности
захвата в стартовом посте не заявлено.

Posted via ActualForum NNTP Server 1.5

2 июн 21, 16:44    [22330457]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
Barmaley57
Member

Откуда: Москва
Сообщений: 5866
Гаджимурадов Рустам,
ТС
Например, запущено три.
Хочу решить такую задачу - мне нужно отреагировать в момент, когда пользователь закрывает два экземляра, и остается только один (последний).
2 июн 21, 16:49    [22330464]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
Dimitry Sibiryakov
Member

Откуда:
Сообщений: 53436

alekcvp
Уголок извращенца #2

О, как внезапно "семафоры" превращаются в "shared memory + atomic counter"... А теперь
возвращаемся на первую страницу и перечитываем первые три сообщения.

Posted via ActualForum NNTP Server 1.5

2 июн 21, 16:52    [22330471]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
Гаджимурадов Рустам
Member

Откуда:
Сообщений: 62803
Barmaley57> пользователь закрывает два экземляра,
Barmaley57> и остается только один (последний).

Это не проблема. Проблема, если закрывают два последних,
а "главный" (держатель мьютекса) ещё работает. В общем,
нужно уточнять, что и для чего ему нужно - наверняка, он
хочет "прибрать" за собой ресурсы или что-то вроде того.

Posted via ActualForum NNTP Server 1.5

2 июн 21, 17:23    [22330497]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
alekcvp
Member

Откуда:
Сообщений: 2870
Dimitry Sibiryakov

О, как внезапно "семафоры" превращаются в "shared memory + atomic counter"... А теперь
возвращаемся на первую страницу и перечитываем первые три сообщения.


1. Про семафоры я ничего не писал.
2. На первой странице я привёл работающее у меня решение на мьютексах.
3. Просто счётчик в Shared Memory не катит из-за аварийного завершения процессов. Я просто не знал, что для dll тоже не выхывается нотификация при убийстве процесса, так что это решение тоже не подходит.

Сообщение было отредактировано: 2 июн 21, 17:42
2 июн 21, 17:49    [22330502]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
_Vasilisk_
Member

Откуда: Украина, Харьков
Сообщений: 12885
Barmaley57
Каждый процесс создаёт в заведомо известном каталоге временный файл (флаг FILE_FLAG_DELETE_ON_CLOSE) и подписывается на изменения содержимого каталога.
Всё. Телемаркет.
Красиво. Если отбросить проблему конфликтов, то решение самое работоспособное
2 июн 21, 19:31    [22330554]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
Maxim Rusov
Member

Откуда: Москва-Питер
Сообщений: 2498
А теперь давайте все тоже самое - но кроссплатформенно.
2 июн 21, 22:06    [22330619]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
YuRock
Member

Откуда: Донецк
Сообщений: 4653
Maxim Rusov
А теперь давайте все тоже самое - но кроссплатформенно.
Я предлагал сокеты
2 июн 21, 22:30    [22330626]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
Fr0sT-Brutal
Member

Откуда:
Сообщений: 755
Maxim Rusov
А теперь давайте все тоже самое - но кроссплатформенно.

В Лине как раз временный файл по типу PID больше распространен. Да и там намного легче создать и юзать именованный файловый сокет
3 июн 21, 10:19    [22330760]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
Мимопроходящий
Member

Откуда: бурятский тундрюк, эсквайр
Сообщений: 32387

я так подозреваю, граждане, что Квейд подался в партизаны...

Posted via ActualForum NNTP Server 1.5

3 июн 21, 11:31    [22330808]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
Квейд
Member

Откуда: Kyiv, Ukraine
Сообщений: 5406
Fr0sT-Brutal
Надо именно ловить момент, когда экземпляр остается в одиночестве? Чтобы из реплики стать мастером?
Да
7 июн 21, 13:23    [22332251]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
Квейд
Member

Откуда: Kyiv, Ukraine
Сообщений: 5406
Мимопроходящий
а где ТС?
На связи
7 июн 21, 13:25    [22332254]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
Квейд
Member

Откуда: Kyiv, Ukraine
Сообщений: 5406
softwarer
Мимопроходящий
а где ТС?

Сделал всё на семафорах после первого коммента :)
А если приложение будет завершено нестандартно, например через диспетчер задач - семафор будет освобожден?
7 июн 21, 13:26    [22332257]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
Квейд
Member

Откуда: Kyiv, Ukraine
Сообщений: 5406
Гаджимурадов Рустам
В общем,
нужно уточнять, что и для чего ему нужно - наверняка, он
хочет "прибрать" за собой ресурсы
Верно, именно так
7 июн 21, 13:29    [22332260]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
Мимопроходящий
Member

Откуда: бурятский тундрюк, эсквайр
Сообщений: 32387

07.06.2021 13:29, Квейд пишет:
> Верно, именно так

ты задачу-то опиши.
а то народ и дальше будет городить огороды.

Posted via ActualForum NNTP Server 1.5

7 июн 21, 13:35    [22332263]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
Квейд
Member

Откуда: Kyiv, Ukraine
Сообщений: 5406
Гаджимурадов Рустам
Автор невовремя пропал, конечно.
Квейд
Хочу решить такую задачу - мне нужно отреагировать в момент,
когда пользователь закрывает два экземляра, и остается только один (последний).

Для этого reference counter не нужен.


А если остается "последний", после чего пользователь опять запускает второй экземпляр, а первый - закрывает?
Не могу уложить в голове, как тогда обойтись без счетчика ссылок.
7 июн 21, 13:36    [22332264]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
Квейд
Member

Откуда: Kyiv, Ukraine
Сообщений: 5406
Мимопроходящий

07.06.2021 13:29, Квейд пишет:
> Верно, именно так

ты задачу-то опиши.
а то народ и дальше будет городить огороды.
Мне нужно чистить хитрый внешний ресурс при закрытии приложения, и есть условие что это надо делать только если в системе запущен один экземпляр программы.
7 июн 21, 13:39    [22332269]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
Dimitry Sibiryakov
Member

Откуда:
Сообщений: 53436

Квейд
Не могу уложить в голове, как тогда обойтись без счетчика ссылок.

Проблема в том, что и счётчик ссылок тебе в этом случае не поможет.

Posted via ActualForum NNTP Server 1.5

7 июн 21, 13:41    [22332273]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
Квейд
Member

Откуда: Kyiv, Ukraine
Сообщений: 5406
Dimitry Sibiryakov

Квейд
Не могу уложить в голове, как тогда обойтись без счетчика ссылок.

Проблема в том, что и счётчик ссылок тебе в этом случае не поможет.
Почему? Если счетчик равен единице, значит "мы последние". На первый взляд все просто. Что я мог пропустить?
7 июн 21, 13:54    [22332279]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
Dimitry Sibiryakov
Member

Откуда:
Сообщений: 53436

Квейд
Что я мог пропустить?

Гонки потоков.

В твоём случае я бы вынес работу с "хитрым внешним ресурсом" в сервис, который всегда
один, а из приложений уже взаимодействовал с ним.

Posted via ActualForum NNTP Server 1.5

7 июн 21, 14:06    [22332294]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
Кроик Семён
Member

Откуда: СПб --> Dortmund
Сообщений: 6743
Квейд,

А если по таймеру из каждого инстанса мониторить список процессов, можно было бы поймать тот момент, когда определённый EXEшник остался один.

Если же не хочется привязываться к имени EXE файла, то можно было бы в каждом создать через AllocateHWnd невидимое окно со специфическими свойствами и периодически мониторить окна верхнего уровня.
7 июн 21, 17:41    [22332463]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
_Vasilisk_
Member

Откуда: Украина, Харьков
Сообщений: 12885
Кроик Семён
можно было бы поймать тот момент, когда определённый EXEшник остался один.
Можно. А в следующий тик их будет два
7 июн 21, 18:48    [22332495]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
alekcvp
Member

Откуда:
Сообщений: 2870
_Vasilisk_
Кроик Семён
можно было бы поймать тот момент, когда определённый EXEшник остался один.
Можно. А в следующий тик их будет два

От этого ты никак не застрахуешься в обычной операционной системе. Разве что перед проверкой устанавливать какой-нибудь эвент, который запрещает запуск новых экземпляров.
8 июн 21, 13:48    [22332858]     Ответить | Цитировать Сообщить модератору
 Re: Глобальный reference counter для нескольких процессов?  [new]
Мимопроходящий
Member

Откуда: бурятский тундрюк, эсквайр
Сообщений: 32387

08.06.2021 13:48, alekcvp пишет:
> От этого ты никак не застрахуешься в обычной операционной системе.

в обычной операционной системе есть стандартные функции, дабы не заниматься велосипедированием.
но почему-то большинство участников дискуссии их предпочитают игнорировать.

Posted via ActualForum NNTP Server 1.5

8 июн 21, 13:53    [22332866]     Ответить | Цитировать Сообщить модератору
Топик располагается на нескольких страницах: 1 2 3 4      [все]
Все форумы / Delphi Ответить