![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Вопрос про многопоточность.
@!!ex © (2007-12-24 18:46:00)Чем грозит такая ситуация:
есть boolean массив.
есть дополнительный поток, который постоянно перебирается все элементы массива и меняет их значения.
Из основного потока периодически берутся значения массива.
Никакой синхронизации нет...
oxffff (2007-12-24 20:47:00) [1]
> DiamondShark © (24.12.07 20:41) [48]
>
> > oxffff © (24.12.07 20:36) [46]
>
> Ты тормоз. ;)
Плакалъ.А ты замерь пересылку.
А прикинь нажал кнопку, и никакого результата.
@!!ex (2007-12-24 20:46:00) [2]Товарищи модераторы, пожалуйста закройте ветку!
Не хочеться, чтобы два хороших человека ругались из-за ерунды!
Задача решена через GetAsyncKeyState:
procedure TKeys.Update;
var
Index:integer;
Key:Smallint;
begin
for Index:=0 to 255 do begin
Key:=GetAsyncKeyState(Index);
if Key And $8000<> OldKeys[Index] And $8000 then begin
Keys[Index]:=(Key And $8000)<>0;
OldKeys[Index]:=Key;
end;
end;
end;
Sapersky, спасибо!
DiamondShark (2007-12-24 20:41:00) [3]
> oxffff © (24.12.07 20:36) [46]
Ты тормоз. ;)
oxffff (2007-12-24 20:38:00) [4]
> @!!ex © (24.12.07 20:33) [45]
Другой поток может вообще не увидить никакого обновления в течении длительного времени на мнопроцессорной машине.
Жмешь кнопку и никакого отклика.
Поток чтения не видит обновления.
oxffff (2007-12-24 20:36:00) [5]
> DiamondShark © (24.12.07 20:31) [43]
Ты реально даже прочитать не можешь SDK.
An application can call this function to retrieve the current status of all the virtual keys. The status changes as a thread removes keyboard messages from its message queue.
@!!ex (2007-12-24 20:33:00) [6]> Ты реально бестолковый дятел.
> Увы запись байта атомарна.
> А вот состояние всего массива не согласовано.
ну и что?
Отклик за 20 мс(это примерно 40 фпс) никто не заметит. Ибо ниочем.
Так что то, что обновится только полокина массива - это фигня.
Меня волновало именно то, что не будет AV.
oxffff (2007-12-24 20:33:00) [7]
> DiamondShark © (24.12.07 20:28) [41]
А ты читай книжки и набивай всою пустую башку.
Родился в день знаний и не хрена не знаешь.
Еще и статьи пишешь.
Как тебя только допустили до статей?
DiamondShark (2007-12-24 20:31:00) [8]
> oxffff © (24.12.07 20:26) [40]
>
> А если прикинь нажал кнопку, а результата нет.
А прикинь, нажал на кнопку, а поток циклом пересылки массива занят. А когда поток освободился, то кнопку уже отпустили.
Трагедия, однако. ;)
Опять фантазии. Теперь на тему критичности приложения.
oxffff (2007-12-24 20:31:00) [9]
> @!!ex © (24.12.07 20:24) [39]
C DI время отклика будет лучше. Гораздо.
Работать очень просто.
Код с моего движка.
DirectInput8.CreateDevice(GUID_SysMouse,DirectInputDeviceMouse,nil);
//if DirectInputDevice.SetCooperativeLevel(Handle,DISCL_BACKGROUND or DISCL_NONEXCLUSIVE)=DI_OK then ;//showmessage('DI_OK');
//DirectInputDeviceMouse.SetCooperativeLevel(Handle,DISCL_FOREGROUND);
DirectInputDeviceMouse.SetCooperativeLevel(Handle,DISCL_NONEXCLUSIVE or DISCL_BACKGROUND);
DirectInputDeviceMouse.SetDataFormat(c_dfDIMouse);
DirectInputDeviceMouse.Acquire;
DirectInput8.CreateDevice(GUID_SysKeyboard,DirectInputDeviceKeyboard,nil);
DirectInputDeviceKeyboard.SetCooperativeLevel(Handle,DISCL_FOREGROUND);
DirectInputDeviceKeyboard.SetDataFormat(c_dfDIKeyboard);
DirectInputDeviceKeyboard.Acquire;
Обработка
param.DirectInputDeviceKeyboard.GetDeviceState(sizeof(diKeys),@diKeys);
if diKeys[DIK_ESCAPE]=$80 then param.DirectInputDeviceMouse.Unacquire;
if diKeys[DIK_W]=$80 then Camera.Walk(300);
if diKeys[DIK_S]=$80 then Camera.Walk(-300);
if diKeys[DIK_A]=$80 then Camera.Yaw(-0.005);
if diKeys[DIK_D]=$80 then Camera.Yaw(0.005);
if param.DirectInputDeviceMouse.GetDeviceState(sizeof(DIMOUSESTATE),@MouseState)=DI _OK then
begin
if MouseState.rgbButtons[0]>0 then Camera.Walk(300);
if MouseState.rgbButtons[1]>0 then Camera.Walk(-300);
if MouseState.lX<>0 then Camera.Yaw(-MouseState.lX/900);
if MouseState.lY<>0 then Camera.Pitch(-MouseState.lY/900);
Camera.CalculateMatrixView(matrixView);
setTransform(D3DTS_VIEW,matrixView);
end;
DiamondShark (2007-12-24 20:28:00) [10]
> Нет, Я это твоя проблема.
Всё. Пипец. Ржу до слёз. :)
Лечись от манечки.
oxffff (2007-12-24 20:26:00) [11]
> Sapersky (24.12.07 20:20) [37]
А если прикинь нажал кнопку, а результата нет.
Так что увы это критично.
@!!ex (2007-12-24 20:24:00) [12]> Также странно и желание автора вопроса использовать GetKeyboardState
> в отдельном потоке. Неужели в основном не работает?
> Как вариант, есть ещё GetAsyncKeyState/DirectInput.
http://www.delphimaster.ru/cgi-bin/forum.pl?n=3&id=1198510244
GetAsyncKeyState чем лучше?
DirectInput - не хочеться привязывать к директиксу. Да и не работал DI никогда.. а под дельфи так вообще с DX Не работал.
oxffff (2007-12-24 20:24:00) [13]
> DiamondShark © (24.12.07 20:11) [33]
>
> > oxffff © (24.12.07 19:52) [31]
>
> Это ты глупый. Не видишь разницы между общим правилом и
> частным случаем.
Частный случай, ты телепат?
Есть правила которых ты не знаешь.
Как раз ты говоришь о частном случае.
> > Это не атомарная операция.
>
> Конечно. Запись байта -- сильно не атомарная операция. ;
> )
> Я поторопился с оценкой "хорошая память". Ты опять забыл,
> какой массив общий.
Массив общий только его состояние будет не согласовано.
Нажал кнопку, а результат позже чем ты ожидаешь.
> > Состояние обновлено частично в момент работы потока чтения.
>
>
> Да. Пол-байта записали. ;)
Ты реально бестолковый дятел.
Увы запись байта атомарна.
А вот состояние всего массива не согласовано.
> > Не видно обновления в потоке чтения, либо видно частично.
>
>
> Булеан значение частично -- это у блондинок.
>
> Ты за весь массив целиком боишься? Зря. Прикладные данные
> в нём такого характера, что это совершенно не критично.
Да ты что? Телепат что ли ты?
Прикинь нажал кнопку, а результата нет.
> > Опять пытаешься съехать.
> Опять твоё воображение.
> Ты почему-то решил, что я давал общий ответ, а не в контексте
> задачи, а потом коварно "съехал".
> Но твои церебральные тараканы -- твоя личная проблема.
Нет, Я это твоя проблема.
Sapersky (2007-12-24 20:20:00) [14]Состояние обновлено частично в момент работы потока чтения.
Не видно обновления в потоке чтения, либо видно частично.
Так и фиг с ним. Это же проверка нажатия клавиш. На этом цикле не увидится - на следующем дойдёт. А нажать так, чтобы за один цикл всё пролетело, ни один юзер не сможет.
Пример из MSDN, если это тот, который с
int iValue;
BOOL fValueHasBeenComputed = FALSE;
- относится к порядку записи значений в память.
В данном случае порядок неважен.
GetKeyboardState
An application can call this function to retrieve the current status of all the virtual keys. The status changes as a thread removes keyboard messages from its message queue.
Обычно GetKeyboardState работает быстрее, чем отлавливание WM_KEYDOWN (т.е. реакция на нажатие кнопок лучше). Здесь же написано, что она фактически привязана к очереди сообщений. Странно...
Также странно и желание автора вопроса использовать GetKeyboardState в отдельном потоке. Неужели в основном не работает?
Как вариант, есть ещё GetAsyncKeyState/DirectInput.
DiamondShark (2007-12-24 20:18:00) [15]
> @!!ex © (24.12.07 20:16) [35]
См. Remarks к функции GetKeyboardState
@!!ex (2007-12-24 20:16:00) [16]> Ни точной постановки задачи, ни твоей реализации нет.
Да как же нет?
Все реализация здесь...
Нужно получить состояние клавиши...
И оно не получается. вот и все.
DiamondShark (2007-12-24 20:15:00) [17]
> Если ты не понимаешь, что операция установки нового состояния
> для всего массива не атомарна
Весь массив никого не волнует.
Вникай в задачу.
Массив здесь только из соображений удобства доступа. А по задаче -- это 256 независимых булевских переменных.
DiamondShark (2007-12-24 20:11:00) [18]
> oxffff © (24.12.07 19:52) [31]
Это ты глупый. Не видишь разницы между общим правилом и частным случаем.
> Это не атомарная операция.
Конечно. Запись байта -- сильно не атомарная операция. ;)
Я поторопился с оценкой "хорошая память". Ты опять забыл, какой массив общий.
> Состояние обновлено частично в момент работы потока чтения.
Да. Пол-байта записали. ;)
> Не видно обновления в потоке чтения, либо видно частично.
Булеан значение частично -- это у блондинок.
Ты за весь массив целиком боишься? Зря. Прикладные данные в нём такого характера, что это совершенно не критично.
> Опять пытаешься съехать.
Опять твоё воображение.
Ты почему-то решил, что я давал общий ответ, а не в контексте задачи, а потом коварно "съехал".
Но твои церебральные тараканы -- твоя личная проблема.
oxffff (2007-12-24 19:56:00) [19]
> DiamondShark © (24.12.07 19:46) [30]
Ты реально не понимаешь проблемы.
Опять пытаешься съехать.
for Index:=0 to 255 do
if NewKeys[Index] shr 7 <> OldKeys[Index] shr 7 then
Keys[Index]:=NewKeys[Index] shr 7 = 1;
Это не атомарная операция.
-> потенциальные проблемы на однопроцессорной машине.
Состояние обновлено частично в момент работы потока чтения.
-> потенциальные проблемы на многопроцессорной машине.
Не видно обновления в потоке чтения, либо видно частично.
oxffff (2007-12-24 19:52:00) [20]
> DiamondShark © (24.12.07 19:44) [29]
Слушай, ты что глупый?
Тебе сказали, что представление памяти для потоков запущенных на разных процессорах в один и тот же момент будет разным.
Если ты не понимаешь, что операция установки нового состояния для всего массива не атомарна, то будут dirty Updates.
Которые могут приводить к проблемам в логике даже на однопроцессорной машине.
На многопроцессорной машине ситуация еще хуще. Ты обновил значения, а другой поток не видит обновления.
А если это критично?