Thanks - I'm persevering with the busy wait for now, but may look at async. I also thought it looked much trickier, but your example code is great so thanks for that.
I did originally try using sockets, but it triggers all kinds of security warnings on a PC when a socket server is set up. I didn't want to worry end users, or required them to put exceptions in their firewalls, etc., when the communication is entirely local. I have also tried using plain files (which works), but watching for changes on the filesystem is ugly and prone to missing things.
Ideally, I'd like to use messages (e.g. via WndProc on Win32). In fact, I've been able to *send* windows messages from Squeak to a vb.net app by calling RegisterWindowMessage / SendMessage in user32.dll, but I couldn't find any way of receiving messages using this system, and I need bi-directional. I presume the VM would need to capture and pass those on to the Squeak image, which it doesn't currently do. If there is some kind of 'user' event channel I could use, please do suggest something...
Hence pipes was the least worst option so far.
Thanks again,
Dave
On Fri, Jan 10, 2014 at 3:37 PM, Levente Uzonyi-2 [via Smalltalk] < ml-node+s1294792n4735726h10@n4.nabble.com> wrote:
On Fri, 10 Jan 2014, dsl101 wrote:
Hi Ron, Thanks for that - but I can only see #dataAvailable for Sockets, not for
FileStream (named pipes). I think the same kind of thing is available for pipes (you can do `pipe size` to see how much data is there),
but it still doesn't wait. I'm trying to avoid a busy loop waiting for
the data - like this:
FileStreams don't have semaphores, so you can only use busy waiting with them. However there's AsyncFile, which can do what you want. But its interface is a bit cumbersome, and it's hardly tested/used at all. Here's how it could work:
| syncSemaphore file message | syncSemaphore := Semaphore new. file := AsyncFile new. file open: 'your_pipe' forWrite: true. message := 'Here''s Johnny!!!!'. file writeBuffer: message atFilePosition: 0 onCompletionDo: [ syncSemaphore signal ]. (syncSemaphore waitTimeoutMSecs: 3000) ifTrue: [ "handle timeout" ]. file readByteCount: 32 fromFilePosition: 0 onCompletionDo: [ :response | message := response. syncSemaphore signal ]. (syncSemaphore waitTimeoutMSecs: 3000) ifTrue: [ "handle timeout" ]. Transcript show: 'Received: ', message; cr. file close.
Using syncSemaphore is a must, because the callbacks are evaluated from another process.
Levente
P.S.: If you want to communicate with another program from Squeak, then you should use Sockets if possible, since those are versatile and well tested.
start := DateAndTime millisecondClockValue. (pipe size < 32) & (DateAndTime millisecondClockValue - start < 3000)
ifTrue: [
(Delay forMilliseconds 50) wait. ] pipe size = 32 ifTrue: [ "Get data" ] ifFalse: [ "Deal with timeout" ]
The shorter the 'wait', the more responsive the code is to data arriving
on the pipe, but the more CPU it will use as it spins round the loop. The longer the 'wait', the more lag it has for data coming back.
That's what I'm trying to avoid by blocking on the read, but with a way
to escape after some timeout.
I'm guessing the call to 'pipe next:' is a primitive, and blocks there,
which is why valueWithin:onTimeout: doesn't return after the timeout, but does eventually return the correct answer. So, I'm guessing
I'll have to do something like this:
- Set up a semaphore
- Fork the blocking read process, which will signal the semaphore if
it ever returns its 32 bytes
- In the main thread, wait for up to 3 seconds for the semaphore to be
signalled
- If the semaphore times out, kill the forked process
Obviously there's a potential race at the end there, but the worst case
is we throw away data which was returned at the last moment. Is there anything else you can see wrong with this approach?
Thanks,
Dave
On Thu, Jan 9, 2014 at 9:16 PM, Ron Teitelbaum [via Smalltalk] <[hidden
email]> wrote:
Hi Dave, See #dataAvailable ??and #recieveAvailableData. It's never good to call for data if you don't know you have any.
??Better to
setup a wait for data until call instead. ?? All the best, Ron Teitelbaum Head Of Engineering 3d Immersive Collaboration Consulting [hidden email] Follow Me On Twitter: @RonTeitelbaum www.3dicc.com https://www.google.com/+3dicc > -----Original Message----- > From: [hidden email] [mailto:[hidden email] > [hidden email]] On Behalf Of dsl101 > Sent: Thursday, January 09, 2014 10:16 AM > To: [hidden email] > Subject: [Newbies] Read a filestream (named pipe) with a timeout > > I'm using Squeak 4.2 and working on the smalltalk end of a named
pipe
> connection, which sends a message to the named pipe server with: > > msg := 'Here''s Johnny!!!!'. > pipe nextPutAll: msg; flush. > > It should then receive an acknowledgement, which will be a
32-byte md5
hash of
the received message (which the smalltalk app can then verify). It's
possible the
named pipe server may have gone away or otherwise been unable to deal
with
the request, and so I'd like to set a timeout on reading the
acknowledgement.
I've tried using this:
ack := [ pipe next: 32 ] valueWithin: (Duration seconds: 3)
onTimeout: [
'timeout'. ].
and then made the pipe server pause artificially to test the code. But
the
smalltalk thread blocks on the read and doesn't carry on (even after
the
timeout), although if I then get the pipe server to send the correct
response
(after a 5 second delay, for example), the value of 'ack' is
'timeout'.
Obviously
the timeout did what it's supposed to do, but couldn't 'unblock' the
blocking
read on the pipe.
Is there a way to accomplish this even with a blocking FileStream
read?
I'd rather
avoid a busy wait on there being 32 characters available if at all
possible.
Thanks,
Dave
-- View this message in context:
http://forum.world.st/Read-a-filestream-named-
pipe-with-a-timeout-tp4735456.html Sent from the Squeak - Beginners mailing list archive at Nabble.com. _______________________________________________ Beginners mailing list [hidden email] http://lists.squeakfoundation.org/mailman/listinfo/beginners
Beginners mailing list [hidden email] http://lists.squeakfoundation.org/mailman/listinfo/beginners
If you reply to this email, your message will be added to the discussion
below:
http://forum.world.st/Read-a-filestream-named-pipe-with-a-timeout-tp4735456p...
To unsubscribe from Read a filestream (named pipe) with a timeout, click
here.
NAML
View this message in context: Re: Read a filestream (named pipe) with a
timeout Sent from the Squeak - Beginners mailing list archive at Nabble.com.
Beginners mailing list [hidden email] http://user/SendEmail.jtp?type=node&node=4735726&i=0 http://lists.squeakfoundation.org/mailman/listinfo/beginners
If you reply to this email, your message will be added to the discussion below:
http://forum.world.st/Read-a-filestream-named-pipe-with-a-timeout-tp4735456p... To unsubscribe from Read a filestream (named pipe) with a timeout, click herehttp://forum.world.st/template/NamlServlet.jtp?macro=unsubscribe_by_code&node=4735456&code=ZGwzQHBhbGUtZWRzLmNvLnVrfDQ3MzU0NTZ8MTEyNTU4NzUzMg== . NAMLhttp://forum.world.st/template/NamlServlet.jtp?macro=macro_viewer&id=instant_html%21nabble%3Aemail.naml&base=nabble.naml.namespaces.BasicNamespace-nabble.view.web.template.NabbleNamespace-nabble.view.web.template.NodeNamespace&breadcrumbs=notify_subscribers%21nabble%3Aemail.naml-instant_emails%21nabble%3Aemail.naml-send_instant_email%21nabble%3Aemail.naml
-- View this message in context: http://forum.world.st/Read-a-filestream-named-pipe-with-a-timeout-tp4735456p... Sent from the Squeak - Beginners mailing list archive at Nabble.com.