Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

разделение общего ресурса на несколько потоков


Страницы:   1 2

supervk ©   (2006-08-31 05:17:00) 

Есть приложение, в котором работает несколько потоков. И есть общий ресурс, к которому не должен осуществляться одновременный доступ нескольких потоков, а только поочерёдно.

Правильно ли будет разделит его таким образом:

while( !fl_stop )
begin
    WaitForSingleObject(ResourceFree, INFINITE);
    ResetEvent(ResourceFree);
    [... код использующий общие ресурсы ...]
    SetEvent(ResourceFree);
end;
где ResourceFree - общий handle.

Возникает мысль, что все потоки одновременно выйдут из WaitForSingleObject. Если это так, то каким образом лучше сделать такое разделение общего ресурса?


Сергей М.   (2006-08-31 15:29:00) [1]


> supervk ©   (31.08.06 14:34) [26]


Тем не менее в случае с WSAPI не забывай про try..finally..except


supervk   (2006-08-31 14:34:00) [2]


> Надеюсь, ты осознаешь, что UDP есть протокол без гарантии
> доставки ?

Осознаю. ТЗ такое. Клиенты, которым переправляются пакеты, только UDP и понимают.


Сергей М.   (2006-08-31 14:18:00) [3]


> supervk ©   (31.08.06 14:00) [24]


> Через датаграммы UDP


Надеюсь, ты осознаешь, что UDP есть протокол без гарантии доставки ?


supervk   (2006-08-31 14:00:00) [4]


> medved_68   (31.08.06 13:57) [23]
> А кому сливают??? Главному треду приложения или вообще на
> другую машину???

На другие машины в сети. Через датаграммы UDP.


medved_68   (2006-08-31 13:57:00) [5]

supervk
> Потоки обрабатывают информацию получаемую от клиентов, а
> результаты обработки сливают через общий сокет:

А кому сливают??? Главному треду приложения или вообще на другую машину???


supervk   (2006-08-31 13:46:00) [6]


> Сергей М. ©   (31.08.06 13:32) [20]
> Для серьезных серверов, способных максимально быстро реагировать
> на запросы клиентов, такая схема, мягко говоря, не желательна.

Максимум, что будет - 10 потоков. Причем постоянных, отключаться и подключаться они будут редко и то в результате сбоя в сети. Один из главных критериев на данный момент - скорость разработки, а она определяется моими знаниями.
Мне же пока про пулы менеджеров ничего не известно. Но буду иметь ввиду на будущее.


supervk   (2006-08-31 13:45:00) [7]


> Сергей М. ©   (31.08.06 13:32) [20]
> Для серьезных серверов, способных максимально быстро реагировать
> на запросы клиентов, такая схема, мягко говоря, не желательна.

Максимум, что будет - 10 потоков. Причем постоянных, отключаться и подключаться они будут редко и то в результате сбоя в сети. Один из главных критериев на данный момент - скорость разработки, а она определяется моими знаниями.
Про пулы менеджеров мне пока ничего не известно. Но буду иметь ввиду.


Сергей М.   (2006-08-31 13:32:00) [8]


> supervk ©   (31.08.06 11:04) [19]


Для серьезных серверов, способных максимально быстро реагировать на запросы клиентов, такая схема, мягко говоря, не желательна.

Создание и старт нового кодового потока - операция не мгновенная и "тяжелая" для ОС, ее можно сравнить со стартом холодного автодвигателя в морозное время.

В этом плане крайне желательна организация пула и пул-менеджера потоков.


supervk   (2006-08-31 11:04:00) [9]

Что касается кода. Если кому надо/интересно, смысл следующий:

Основной поток создаёт TCP сокет и при подключении клиента выносит его обработку в отдельный поток:

clnt_sock = accept(recv_sock, (struct sockaddr *)&client, &addr_sz);          
CreateThread(NULL, 0, thrd_process_client, this, 0, &thread_id);


Потоки обрабатывают информацию получаемую от клиентов, а результаты обработки сливают через общий сокет:

recv_size = recv(clnt_sock, (char *)buf, buf_sz, 0);
process(buf, buf_sz, send_buf, &makd_size);
::EnterCriticalSection( &locker );
sendto(send_sock, (char *)send_buf, makd_size, 0, (SOCKADDR *)&taddr_addr[i], sizeof(taddr_addr[i]));
::LeaveCriticalSection( &locker );


Сергей М.   (2006-08-31 10:49:00) [10]


> supervk ©   (31.08.06 10:43) [17]


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

EnterCriticalSection(..);
try
 SendTo(..);
finally
 LeaveCriticalSection(..);
end;


supervk   (2006-08-31 10:43:00) [11]

Большое спасибо, очень помогли. Почитал про критические секции, вроде бы то что мне надо. Не использовал их потому что не знал об их существовании.

Что касается программы и кода - речь идёт об использовании несколькими потоками одного - общего сокета для отправки результатов работы потока. Код полностью приводить не стал по причинам:
1) Мудрёности полного кода. Вроде бы как незачем засорять чужие мозги, а  краткую суть проблемного участка я попытался изложить в первом посте.
2) Написан на c++

Т.е. в моём случае в потоки будут использовать код следующим образом:
EnterCriticalSection( Section );
SendTo(soc, buf, len, 0, addr_to, to_len);
LeaveCriticalSection( Section );


Сергей М.   (2006-08-31 10:10:00) [12]

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


Сергей М.   (2006-08-31 10:03:00) [13]


> medved_68 ©   (31.08.06 09:47) [13]


> у него в треде есть выборка сообщений?


Без кода сказать, конечно, сложно.
Просто есть подозрение, что одна из синхронизируемых нитей - основная.


> зачем тогда они нужны, если не для этого?


Ивенты скорее предназначены для использования в кач-ве "стартового пистолета" - ивент просигналил, и всенити, которые ждали этого сигнала, мгновенно "сорвались с места".


medved_68   (2006-08-31 09:57:00) [14]


> Вот мьютексы тут и предпочтительней

Наверное....Без кода спорить.....Ну в любом случае автору виднее, а его логику постигать.....Да и нужно ли нам это???
> Если это так, то каким образом лучше сделать такое разделение
> общего ресурса?

Если следовать его логике (пост1), то все же критическая секция :))


medved_68   (2006-08-31 09:47:00) [15]


> а во-вторых на то есть есть MsgWaitForMultipleObjects()

Сергей МА у него в треде есть выборка сообщений??? И вообще он что нибудь посылает треду??? Вероятность что тред не "проснется" раньше чем надо???Или позже??? Что то много сразу вопросов возникло, как то абстрактно все это!!!
supervkА код можно привести??? А то на кофе гадать, что лучше.... :)))

> Не следует использовать ивенты для межпоточной синхронизации

Сергей МНу а зачем тогда они нужны, если не для этого??? Мы ведь говорим о тредах одного приложения, или нет???


Сергей М.   (2006-08-31 09:39:00) [16]


> medved_68 ©   (31.08.06 09:34) [11]


Вот мьютексы тут и предпочтительней, хотя бы даже по этой причине.
Для случая с мьютексами "анабиоз" не так страшен, поскольку есть WAIT_ABANDONED.


medved_68   (2006-08-31 09:34:00) [17]

Т.е. WaitForSingleObject сбросит событие и уложит поток в анабиоз до наступления события, которое может и не наступить :)))


medved_68   (2006-08-31 09:31:00) [18]


> Я это понял так: событие автоматически сбросится после того,
>  как на него сработает первый же ждущий его поток.
> Т.е. первый WaitForSingleObject, ожидающий его, после срабатывания
> снова сбросит (отключит) этот event.
>
> Я неправильно понял?

Да неправильно. Событие автоматически сбросится при первой командеWaitForSingleObject


Сергей М.   (2006-08-31 09:30:00) [19]


> supervk ©   (31.08.06 09:27) [7]


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


Сергей М.   (2006-08-31 09:28:00) [20]


> А это не блокирование нити


Да, разумеется.
Но, во-первых, никто не завставляет использовать именно INFINITE, а во-вторых на то есть есть MsgWaitForMultipleObjects()


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо