I compared with Jon Hylands and discovered a big difference between my Ubuntu
and his Windows results.
Time millisecondsToRun: [10 timesRepeat: [(Delay forMilliseconds: 1000) wait]]
10015
Time millisecondsToRun: [100 timesRepeat: [(Delay forMilliseconds: 100) wait]]
10015
Time millisecondsToRun: [1000 timesRepeat: [(Delay forMilliseconds: 10) wait]]
13405
Time millisecondsToRun: [10000 timesRepeat: [(Delay forMilliseconds: 1) wait]]
45728
He did the third test and got something like 10250 instead of my 13405.
Is this behavior well-known and understood or is there something wrong with my
install?
---
This is a very well known issue. Different operating systems have very
different minimal timer resolutions. Generally speaking, on Windows and
Mac OS the timer resolution is very close to 1ms whereas most Linux
kernels have *awful* timer resolutions. I have been told that you can
recompile your kernel to fix it but I'm not sure how. The classic
benchmark to verify your timer accuracy is to do something like here:
delay := Delay forMilliseconds: 1.
bag := Bag new.
1000 timesRepeat:[bag add: [delay wait] timeToRun].
bag sortedCounts
On my box it yields "a SortedCollection(941->1 51->2 8->3)" which means
that 94.1% of the delays are true 1msec delays.
---
What you want is the ability for a serial port
to issue an interrupt / signal a semaphore so that your waiting process
gets woken up when something happens. The way to do this is by fixing
the (very, very naive) serial port primitives to add something that
allows you to signal a semaphore upon data availability. There are
examples for this kind of thing in other plugins (like the socket or
async file plugin).
Also, I vaguely remember that John had built a better serial port plugin
(don't remember where I saw this but I'm sure he'll chime in) which may
very well support this out of the box.
> I probably don't understand the primitive serial methods well enough.
> They seem not to block while awaiting input so that requires
> continuously looping to read. Is there a blocking method?
There isn't. Since Squeak doesn't use native threads internally (instead
it uses so-called "green threads") a blocking read would block the
entire VM and completely defeat the purpose of a blocking read. That's
why all such primitives are designed to simply signal a semaphore so
that the process in squeak just sits there doing something like:
dataArrived := Semaphore new.
self registerSemaphoreForSignallingData: dataArrived.
[true] whileTrue:[
dataArrived wait.
self processData.
].
etc.
Cheers,
- Andreas