И там же узнал о существовании семафора.
Переделал код вот в такой тест.
- Код: Выделить всё
{$mode objfpc} {$h+} {$codepage UTF8}
uses
Windows, SysUtils;
function QueueUserWorkItem(func: LPTHREAD_START_ROUTINE; Context: pointer; Flags: ULONG): BOOL; stdcall; external kernel32;
var
runningTasks: integer; // = 0
allTasksCompleted: PRTLEvent;
i,iCount:integer;
Sem:HANDLE;
boSemaphore:boolean;
b:byte;
label repeattest;
procedure PrepareTaskQueuing;
begin
if InterlockedIncrement(runningTasks) = 1 then RTLEventResetEvent(allTasksCompleted);
end;
procedure NoteTaskCompleted;
begin
if InterlockedDecrement(runningTasks) = 0 then RTLEventSetEvent(allTasksCompleted);
end;
procedure TaskPen(param: pointer); stdcall;
begin
if boSemaphore then begin
WaitForSingleObject(Sem, INFINITE);
inc(iCount);
ReleaseSemaphore(Sem, 1, nil);
end;
inc(iCount);
writeln('Художник в потоке №' + IntToStr(GetCurrentThreadID) +
' - не знает что такео симафор. Может лучше у программистов спросим? Художники готовят кисточку.');
//Sleep(random(1));
writeln('Кисточка готова. Но мы в потоке №' + IntToStr(GetCurrentThreadID) +
' - не знаем что такое симафор. Без симафора невозможно нарисовать картину. Что такое симафор?');
NoteTaskCompleted;
end;
procedure TaskColors(param: pointer); stdcall;
begin
if boSemaphore then begin
WaitForSingleObject(Sem, INFINITE);
inc(iCount);
ReleaseSemaphore(Sem, 1, nil);
end;
inc(iCount);
writeln('Художник в потоке №' + IntToStr(GetCurrentThreadID) +
' - не знает что такео симафор. Художники готовят краски. Для чего мы это делаем?');
//Sleep(random(1));
PrepareTaskQueuing;
writeln('Требование красок (из потока №' + IntToStr(GetCurrentThreadID) + '). Ты знаешь что такое симафор?');
QueueUserWorkItem(@TaskPen, nil, 0);
writeln('Краски готовы. Что такое симафор? (поток №' + IntToStr(GetCurrentThreadID) + ')');
NoteTaskCompleted;
end;
procedure TaskArt(param: pointer); stdcall;
begin
if boSemaphore then begin
WaitForSingleObject(Sem, INFINITE);
inc(iCount);
ReleaseSemaphore(Sem, 1, nil);
end;
inc(iCount);
writeln('Художник в потоке №' + IntToStr(GetCurrentThreadID) +
' - не знает что такео симафор. Художники готовят холст. Зачем мы это делаем?');
PrepareTaskQueuing;
writeln('Требование красок (из потока №' + IntToStr(GetCurrentThreadID) + '). Ты знаешь что такое симафор?');
QueueUserWorkItem(@TaskColors, nil, 0);
//Sleep(random(1));
writeln('Холст готов. Что такое симафор? (поток №' + IntToStr(GetCurrentThreadID) + ')');
NoteTaskCompleted;
end;
procedure Tasks(param: pointer); stdcall;
begin
if boSemaphore then begin
WaitForSingleObject(Sem, INFINITE);
inc(iCount);
ReleaseSemaphore(Sem, 1, nil);
end;
inc(iCount);
writeln('Попытка выяснить что такое симафор №' + IntToStr(GetCurrentThreadID));
PrepareTaskQueuing;
writeln('Вопрос из потока №' + IntToStr(GetCurrentThreadID) + ': Ты знаешь что такое симафор?');
QueueUserWorkItem(@TaskArt, nil, 0);
//Sleep(random(1));
writeln('выполнено (поток №' + IntToStr(GetCurrentThreadID) + ')');
NoteTaskCompleted;
end;
begin
allTasksCompleted := RTLEventCreate;
boSemaphore := true; // false
Sem := CreateSemaphore(nil, 1, 1, nil);
repeattest:
for i:=1 to 11111 do begin
PrepareTaskQueuing;
writeln('Добавление задачи № '+intToStr(i));
QueueUserWorkItem(@Tasks, nil, 0);
end;
writeln(LineEnding + 'Вопрос задан '+intToStr(iCount)+' художникам. До переезда осталось 666 метров.');
RTLEventWaitFor(allTasksCompleted);
if boSemaphore
then writeln(LineEnding + 'Вопрос задан '+intToStr(iCount)+' художникам, должно быть 88888. До переезда осталось 555 метров.')
else writeln(LineEnding + 'Вопрос задан '+intToStr(iCount)+' художникам, должно быть 44444. До переезда осталось 555 метров.');
readln(b);
iCount := 0;
if b = 1 then begin
boSemaphore := true;
goto repeattest;
end else begin
boSemaphore := false;
goto repeattest;
end;
RTLEventDestroy(allTasksCompleted);
end.
тест работает, но иногда счётчик художников inc(iCount); врёт всего лишь на единицу, из-за потоков.
Попробовал добавить ReleaseSemaphore. Я не знаю правильно или нет я добавил чёртов семафор, но одного художника по прежнему не могу досчитаться. Точнее он по прежнему куда-то "пропадает" (симафор не работает). Скорее всего я неправильно подключил семафор или семафор вообще не для этого.
Суть понять как мне включить семафор?
Правила: если вводится 1 + enter, то пересчитывает с семафором. Если иное то без.