Задача и одновременный доступ в Юлии
Я бы хотел реализовать в Julia управление виртуальными клавиатурами, каждая из которых связана с определенной задачей (или процессом, потоком ...).
В Аде это осуществляется с помощью объектов защищенного типа для этих виртуальных клавиатур и задачи, которая сканирует клавиатуру компьютера, как показано в следующем примере кода.
Как это можно реализовать в Юлии? Документация, по-видимому, плохая при одновременном контроле доступа в Юлии.
with Unchecked_Deallocation;
package Buffer is
N : constant := 128;
type Index is mod N;
type Char_Array is array (Index) of Character;
protected type Keyboard is
entry Put (X : in Character);
entry Get (X : out Character);
private
A : Char_Array;
In_Ptr, Out_Ptr : Index := 0;
Count : Integer range 0 .. N := 0;
end Keyboard;
type Keyboard_Ptr is access all Keyboard;
procedure Free is new Unchecked_Deallocation (Keyboard, Keyboard_Ptr);
end Buffer;
package body Buffer is
protected body Keyboard is
entry Put (X : in Character) when Count < N is
begin
A (In_Ptr) := X;
In_Ptr := In_Ptr + 1;
Count := Count + 1;
end Put;
entry Get (X : out Character) when Count > 0 is
begin
X := A (Out_Ptr);
Out_Ptr := Out_Ptr + 1;
Count := Count - 1;
end Get;
end Keyboard;
end Buffer;
task Keyboard_Handler;
task body Keyboard_Handler is
K0 : Character;
Available : Boolean := False;
-- Keyboard_Current : Keyboard_Ptr is defined at upper level
begin
loop
Get_Immediate (K0, Available);
if Available and then Character'Pos (K0) /= 0 then
Keyboard_Current.Put (K0);
end if;
delay 0.06;
end loop;
end Keyboard_Handler;
Один из первых шагов - показать, как перехватывать определенные нажатия клавиш (например, стрелки, w, v) и как передавать им канал. Следующее прекрасно работает в Windows, чтобы снабдить основной процесс информацией с клавиатуры:
ch1 = Channel{String}(128)
function run(ch1::Channel)
while true
c1 = ccall((:_getch, "msvcrt.dll "), Int32,())
if c1 == 224
c2 = ccall((:_getch, "msvcrt.dll "), Int32,())
if c2 == 72
put!(ch1, "KEY UP")
elseif c2 == 80
put!(ch1, "KEY DOWN")
elseif c2 == 77
put!(ch1, "KEY RIGHT")
elseif c2 == 75
put!(ch1, "KEY LEFT")
elseif c2 == 81
put!(ch1, "ALT KEY DOWN")
elseif c2 == 73
put!(ch1, "ALT KEY UP")
end
elseif c1 == Int32('w')
put!(ch1, "w")
elseif c1 == Int32('v')
put!(ch1, "v")
end
end
end
buffer = Channel(run)
for x in buffer
println(x)
end
Теперь я хотел бы передать задачу по своему выбору с клавиатуры. Может быть с чем-то вроде:
using Distributed
addprocs(3)
function tache1(ch::Channel)
for x in ch
println("TACHE 1 :",x)
end
end
function tache2(ch::Channel)
for x in ch
println("TACHE 2 :",x)
end
end
buffer1 = Channel(tache1)
buffer2 = Channel(tache2)
ch1 = buffer1
function run()
while true
c1 = ccall((:_getch, "msvcrt.dll "), Int32,())
if c1 == 224
c2 = ccall((:_getch, "msvcrt.dll "), Int32,())
if c2 == 72
put!(ch1, "KEY UP")
elseif c2 == 80
put!(ch1, "KEY DOWN")
elseif c2 == 77
put!(ch1, "KEY RIGHT")
elseif c2 == 75
put!(ch1, "KEY LEFT")
elseif c2 == 81
put!(ch1, "ALT KEY DOWN")
elseif c2 == 73
put!(ch1, "ALT KEY UP")
end
elseif c1 == Int32('w')
ch1 = Channel(tache1)
elseif c1 == Int32('v')
ch1 = Channel(tache2)
end
end
end
f = @spawnat 1 run()
function t1()
for x in buffer1
println("11111 ",x)
end
end
function t2()
for x in buffer2
println("22222 ",x)
end
end
h1 = @spawnat 2 t1()
h2 = @spawnat 3 t2()
for x in buffer1
println(x)
end
Но это не работает! Может быть, Юля не может сделать то, что Ада может сделать довольно легко ... ?? Или, скорее всего, я очень плохо понимаю многозадачные аспекты Юлии.