Tcl применяет функциональность, подобную «nohang», ко всему каналу, и это делается путем настройки неблокирующего канала.После этого любой read
вернет только те данные, которые есть, gets
вернет только полные строки, которые доступны без ожидания, а puts
(на записываемом канале) организует отправку своего вывода наОС асинхронно. Это зависит от работоспособности цикла событий.
Рекомендуется использовать неблокирующие каналы с зарегистрированным обработчиком событий файла.Вы можете объединить это с неблокированием, чтобы реализовать вашу coolget
идею:
proc coolget {channel callback} {
fileevent $channel readable [list apply {{ch cb} {
if {[gets $ch line] >= 0} {
uplevel [lappend cb $line]
} elseif {[eof $ch]} {
# Remove handler at EOF: important!
fileevent $ch readable {}
}
}} $channel $callback]
}
Это будет работать просто отлично, за исключением того, что вам придется вызывать либо vwait
, либо update
для обработкисобытия (если вы не используете Tk тоже; Tk особенный), поскольку Tcl не будет обрабатывать вещи магически в фоновом режиме;Волшебная фоновая обработка вызывает больше проблем, чем стоит…
Если вы сильно запутались в асинхронной обработке событий, рассмотрите возможность использования сопрограмм Tcl 8.6 для реструктуризации кода.В частности, такой код как Coronet может сильно помочь.Однако это очень сильно зависит от Tcl 8.6, так как более ранние реализации Tcl вообще не поддерживают сопрограммы;низкоуровневая реализация должна была быть переписана с простых C-вызовов на продолжения, чтобы включить эти функции, а это не позволяет осуществлять бэкпорт при разумных усилиях.