I'm writing a snake game for the terminal, i.e. output via print.
The following works just fine:
while status[snake_monad] do
print to_string draw canvas, compose_all([
frame,
specs,
snake_to_hash(snake[snake_monad])
])
turn! snake_monad, get_dir
move! snake_monad, specs
sleep 0.25
end
But I don't want the turn!ing to block, of course. So I put it into a new Thread and let it loop:
Thread.new do
loop do
turn! snake_monad, get_dir
end
end
while status[snake_monad] do
...
# no turn! here
...
end
Which also works logically (the snake is turning), but the output is somehow interspersed with newlines. As soon as I kill the input thread (^C) it looks normal again.
So why and how does the thread have any effect on my output?
And how do I work around this issue? (I don't know much about threads, even less about them in ruby. Input and output concurrently on the same terminal make the matter worse, I guess...)
Also (not really important): Wanting my program as pure as possible, would it be somewhat easily possible to get the input non-blockingly while passing everything around?
Thank you!
You don't want non-blocking IO - you want unbuffered IO.
There's no need for threads, here - you just need to put your terminal into the right mode and then wait for the keypress on the main event loop.
Here's a completely ridiculous example.
require 'io/wait'
def ping
term = `stty -g`
`stty raw -echo cbreak`
loop do
if STDIN.ready?
#command thy snake!
ret = STDIN.getc
end
if ret
#process the snake command if there was one
STDOUT.write("you told the snake to #{ret}\n")
else
#slither around bitin' fools and hustling apples.
end
end
ensure
`stty #{term}`
end
I found a dirty solution:
I just had to add a carriage return (\r) after each newline in the to_string function, so everything that gets printed after it will be overwritten. Since it was a newline, it loses its effect. Everything seems fine now.
But I'd much rather know why this happens and fix it (if possible) cleanly.
Related
I have code that is running in a manner similar to the sample code below. There are two threads that loop at certain time intervals. The first thread sets a flag and depending on the value of this flag the second thread prints out a result. My question is in a situation like this where only one thread is changing the value of the resource (#flag), and the second thread is only accessing its value but not changing it, is a mutex lock required? Any explanations?
Class Sample
def initialize
#flag=""
#wait_interval1 = 20
#wait_interval2 = 5
end
def thread1(x)
Thread.start do
loop do
if x.is_a?(String)
#flag = 0
else
#flag = 1
sleep #wait_interval
end
end
end
def thread2(y)
Thread.start do
loop do
if #flag == 0
if y.start_with?("a")
puts "yes"
else
puts "no"
end
end
end
end
end
end
As a general rule, the mutex lock is required (or better yet, a read/write lock so multiple reads can run in parallel and the exclusive lock's only needed when changing the value).
It's possible to avoid needing the lock if you can guarantee that the underlying accesses (both the read and the write) are atomic (they happen as one uninterruptible action so it's not possible for two to overlap). On modern multi-core and multi-processor hardware it's difficult to guarantee that, and when you add in virtualization and semi-interpreted languages like Ruby it's all but impossible. Don't be fooled into thinking that being 99.999% certain there won't be an overlap is enough, that just means you can expect an error due to lack of locking once every 100,000 iterations which translates to several times a second for your code and probably at least once every couple of seconds for the kind of code you'd see in a real application. That's why it's advisable to follow the general rule and not worry about when it's safe to break it until you've exhausted every other option for getting acceptable performance and shown through profiling that it's acquiring/releasing that lock that's the bottleneck.
I can't figure out why IO methods won't work on STDIN, when properly set to non-blocking mode:
require 'fcntl'
stdin_flags = STDIN.fcntl(Fcntl::F_GETFL)
p stdin_flags #32770
p STDIN.fcntl(Fcntl::F_SETFL, stdin_flags | Fcntl::O_NONBLOCK) # 0
p STDIN.fcntl(Fcntl::F_GETFL) # 34818
#at_exit { STDIN.fcntl(Fcntl::F_SETFL, stdin_flags & ~Fcntl::O_NONBLOCK) }
STDIN.readline # this call blocks, IO::EAGAINWaitReadable expected
exit
IO.fcntl successfully sets non-blocking mode but all IO functions like read, readline, gets, readchar ignore the mode and hang at reading when no input has been received.
Setting sync mode to true has no effect.
If I replace STDIN.readline with the shell call system('read line') it does work correctly. It won't wait or would wait for input depending if non-blocking mode was set.
I'm aware of IO.read_nonblock but looking for an efficient way how to read newline terminated strings. Calling read_nonblock for each single character is painfully slow.
Can anybody explain this (mis)behavior?
It's a bit unfortunate but standard functions from IO module seem to not respect status flags associated with a file descriptor.
One of the working solutions is use of IO.select class method for input polling, then read the data with regular methods as they become available.
Be aware when line processing methods are used, code may hang until terminating newline character gets consumed. It's advisable to enclose polling code in Timeout block when things are going out of control.
In cases when amount of characters/bytes is known beforehand, stock IO.read_nonblock would simply serve well.
The first Curses.getstr call clears another window. On later calls it doesn't happen.
require "curses"
Curses.init_screen
window = Curses::Window.new(10, 10, 5, 0)
window.scrollok true
Thread.new do
loop do
window.addstr rand(1000000).to_s
window.refresh
sleep 0.1
end
end
Curses.setpos 20, 0
sleep 1
# now several lines of numbers suddenly disappear
loop{ Curses.getstr }
How can I fight this behaviour?
What you're seeing is an implicit refresh() of the stdscr window -- because getstr() is really wgetstr(stdscr). Your options include:
Manually refreshing stdscr before drawing anything
Using your new window for input, rather than stdscr, and/or
Using stdscr for output.
At least, that's the answer I'd give for curses' native C -- I'm not sure how it translates to Ruby.
Running matlab R2010B on Windows 7 Enterprise
In matlab scripts, I save a bunch of results to a word file and then at the end, close and quit word. The code I use is:
WordFname = ['BatInfoDoc' sprintf('%0.3f',now) '.doc']; % serialnumbered filenames
WordFile = fullfile(pwd,WordFname);
WordApp = actxserver('Word.Application');
WordDoc = WordApp.Documents.Add;
WordDoc.SaveAs2(WordFile);
....
WordApp.Selection.TypeText([title2 title3 title4 title5 title6]);
WordApp.Selection.TypeParagraph;
then finally at the end of the script
WordDoc.Close;
WordApp.Quit;
The problem I have is that through my development process, I often crash the matlab script and wind up leaving orphaned WINWORD.EXE processes, each one of which keeps a lock on the file it had been writing.
Up until now I have been using TaskManager to kill these processes one at a time by hand. Having been developing all morning, I find myself with around 20 files I can't delete because they are locked by about 11 orphaned WINWORD.EXE processes!
My question(s):
1) Is there an elegant way to handle the file writing and saving and closing and so on so I don't lock up files and processes when my script crashes out before I get to the part where I close the file and quit word?
2) Is there an elegant way to determine the bad processes from within matlab script and go through and delete them from within a matlab script? That is, can I code my matlab so it cleans up after itself?
ADDED A FEW MINUTES LATER:
By the way, I would prefer NOT to enclose all my code in a big try-catch and then close the windows after I've caught my error. The problem with this is I do like to go to debug mode on error, and caught errors don't bring me to debug mode.
Straight after you create Wordapp, use c = onCleanup(#()Wordapp.Quit). When your function exits, either naturally or with a crash, c will be deleted and its function will execute, quitting Word. If this is part of a script rather than a function, you can manually delete c to quit.
Also - while developing/debugging, I would set Wordapp.Visible to true so you can manually close word if necessary. Set back to false for production.
Use a handle class to delete them automatically.
classdef SafeWord < handle
properties(Access=public)
WordApp;
end
methods(Access=public)
function this = SafeWord(WordApp)
this.WordApp= WordApp;
end
function delete(this)
this.WordDoc.Close;
this.WordApp.Quit;
end
end
end
And the use case:
sw = SafeWord(Word.Application());
WordApplication = sw.WordApp;
% Do something here
% When sw ends its lifecycle, it calls delete.
Here is a related question.
I'm doing some joystick programming in Ruby on Linux using a Ruby extension which wraps the basic functionality of joystick.h. Getting a joystick event is a blocking read by default, but I don't want that to interrupt the game loop.
Currently I'm hacking around it by making non-blocking calls to the joystick and running that in a really fast loop. That works, but it also makes the script use 100% CPU because I want the joystick events as close to real time as possible.
I'm trying to do something like
input = Thread.new do
while e = joystick.event
#event = e
end
end
main = Thread.new do
while true
sleep 0.1
puts #event
end
end
But even then, the joystick.event call blocks the main thread. Am I totally misunderstanding how Ruby threads work, or how joysticks work on Linux? Or is there a totally different way of approaching this that is better?
I needed to make the read call in the C extension using rb_thread_blocking_region. Works perfectly now!