Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 2008.11.30;
Скачать: [xml.tar.bz2];

Вниз

critical section timeouts   Найти похожие ветки 

 
SkyN   (2008-10-03 16:15) [0]

Требуется, чтобы после deadlock"а программа продолжала работать
i := 0;
while (not TryEnterCriticalSection(FLock))and(i<100) do begin
 sleep(100);
 inc(i);
end;
if i=100 then Raise Exception.Create("Deadlock");

правильно ли я решаю задачу?
более простого способа нет?

PS: о том, что таких ситуаций допускать нельзя, я знаю


 
Сергей М. ©   (2008-10-03 16:16) [1]

а где тут дедлок  ?

В упор не вижу ..


 
Rouse_ ©   (2008-10-03 17:44) [2]

if WaitForSingleObject() = WAIT_TIMEOUT then


 
guav ©   (2008-10-03 22:17) [3]

> правильно ли я решаю задачу?

Нет.
TryEnterCriticalSection + Sleep - это не ожидание КС.
В стандартной КС не предусмотрено ожидание с таймаутом. (Хотя, исключение при дедлоке по таймауту предусмотрено, см EXCEPTION_POSSIBLE_DEADLOCK  http://msdn.microsoft.com/en-us/library/ms682608(VS.85).aspx ).
Согласен с
> [2] Rouse_ ©   (03.10.08 17:44)


 
Cobalt ©   (2008-10-05 09:08) [4]

А Дельфи поймёт это исключение?


 
guav ©   (2008-10-05 10:44) [5]

поймёт и в ближайшем except отранслирует в EExternalException, несмотря на то что по ссылке выше написано "Do not handle a possible deadlock exception; instead, debug the application."


 
SkyN   (2008-10-09 17:45) [6]

Спасибо, вот такое решение у меня получилось:
type
 tCriticalSection = class
   private
     fDeadlockTime          : Integer;
     fCriticalSection       : TRTLCriticalSection;
     fEvent                 : THandle;
   public
     constructor Create(const DeadlockTime: Integer = 10000);
     destructor  Destroy; override;
     procedure   lock;
     procedure   unlock;
   published
     property DeadlockTime: integer read fDeadlockTime write fDeadlockTime;
 end;

constructor tCriticalSection.Create(const DeadlockTime: Integer = 10000);
begin
 inherited Create;
 InitializeCriticalSection(fCriticalSection);
 fEvent := CreateEvent(nil, True, False, nil);
 fDeadlockTime  := DeadlockTime;
 trace(ClassName+": tCriticalSection.Create");
end;

destructor tCriticalSection.Destroy;
begin
 CloseHandle(fEvent);
 DeleteCriticalSection(fCriticalSection);
 trace(ClassName+": tCriticalSection.Destroy");
 inherited Destroy;
end;

procedure tCriticalSection.lock;
var
 W: Integer;
begin
 W := WAIT_OBJECT_0;
 ResetEvent(fEvent);
 while (not TryEnterCriticalSection(fCriticalSection))and(WR=WAIT_OBJECT_0) do begin
   trace(ClassName+".wait");
   W := WaitForSingleObject(fEvent, fDeadlockTime);
 end;
 if W = WAIT_OBJECT_0 then trace(ClassName+".Lock")
                      else Raise Exception.Create(ClassName+": Deadlock WR="+IntToStr(WR));
end;

procedure tCriticalSection.unlock;
begin
 trace(ClassName+".Unlock");
 LeaveCriticalSection(fCriticalSection);
 SetEvent(fEvent);
end;

что скажете?
WaitForSingleObject(tCriticalSection, fDeadlockTime) я же не могу сделать?
Насколько я понял из ссылки, этот время для EXCEPTION_POSSIBLE_DEADLOCK  будет одинаковое для всей системы, а хотелось бы менять его в зависимости от объекта.


 
han_malign ©   (2008-10-09 17:52) [7]

Mutex


 
SkyN   (2008-10-09 17:59) [8]

Понял, что цикл должен быть таким:
 while (not TryEnterCriticalSection(fCriticalSection))and(WR=WAIT_OBJECT_0) do begin
   trace(ClassName+".wait");
   WR := WaitForSingleObject(fEvent, fDeadlockTime);
   ResetEvent(fEvent);
 end;

т.к. если есть рекурсия, то unlock будет вызываться несколько раз и SetEvent(fEvent) произойдет до освобождения КС.

Сейчас про Mutex почитаю


 
guav ©   (2008-10-09 22:46) [9]

КС не позволяет ожидать с таймаутом. (EXCEPTION_POSSIBLE_DEADLOCK исключительно для отладки). Ни код [8], ни последующие попытки с TryEnterCriticalSection работать не будут.

Mutex.

(Если уж нужно снизить оверхед, при этом блокировки редки, можно реализовать КС самостоятельно через Event и Interlocked функции).


 
SkyN   (2008-10-16 09:45) [10]

Почему код [6] с изменениями [8] не будет работать? поправьте меня, в чем я ошибаюсь:
 1) Пытаюсь войти в КС
 2) Если не вышло, то ожидаю сообщения об освобождении критической секции, но не больше таймаута
 3) Если дождался сообщения об освобождении КС пытаюсь её захватить
 4) Случился таймаут при ожидании события освобождения КС, сообщаю об ошибке

Недостатком Mutex, по сравнению с КС, считаю сложность рекурсии из одного потока, возможно я ошибаюсь.

Неужели нет стандартных, устоявшихся кодов для данной задачи?


 
guav ©   (2008-10-16 10:20) [11]

> [10] SkyN   (16.10.08 09:45)


> Недостатком Mutex, по сравнению с КС, считаю сложность рекурсии
> из одного потока, возможно я ошибаюсь.

ошибаешься. из нерекурсивного мьютекса легко сделать рекурсивный.
пишу прямо сюда, может и не скомпилится, но идея, думаю, понятна.
type
 TRecursiveMutex = class(TObject)
   FMutex: THandle;
   FRecursionCount: Integer;
   FThd: DWORD;
   function Lock(Timeout: DWORD): Boolean;
   procedure Unlock();
 end;

function TRecursiveMutex.Lock(Timeout: DWORD): Boolean;
begin
 if GetCurrentThreadId() = FThd then
 begin
   Inc(FRecursionCount);
   Result := True;
 end
 else
   Result := WAIT_OBJECT_0 = WaitForSingleObject(FMutex, Timeout);
   if Result then
   begin
     InterlockedExchange(@FThd, GetCurrentThreadId());
     Inc(FRecursionCount);      
   end;
 end;
end;

procedure TRecursiveMutex.Unlock()
begin
 Dec(FRecursionCount);  
 if 0 = FRecursionCount then
 begin
   InterlockedExchange(@FThd, 0);
   ReleaseMutex(FMutex);
 end;
end;



> [10] SkyN   (16.10.08 09:45)


> Неужели нет стандартных, устоявшихся кодов для данной задачи?

Знаю такой, но не для Delphi.


 
SkyN   (2008-10-16 15:55) [12]

спасибо guav, это работает
добавлю, для будущих поколений, что в конструкторе надо
 FMutex := CreateMutex(nil, False, nil);
 FRecursionCount := 0;
 FThd            := 0;

a уничтожая объект
 CloseHandle(FMutex);
Ну а теперь задача давать доступ на чтения для любого количества потоков, а для записи, захватывать монопольно. Но это уже тема следующей ветки :)


 
guav ©   (2008-10-16 16:39) [13]

> Ну а теперь задача давать доступ на чтения для любого количества
> потоков, а для записи, захватывать монопольно.

TMultiReadExclusiveWriteSynchronizer, TSimpleRWSync в Delphi.
Другие реализации: SWMRG Рихтера, boost::shared_butex из Boost.Thread, Slim Reader/Writer (SRW) Locks в Висте.


 
han_malign ©   (2008-10-16 17:02) [14]

Болеете???

to release its ownership, the thread must call ReleaseMutex one time for each time that it obtained ownership (either through CreateMutex or a wait function).


 
guav ©   (2008-10-16 17:07) [15]

:-) Точно, не знал



Страницы: 1 вся ветка

Форум: "Начинающим";
Текущий архив: 2008.11.30;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.49 MB
Время: 0.006 c
15-1222777987
tesseract
2008-09-30 16:33
2008.11.30
Настоящий техсаппорт не читает вопросы :-)


2-1224488717
dmitry_12_08_73
2008-10-20 11:45
2008.11.30
Удаление события мыши


2-1224529956
cruiser
2008-10-20 23:12
2008.11.30
String и повторяющиеся элементы


15-1222826765
Slider007
2008-10-01 06:06
2008.11.30
С днем рождения ! 1 октября 2008 среда


2-1224677195
Серж
2008-10-22 16:06
2008.11.30
Составление сервисом запроса.





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский