Текущий архив: 2008.11.30;
Скачать: CL | DM;
Вниз
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;
Скачать: CL | DM;
Память: 0.48 MB
Время: 0.005 c