Страница 1 из 2

быть потоку или не быть

СообщениеДобавлено: 18.06.2009 16:52:38
Attid
решил мыслю подумать, может кто скажет что не так думаю.
правда есть у меня дежавю что что-то подобное думал но не нашел =)

есть у меня небольшой демон, работающий с устройствами.

алгоритм прост до безобразияи рабоет стабильно :
1, загружаем список устройств
2, проверяем их по очереди
3, записываем лог в файл что сделали
4, отчитались в БД что натварили
5. goto 2


все было хорошо пока не появились сетевые устройства
а когда они пропадают, система очень долго может весеть прежде чем вернет что устройство отсутствует.
как я понимаю эта батва на уровне протокола TCP\IP и с этим ничего сделать нельзя, но тормазить очередь нельзя.
вывод надо распаралелится

I класический вариант fork
1 загружаю список устройств
2, создаю клонов согласно купленным билетам каждому даю свою задачу.

возникает вопрос как писаль лог и следить за сиротами. значит надо общаться между собой и строить общение.

II потоки
1, получаю информацию
2, создаю каждому по потоку и там они опрашиваются.
3, в синхронизации пишу все в лог и в БД чтоб не плодить конекты


с логикой вроде понятно. с потоками не разу не сталкивался кроме теоретики.
теперь вопрос
1. какие потоки использовать лучше те которые класические в паскале критические функции или из lcl TTheard ?
2. что есть "потокобезопасная функция" и как их правельно создовать ?

Re: быть потоку или не быть

СообщениеДобавлено: 18.06.2009 20:39:28
Ракшас
все было хорошо пока не появились сетевые устройства
а когда они пропадают, система очень долго может весеть прежде чем вернет что устройство отсутствует.

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

Re: быть потоку или не быть

СообщениеДобавлено: 18.06.2009 22:56:01
Logo
Помойму это наиболее просто, в данном случае:
(uses System;)

BeginThread(@MyProcedure, @MyMem, ID_of_thread);

MyProcedure// процедура обработки
MyMem// Память для общения с Thread (например структура)
var ID_of_thread: QWord // идентефикатор потока.

Можно еще задать стек, но для Линукс это не актуально.


TO: Ракшас
Возможно скажу глупость, но может просто ограничить время на опрос одного устройства? Поставить таймер, по выполнении которого неответившее устройство считается нерабочим/отсутствующим.

Как? Есть идеи? Я не исключаю, что это можно сделать, но не представляю как.

Добавлено спустя 6 минут 27 секунд:
fork полностью копирует приложение в новую область памяти продолжая выполнение с точки после fork. По моему это очень расточительно для памяти, во всяком случае для данной задачи.

Добавлено спустя 8 минут 5 секунд:
что есть "потокобезопасная функция" и как их правельно создовать ?

Не лезть в недопустимые регистры. Если писать без ассемблеровских кодов, то проблем не возникает. INC() и DEC() в потоках нельзя использовать, есть им замена InterLockedDecrement(), InterLockedDecrement64(), InterLockedIncrement(), InterLockedIncrement64(). Какие еще - не помню :oops: Но наводка есть, думаю разберешься.

Re: быть потоку или не быть

СообщениеДобавлено: 19.06.2009 07:06:10
Vadim
Logo писал(а):InterLockedDecrement(), InterLockedDecrement64(), InterLockedIncrement(), InterLockedIncrement64()

Это для WinAPI, а для Линукса?

Re: быть потоку или не быть

СообщениеДобавлено: 19.06.2009 10:54:00
Attid
Ракшас писал(а):но может просто ограничить время на опрос одного устройства?

при работе с сетью не прокатывает. будешь висеть пока система не скажет что устройства нет.


Logo писал(а):BeginThread(@MyProcedure

а для доступа к общем данным что лучше критическую секцию или мутексы или чего еще ?
причем желательно выставить очередь чтобы не получилось что пришли данные от 1 2 3 4

1 захватил ресурс, остальняе стунулись стали ждать 1мс
2 захватил ресурс, 3,4 ждут 1с
а тутвернулся 1 и опять захватил. а 3 4 будут задерживаться

Re: быть потоку или не быть

СообщениеДобавлено: 19.06.2009 11:11:46
Max Rusov
Ну так критическая секция нужна только при доступе к общим ресурсам (записи в лог). По сравнению со временем опроса устройства его можно считать пренебрежимо малым.

Re: быть потоку или не быть

СообщениеДобавлено: 19.06.2009 12:07:59
FedeX
Не лезть в недопустимые регистры. Если писать без ассемблеровских кодов, то проблем не возникает. INC() и DEC() в потоках нельзя использовать, есть им замена InterLockedDecrement(), InterLockedDecrement64(), InterLockedIncrement(), InterLockedIncrement64(). Какие еще - не помню :oops: Но наводка есть, думаю разберешься.

Это для WinAPI, а для Линукса?

Нашел эти функции в rtl (под разные системы), но всё-таки не понял их назначения - я раньше думал, что при переключении потоков система сама сохраняет и переключает стек и все (или почти все) регистры процессора, так что у каждого потока своя копия этих ресурсов... Разве нет? И если нет, то почему тогда только для инкрементов/декрементов такая немилость? Где узнать полный список разрешонных в потоке регистров и операций? У меня в коде уже немало инк-ов и дек-ов в потоках, пока работает, но появились опасения... :o Вообщем откудого такая информация?

а для доступа к общем данным что лучше критическую секцию или мутексы или чего еще ?

То что удобнее в конкретной ситуации..
1 захватил ресурс, остальняе стунулись стали ждать 1мс
2 захватил ресурс, 3,4 ждут 1с
а тутвернулся 1 и опять захватил. а 3 4 будут задерживаться

А зачем им ждать 1 с? Сейчас не имею дело с потоками, но точно помню что какой-то из типов синхронизации (криические секции?) сам притормаживает выполнение потока ровно до того момента когда секция освободиться, тоесть 3 и 4 запустяться сразу после того как 1 освободит критическую секцию (или что там ещё), точнее запуститься тот который запросил её следующим, (напр 3, а 4 останеться ждать..) Вроде так..

Re: быть потоку или не быть

СообщениеДобавлено: 19.06.2009 12:31:18
Attid
FedeX писал(а):Вроде так..

да так и будет и именно с критическими секциями. по крайней мере на стенде =) с ПН поставлю в поле.

я просто сначало спрашиваю что не понятно потом иду експерементировать, если ответят то хорошо и сравниваю результат.

если нет то надеюсь только на свой опыт =)

Re: быть потоку или не быть

СообщениеДобавлено: 19.06.2009 12:57:47
Max Rusov
Interlocked функции нужны только при обращении из разных потоков к общим переменным. Они позволяют в ряде простых случаев обойтись без критической секции. К локальным переменным потока доступ, естественно, свободный.

Re: быть потоку или не быть

СообщениеДобавлено: 19.06.2009 13:25:28
FedeX
А.. Тогда всё понятно :) А то напугали)

редактирование.. О! С этим постом я стал числиться на форуме как "бывалый" :D

Re: быть потоку или не быть

СообщениеДобавлено: 19.06.2009 13:36:13
Logo
Max Rusov писал(а):Interlocked функции нужны только при обращении из разных потоков к общим переменным. Они позволяют в ряде простых случаев обойтись без критической секции. К локальным переменным потока доступ, естественно, свободный.

+100
Вот пример из fpc Help:
Код: Выделить всё
{$mode objfpc} 

uses 
  sysutils {$ifdef unix},cthreads{$endif} ;  //Не понятно! Предупреждают, что "cthreads" должен быт обязательно первым, а в примере второй. Отнесем на ошибку хелпа.

const 
  threadcount = 100; 
  stringlen = 10000; 

var 
   finished : longint; 

threadvar 
   thri : ptrint; 

function f(p : pointer) : ptrint; 

var 
  s : ansistring; 
begin 
  Writeln(’thread ’,longint(p),’ started’); 
  thri:=0; 
  while (thri<stringlen) do 
    begin 
    s:=s+’1’; 
    inc(thri);  //Локальные переменные инкрементируются без проблем
    end; 
  Writeln(’thread ’,longint(p),’ finished’); 
  InterLockedIncrement(finished);  //Инкремент глобальной переменной
  f:=0; 
end; 

var 
   i : longint; 

begin 
   finished:=0; 
   for i:=1 to threadcount do 
     BeginThread(@f,pointer(i)); 
   while finished<threadcount do ; 
   Writeln(finished); 
end. 


Списосок:
InterLockedDecrement
InterLockedIncrement
InterLockedExchange
InterLockedExchangeAdd
InterlockedCompareExchange
Может в fpc 2.3.1 чего изменили, я не смотрел.

Добавлено спустя 12 минут 9 секунд:
Глобальные переменные описаные,как "threadvar " доступны в потоках обычным образом см. пример:
threadvar
thri : ptrint;

Re: быть потоку или не быть

СообщениеДобавлено: 19.06.2009 14:06:49
Sergei I. Gorelkin
Attid писал(а):а для доступа к общем данным что лучше критическую секцию или мутексы или чего еще ?

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

Attid писал(а):причем желательно выставить очередь чтобы не получилось что
пришли данные от 1 2 3 4
1 захватил ресурс, остальняе стунулись стали ждать 1мс
2 захватил ресурс, 3,4 ждут 1с
а тутвернулся 1 и опять захватил. а 3 4 будут задерживаться

Так не получится, потому что пока (2) владеет ресурсом, (3) и (4) ждут не просто так, а на попытке захвата, и как только (2) освободится, ресурс сразу достанется либо (3), либо (4) - поэтому "вернувшийся" (1) не сможет ничего захватить, пока (3) или (4) не освободят.
Но, если учесть, что один или несколько потоков могут застрять на сетевом интерфейсе на пару минут, конечный результат едва ли будет напоминать очередь...

Re: быть потоку или не быть

СообщениеДобавлено: 01.07.2009 00:02:44
Attid
чет я разогнался =(
критические секции висят в
{%MainUnit ../lclintf.pp}
// included by interfacebase.pp and lclintf.pp
тобишь зависимо от виджетов, а их то у меня и нет. как разруливать доступ к общим ресурсам в лине в консоле ?

Re: быть потоку или не быть

СообщениеДобавлено: 01.07.2009 00:12:46
Max Rusov
Enter/Leave CriticalSection определены в System, Вы о чем?

Re: быть потоку или не быть

СообщениеДобавлено: 01.07.2009 14:00:30
Attid
Max Rusov
да я пример в лазаре взял а там используется
InitializeCriticalSection\EnterCriticalSection(CriticalSection);

а о том что еще бывают
InitCriticalSection/EnterCriticalsection как-то подумал :oops:

Добавлено спустя 1 минуту 24 секунды:
кста а чем они отличаются и зачем ини бывают разные ?