【发布时间】:2018-09-18 07:40:02
【问题描述】:
Julia 中的任务和并发访问
我想在 Julia 中实现对虚拟键盘的管理,每个虚拟键盘都与一个专用任务(或进程、线程...)相关联。
在 Ada 中,这是通过使用这些虚拟键盘的受保护类型对象和扫描计算机键盘的任务来管理的,如以下代码示例所示。
这如何在 Julia 中实现? 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
但它不起作用!可能是朱莉娅无法做到艾达很容易做到的事情......??或者更可能是我对 Julia 的多任务方面的理解非常糟糕。
【问题讨论】:
-
你在 Julia 中尝试过什么?你看过 Julia 的 Multithreading 和 Parallel Computing 文档吗?
-
我在 Julia 文档中发现的唯一一个似乎接近 Ada 保护对象的主题是“共享数组”,但我不知道如何将它用于我非常简单的目的。
-
我还在文档中看到,通道对于在运行任务之间传递数据非常有用,尤其是那些涉及 I/O 操作的任务。我应该看看那个...
-
我认为 Channels 会运作良好。您是否希望在这里拦截无缓冲的键盘输入?来自键盘的无缓冲击键输入通常是非常特定于操作系统的,并且 Julia 在使用 Gtk 库的 Gtk.jl 等框架之外对这种类型的输入没有太多支持。
-
问题已更新。
标签: concurrency julia ada