views:

200

answers:

4

is it possible to force a thread to return from a call to a blocking function such as a blocking read from a stream ?

int x;
std::cin >> x;

for example...

+5  A: 

No, it's not possible. If you want to find out whether there's data to read, use the select() syscall - if you only read when there's data waiting, you'll never block

Paul Betts
select() unfortunately is not part of standard C++, and won't work on C++ stream objects
anon
All the more reason not to use C++ stream objects.
JSBangs
All the more reason not to use C++ :)
Paul Betts
Of course, select() isn't part of Standard C either :-)
anon
`select()` is not part of any language -- it is a POSIX function and should be available to any languages that interfaces to C on POSIX-compliant systems. It isn't a reason to not to use C++ or its stream objects. You can replace the word C++ with Ruby or Python or D or whatever and you'll not able to use any non-C languages.
KennyTM
A: 

Maybe try the istream::readsome() method. It doesn't wait for the device and only reads what's in the buffer of a buffered stream.

TK
None of the stream functions wait for a device. All of the underlying library does, though. readsome() will not solve the problem.
anon
+1  A: 

You can peek an istream object.

Another method is to have a separate thread permanently waiting on console input and placing the data in a queue or buffer. The interface to the buffer is then up to you, you can make it blocking, non-blocking, or timeout (or all three).

Clifford
+1  A: 

Since it's been said it is not possible, I think it should be great though to give some alternatives.

I usually do some server code and we have the same problem with synchronous calls (blocked) to the database. Sometimes (for whatever reason) the call may not return quickly enough, and you have a limited time for the processing.

The solution we have adopted is pretty simple, and involves MT of course:

  • Upon reception of the query, start a timer which will call a callback at completion
  • If you complete successfully, deactivate the timer, it is not needed now.
  • Do your processing, and after each "blocked" call check the timer (also at other regular intervals would be great): if it's been fired, you have been too long and should abandon the processing and return with all haste. Another thread is now in charge to answer the query since you've been too long.
  • When the timer fires, start a new thread with the callback, this method is supposed to answer in a "best effort" manner and should refrain from using blocked calls. It may use the BOM used by the other thread if the said BOM handles MT correctly (locking and such)

As a matter of habit, we set the timer to a confortable zone between 75% and 95% of the maximum time allowed to process a request (configured by category of requests).

This allows you to neatly avoid the blocking calls. If you don't want to properly synchronize your BOM (since it involves overhead), the "best effort" answer could well be a simple retry message (that's the 95%). If you have cleanup to do or another way (cache?) to answer, you'll need synchronization in part of the BOM at least (that's the 75%).

Matthieu M.