[Newbies] Re: Read a filestream (named pipe) with a timeout

2014-01-13 Thread dsl101
Levente,

I gave it a try with the AsyncFile method you outlined, and I hit 2
problems:

1. The named pipe is created in Message mode, but repeated calls to
writeBuffer:atFilePosition:onCompletionDo: seem to concatenate all the
messages together - I couldn't see the equivalent of 'flush' for FileStream
which separates out the messages at the pipe server end.
2. I couldn't find the equivalent of 'size' from FileStream to find out how
much data was available in the next message when reading -
readByteCount:fromFilePosition:onCompletionDo:
seems to want me to pass this value in. Given that the messages vary in
size, this is a little awkward (although I guess I could make it send a
fixed 256-byte message each time, that is bound to bite me later (640kb is
enough for anyone, etc.)).

Anyway, if you have any other thoughts on using AsyncFile, or an
alternative, I'd be most grateful.

Many thanks,

David.


On Fri, Jan 10, 2014 at 3:37 PM, Levente Uzonyi-2 [via Smalltalk] 
ml-node+s1294792n4735726...@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 

RE: [Newbies] Re: Read a filestream (named pipe) with a timeout

2014-01-13 Thread Ron Teitelbaum
Hi David,

 

Go back to sockets.  The pain you are experiencing is not worth saving the
user from answering a firewall warning that nobody pays attention to.

 

FWIW,

 

Ron

 

From: beginners-boun...@lists.squeakfoundation.org
[mailto:beginners-boun...@lists.squeakfoundation.org] On Behalf Of dsl101
Sent: Monday, January 13, 2014 11:16 AM
To: beginners@lists.squeakfoundation.org
Subject: [Newbies] Re: Read a filestream (named pipe) with a timeout

 

Levente,

 

I gave it a try with the AsyncFile method you outlined, and I hit 2
problems:

 

1. The named pipe is created in Message mode, but repeated calls to
writeBuffer:atFilePosition:onCompletionDo: seem to concatenate all the
messages together - I couldn't see the equivalent of 'flush' for FileStream
which separates out the messages at the pipe server end.

2. I couldn't find the equivalent of 'size' from FileStream to find out how
much data was available in the next message when reading -Â
readByteCount:fromFilePosition:onCompletionDo: seems to want me to pass this
value in. Given that the messages vary in size, this is a little awkward
(although I guess I could make it send a fixed 256-byte message each time,
that is bound to bite me later (640kb is enough for anyone, etc.)).

 

Anyway, if you have any other thoughts on using AsyncFile, or an
alternative, I'd be most grateful.

 

Many thanks,

 

David.

 

On Fri, Jan 10, 2014 at 3:37 PM, Levente Uzonyi-2 [via Smalltalk] [hidden
email] 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,