Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: WinAPI и системное программирование > Существует ли механизм вытеснения из потокозащиты?


Автор: Spike 13.12.2012, 20:36
Ребят, подскажите, куда копать:
Есть данные, используемые разными потоками, одним очень критичным ко времени (как бы RealTime, далее RTT) и одним или несколькими вспомогательными, которые могут и подождать. Думается, что было бы красиво, если RTT когда ему приспичит мог бы вытеснить остальные из защищенного участка, пусть даже ценой потери вспомогательными потоками данных. 
Существует ли какой-то механизм для такого взаимодействия потоков?



Автор: Poseidon 13.12.2012, 20:49
Чем не устраивает повышение приоритета? Приостановка вспомогательных на время выполнения основного? Или я не понял значение слова "вытеснить"?

Автор: Spike 13.12.2012, 21:28
имеется ввиду "вытеснение" из участка потокозащищенного кода, т.е. ситуация, когда второстепенный поток уже в защищенном коде, а главному в это время нужно срочно туда "вломиться"

Автор: bems 13.12.2012, 23:21
А что делать если второстепенный поток уже наполовину изменил общие данные?

Автор: Spike 13.12.2012, 23:41
Допустим что второстепенный поток ничего не меняет, ему доступно только чтение.

Автор: DarkProg 14.12.2012, 00:18
Цитата(Spike @  14.12.2012,  00:41 Найти цитируемый пост)
Допустим что второстепенный поток ничего не меняет, ему доступно только чтение. 

Тогда всё просто на мой взгляд, просто останавливаете поток(если надо вообще убиваете его), используете Synchronize и модифицируете данные. Мне кажется всё.

Автор: northener 14.12.2012, 00:49
Цитата(Spike @  13.12.2012,  20:36 Найти цитируемый пост)
Ребят, подскажите, куда копать

Два ваших последних вопроса наводят меня на мысль, что вы пытаетесь сделать из ОС Windows ОС реального времени. 
Удачи. :(

Автор: bems 14.12.2012, 01:02
Цитата(Spike @  13.12.2012,  23:41 Найти цитируемый пост)
Допустим что второстепенный поток ничего не меняет, ему доступно только чтение. 

тогда не нужно читать в локе. 
добавь общим данным два поля: номер версии данных которая начала записываться (FUpdatingVersion) и номер версии данных которая полностью записана (FUpdatedVersion). Пишущий поток перед записью делает InterlockedIncrement(FUpdatingVersion), потом изменяет данные, потом делает InterlockedIncrement(FUpdatedVersion). Если пишущий поток тоже может быть не один, то всё это включая оба вызова InterlockedIncrement делает внутри лока. Читающий поток без всяких локов запоминает FUpdatingVersion читает сами данные и потом читает FUpdatedVersion.
Если FUpdatingVersion <> FUpdatedVersion значит он скопировал себе данные, с которыми в тот момент работал пишущий поток, и обрабатывать их нельзя. Пусть или повторяет попытку позже, или что ты там предусмотришь для этого случая. Если версии равны, значит данные прочитались целостно.

Цитата(northener @  14.12.2012,  00:49 Найти цитируемый пост)
Два ваших последних вопроса наводят меня на мысль, что вы пытаетесь сделать из ОС Windows ОС реального времени. 
Удачи. :(
вообще-то вроде была real-time надстройка над виндой



Автор: Spike 14.12.2012, 01:08
блин, очень трудно не упустив сути не залезть в дебри....
....
я не совсем правильно выразился, второстепенный поток в особом режиме работы приложения (когда от RTT требуется минимум задержек) может только читать. 

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


Цитата(DarkProg @  14.12.2012,  00:18 Найти цитируемый пост)
просто останавливаете поток(если надо вообще убиваете его)

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


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


Цитата(northener @  14.12.2012,  00:49 Найти цитируемый пост)
Два ваших последних вопроса наводят меня на мысль, что вы пытаетесь сделать из ОС Windows ОС реального времени. Удачи. :(

чх нисколько не полезный пост smile 
во-первых, вопрос я задал лишь один, во-вторых прям уж такого реального реального времени мне не нужно, есть внешние средства для выреальнивания (или отреальнивания), в-третьих, коль уж тут такой вопрос, можно и похоливарить по теме RT (но, пожалуйста, не здесь), в-четвертых, удача - для неудачников )))

Добавлено через 1 минуту и 50 секунд
Цитата(bems @  14.12.2012,  01:02 Найти цитируемый пост)
InterlockedIncrement

крутяк! сегодня как раз на статью про атомарные операции наткнулся, это уже кое-что....

Автор: bems 14.12.2012, 01:17
да, и попробуй еще класс TMultiReadExclusiveWriteSynchronizer из SysUtils

Автор: Spike 14.12.2012, 01:24
Цитата(bems @  14.12.2012,  01:17 Найти цитируемый пост)
TMultiReadExclusiveWriteSynchronizer

Ну судя по описанию это очень хорошо  smile 
Цитата

In applications where threads read from an object or variable frequently and only write to it occasionally, using the multi-read exclusive-write synchronizer instead of a critical section can result in considerable performance improvement. 

Хотя "вытеснения" тут тоже нет, оптимизируется только чтение. Что все равно хорошо!

Автор: northener 14.12.2012, 01:33
Цитата(bems @  14.12.2012,  01:02 Найти цитируемый пост)
вообще-то вроде была real-time надстройка над виндой

Это где?

Добавлено через 2 минуты и 19 секунд
Цитата(Spike @  14.12.2012,  01:08 Найти цитируемый пост)
чх нисколько не полезный пост smile

Это уж мы оценим в будущем.

Автор: Spike 14.12.2012, 01:50
Цитата(northener @  14.12.2012,  01:33 Найти цитируемый пост)
Это где?

[T]winCAT, RTX VenturCom - это навскидку.
Да только мне их не нужно, мне немного по-другому можно делать, без Hard RT. Да и вопрос был о другом )))



Автор: bems 14.12.2012, 01:55
нацарапал класс, иллюстрирующий идею
Код

  TExclusiveFastWriterMultipleSlowReaders<TData> = class
  strict private
    FUpdating,
    FUpdated: Integer;
  strict protected
    function ActualRead: TData; virtual; abstract;
    procedure ActualWrite(const Data: TData); virtual; abstract;
  public
    procedure Write(const Data: TData);
    function TryRead(out Data: TData): Boolean;
  end;

{ TExclusiveFastWriterMultipleSlowReaders<TData> }

function TExclusiveFastWriterMultipleSlowReaders<TData>.TryRead(out Data: TData): Boolean;
var
  Updating: Integer;
begin
  Updating := InterlockedExchangeAdd(FUpdating, 0);
  Data := ActualRead;
  Result := InterlockedExchangeAdd(FUpdated, 0) = Updating;
end;

procedure TExclusiveFastWriterMultipleSlowReaders<TData>.Write(const Data: TData);
begin
  InterlockedIncrement(FUpdating);
  try
    ActualWrite(Data)
  finally
    InterlockedIncrement(FUpdated)
  end;
end;



Цитата(northener @  14.12.2012,  01:33 Найти цитируемый пост)
Это где?

ну вот например http://www.directinsight.co.uk/products/venturcom/rtx.html

Автор: Spike 14.12.2012, 02:01
bems, беспредельный респект и уважуха!!! думаю как это приладить чтоб было красиво

Автор: Spike 20.12.2012, 21:11
Всем привет!
Было не просто... проект не маленький и в-общем-то работающий, внедрение Interlocked-функций субъективно улучшило производительность (конечно, параллельно сделан небольшой рефакторинг и оптимизация). 

Да, поизучал, поэкспериментировал с TMultiReadExclusiveWriteSynchronizer - не совсем то что нужно, насколько я понял - если некий поток хочет что-то записать, он будет ждать пока читающие потоки закончат свои дела. С Interlocked-функциями интереснее - пишущий поток даже не думает что там кто читает, пишет когда нужно и все.

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

Получилось красиво и универсально  smile . bems огромное тебе СПАСИБО за наводку и пример!

P.S.: вот еще полезное
Цитата

The variables for this function must be aligned on a 32-bit boundary; otherwise, this function will behave unpredictably on multiprocessor x86 systems and any non-x86 systems. 



Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)