任务间的异步数据交换
Asynchronous data exchange between tasks
“Toit 中的任务”部分的文档表明该语言具有在任务之间进行异步数据交换的功能。如果我理解正确,那么监控包中的两个 classes:Channel 和 Mailbox 提供了这个机会。不幸的是,我没有找到使用这些 classes 的例子,所以我请你至少给出两个任务的实现的最简单的例子:
- 其中一个任务是消息生成器,例如,它发送
整数或字符串到第二个任务。第二个任务得到这些
数字或字符串。也许在这种情况下 Channel class 应该
被使用。
- 这两个任务中的每一个都是消息的生成者和接收者。
那些。第一个任务向第二个任务发送消息,然后依次
异步接收第二个任务生成的消息。
从描述来看,Mailbox class 应该用在
这种情况。
提前致谢,
MK
感谢提问。
这是第一部分的示例,使用 Channel。如果您有用于另一项任务的消息流,此 class 很有用。
import monitor
main:
// A channel with a backlog of 5 items. Once the reader is 5 items behind, the
// writer will block when trying to send. This helps avoid unbounded memory
// use by the in-flight messages if messages are being generated faster than
// they are being consumed. Decreasing this will tend to reduce throughput,
// increasing it will increase memory use.
channel := monitor.Channel 5
task:: message_generating_task channel
task:: message_receiving_task channel
/// Normally this could be looking at IO ports, GPIO pins, or perhaps a socket
/// connection. It could block for some unknown time while doing this. In this
/// case we just sleep a little to illustrate that the data arrives at random
/// times.
generate_message:
milliseconds := random 1000
sleep --ms=milliseconds
// The message is just a string, but could be any object.
return "Message creation took $(milliseconds)ms"
message_generating_task channel/monitor.Channel:
10.repeat:
message := generate_message
channel.send message
channel.send null // We are done.
/// Normally this could be looking at IO ports, GPIO pins, or perhaps a socket
/// connection. It could block for some unknown time while doing this. In this
/// case we just sleep a little to illustrate that the data takes a random
/// amount of time to process.
process_message message:
milliseconds := random 1000
sleep --ms=milliseconds
print message
message_receiving_task channel/monitor.Channel:
while message := channel.receive:
process_message message
这里是一个使用邮箱的例子。如果您有一个任务处理请求并响应其他任务,这个 class 很有用。
import monitor
main:
mailbox := monitor.Mailbox
task:: client_task 1 mailbox
task:: client_task 2 mailbox
task --background:: factorization_task mailbox
/// Normally this could be looking at IO ports, GPIO pins, or perhaps a socket
/// connection. It could block for some unknown time while doing this. For
/// this example we just sleep a little to illustrate that the data arrives at
/// random times.
generate_huge_number:
milliseconds := random 1000
sleep --ms=milliseconds
return (random 100) + 1 // Not actually so huge.
client_task task_number mailbox/monitor.Mailbox:
10.repeat:
huge := generate_huge_number
factor := mailbox.send huge // Send number, wait for result.
other_factor := huge / factor
print "task $task_number: $factor * $other_factor == $huge"
// Factorize a number using the quantum computing port.
factorize_number number:
// TODO: Use actual quantum computing instead of brute-force search.
for i := number.sqrt.round; i > 1; i--:
factor := number / i
if factor * i == number:
return factor
// This will yield so the other tasks can run. In a real application it
// would be waiting on an IO pin connected to the quantum computing unit.
sleep --ms=1
return 1 // 1 is sort-of a factor of all integers.
factorization_task mailbox/monitor.Mailbox:
// Because this task was started as a background task (see 'main' function),
// the program does not wait for it to exit so this loop does not need a real
// exit condition.
while number := mailbox.receive:
result := factorize_number number
mailbox.reply result
我很确定邮箱示例在 3 月底运行良好。我决定现在检查它并得到错误:
如果是 Console Toit:
./web.toit:8:3:错误:参数不匹配:'task'
任务 --background:: factorization_task 邮箱
^~~~
编译失败。
如果是终端:
microcx@microcx-desktop:~/toit_apps/Hsm/communication$ toit execute mailbox_sample.toit
mailbox_sample.toit:8:3:错误:参数不匹配:'task'
任务 --background:: factorization_task 邮箱
^~~~
编译失败。
可能是因为最新的SDK更新了。以防万一:
Toit 命令行界面:
| v1.0.0 | 2021-03-29 |
“Toit 中的任务”部分的文档表明该语言具有在任务之间进行异步数据交换的功能。如果我理解正确,那么监控包中的两个 classes:Channel 和 Mailbox 提供了这个机会。不幸的是,我没有找到使用这些 classes 的例子,所以我请你至少给出两个任务的实现的最简单的例子:
- 其中一个任务是消息生成器,例如,它发送 整数或字符串到第二个任务。第二个任务得到这些 数字或字符串。也许在这种情况下 Channel class 应该 被使用。
- 这两个任务中的每一个都是消息的生成者和接收者。 那些。第一个任务向第二个任务发送消息,然后依次 异步接收第二个任务生成的消息。 从描述来看,Mailbox class 应该用在 这种情况。
提前致谢, MK
感谢提问。
这是第一部分的示例,使用 Channel。如果您有用于另一项任务的消息流,此 class 很有用。
import monitor
main:
// A channel with a backlog of 5 items. Once the reader is 5 items behind, the
// writer will block when trying to send. This helps avoid unbounded memory
// use by the in-flight messages if messages are being generated faster than
// they are being consumed. Decreasing this will tend to reduce throughput,
// increasing it will increase memory use.
channel := monitor.Channel 5
task:: message_generating_task channel
task:: message_receiving_task channel
/// Normally this could be looking at IO ports, GPIO pins, or perhaps a socket
/// connection. It could block for some unknown time while doing this. In this
/// case we just sleep a little to illustrate that the data arrives at random
/// times.
generate_message:
milliseconds := random 1000
sleep --ms=milliseconds
// The message is just a string, but could be any object.
return "Message creation took $(milliseconds)ms"
message_generating_task channel/monitor.Channel:
10.repeat:
message := generate_message
channel.send message
channel.send null // We are done.
/// Normally this could be looking at IO ports, GPIO pins, or perhaps a socket
/// connection. It could block for some unknown time while doing this. In this
/// case we just sleep a little to illustrate that the data takes a random
/// amount of time to process.
process_message message:
milliseconds := random 1000
sleep --ms=milliseconds
print message
message_receiving_task channel/monitor.Channel:
while message := channel.receive:
process_message message
这里是一个使用邮箱的例子。如果您有一个任务处理请求并响应其他任务,这个 class 很有用。
import monitor
main:
mailbox := monitor.Mailbox
task:: client_task 1 mailbox
task:: client_task 2 mailbox
task --background:: factorization_task mailbox
/// Normally this could be looking at IO ports, GPIO pins, or perhaps a socket
/// connection. It could block for some unknown time while doing this. For
/// this example we just sleep a little to illustrate that the data arrives at
/// random times.
generate_huge_number:
milliseconds := random 1000
sleep --ms=milliseconds
return (random 100) + 1 // Not actually so huge.
client_task task_number mailbox/monitor.Mailbox:
10.repeat:
huge := generate_huge_number
factor := mailbox.send huge // Send number, wait for result.
other_factor := huge / factor
print "task $task_number: $factor * $other_factor == $huge"
// Factorize a number using the quantum computing port.
factorize_number number:
// TODO: Use actual quantum computing instead of brute-force search.
for i := number.sqrt.round; i > 1; i--:
factor := number / i
if factor * i == number:
return factor
// This will yield so the other tasks can run. In a real application it
// would be waiting on an IO pin connected to the quantum computing unit.
sleep --ms=1
return 1 // 1 is sort-of a factor of all integers.
factorization_task mailbox/monitor.Mailbox:
// Because this task was started as a background task (see 'main' function),
// the program does not wait for it to exit so this loop does not need a real
// exit condition.
while number := mailbox.receive:
result := factorize_number number
mailbox.reply result
我很确定邮箱示例在 3 月底运行良好。我决定现在检查它并得到错误:
如果是 Console Toit:
./web.toit:8:3:错误:参数不匹配:'task' 任务 --background:: factorization_task 邮箱 ^~~~ 编译失败。
如果是终端:
microcx@microcx-desktop:~/toit_apps/Hsm/communication$ toit execute mailbox_sample.toit mailbox_sample.toit:8:3:错误:参数不匹配:'task' 任务 --background:: factorization_task 邮箱 ^~~~ 编译失败。
可能是因为最新的SDK更新了。以防万一:
Toit 命令行界面: | v1.0.0 | 2021-03-29 |