Non-blocking 'gets' ?

A

Adam Shelly

Is there a way to perform a non-blocking gets or getc? As in a method
that reads a character from stdin if there is one in the buffer or
returns nil otherwise?

If I was programming a Windows console app in C, I would use kbhit()
to check if there was a character in the buffer. So I decided this
was a good time to try writing my first ruby c extension.

on Windows, save and complie conio.c into conio.dll, and then the
following example should work.
-Adam

--- test_conio.rb ---
require 'conio'
#background work:
Thread.new { print('.') or sleep(1) while true }
#check for input in this thread
Thread.new do
while 1
while !CONIO::kbhit?; end #--wait for key, nonblocking
#s = STDIN::getc #--this blocks until return pressed
s = CONIO::getch #--this doesn't
p "#{s} (#{s.chr})"
exit if s==?q
end
end
#do some foreground work
puts("waiting") or sleep(10) while 1

---
---conio.c---
/* conio.c -- Windows conio functions
3 Oct 2007, Adam Shelly
Ruby license applies
*/
#include "ruby.h"
#include <conio.h>

static VALUE c_kbhit(VALUE self)
{
return _kbhit()? Qtrue : Qfalse;
}

static VALUE c_getch(VALUE self)
{
int n = _getch();
return INT2FIX(n);
}
static VALUE c_ungetch(VALUE self, VALUE cv)
{
int c = FIX2INT(cv);
int n = _ungetch(c);
return INT2FIX(n);
}

VALUE mConio;

__declspec( dllexport ) void Init_conio()
{
mConio = rb_define_module("CONIO");
rb_define_module_function(mConio, "kbhit?", c_kbhit, 0);
rb_define_module_function(mConio, "getch", c_getch, 0);
rb_define_module_function(mConio, "ungetch", c_ungetch, 1);
}
 
S

Stephen Ware

Wow, that is quite complex. Thank you!

I also managed to discover another usable method: run a 'system' command
in a new thread. That seems to release the blocking on gets by creating
a second process, and as far as I can tell will work on both Windows and
*nix. The downside is that the two processes can't really communicate
with each other much, but in my case I don't need them to.

Thanks everyone for you help :)
 
W

Wurzel Cidermaker

Stephen said:
Wow, that is quite complex. Thank you!

I also managed to discover another usable method: run a 'system' command
in a new thread. That seems to release the blocking on gets by creating
a second process, and as far as I can tell will work on both Windows and
*nix. The downside is that the two processes can't really communicate
with each other much, but in my case I don't need them to.

Thanks everyone for you help :)

Stephen,

Can you please provide a very simple 'system' command example as I'm
having the same problem.
 
L

Lloyd Linklater

Why don't you just bind a keypress event? That would capture any given
keystroke in a non blocking way.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,774
Messages
2,569,599
Members
45,177
Latest member
OrderGlucea
Top