> I'm eager to hear if anyone can justify unbuffered mode. If so, perhaps
> in addition to enableBuffering(bool), we could also provide
> disableBuffering(). It reads a whole lot nicer.
I think the majority of people would expect the function calls to
behave in a blocking fashion. I.e. Most people would expect that once
the function returns, the task is complete. Now, you or I, on the
other hand, may expect something completely different.
This is what I think David may have heard rumbling around.
I think keeping status quo for HardwareSerial write() blocking is best
- I can imagine a few scripts behaving differently if switched to
non-blocking.
> But if they do, why would you want to make unbuffered the default? 90%+
> will not understand what disableBuffering does. Heck, they're unlikely
> to ever even find it it the doc ;-> We sure aren't likely to add it to
> the serial example code. So, the typical Arduino user wouldn't call
> disableBuffering, and would be doomed to needlessly slow output.
Actually, I'm scratching my head at what disableBuffering does.
Disable input and/or output buffering? Does that mean that the buffer
is actually not used, freeing up space?
I'd vote for calling it blocking - and be explicit for output.
void setOutputBlocking(boolean value);
While we're at it... it might be nice to make read() blocking as well.
void setInputBlocking(boolean value);
Currently read() is not blocking. If blocking is set, then instead of
returning -1 when nothing is in the queue, it will just wait until a
char is received and return that value.
----
class HardwareSerial : public Stream
{
...
public:
void setInputBlocking(boolean v) { inputBlocking = v; }
void setOutputBlocking(boolean v) { outputBlocking = v; }
private:
boolean inputBlocking;
boolean outputBlocking;
...
}
----
void HardwareSerial::HardwareSerial
: inputBlocking(false),
outputBlocking(true)
{
...
}
...
void HardwareSerial::write(uint8_t)
{
// load data into __txfifo
...
//
if (outputBlocking)
while (__txfifo->count > 0);
}
int HardwareSerial::read(void)
{
if (__rxfifo->count > 0)
// return data from top of __rxfifo
else
if (inputBlocking)
{
while (__rxfifo->count == 0);
// return data from top of __rxfifo
}
}
----
_______________________________________________
___________________________________________________
Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe.
Blocking and buffering are different things. And sketches really
shouldn't block. Blocking is okay in an embedded system when it's
multi threaded. Arduino is single threaded. You block, and nothing
else happens. It's the reason for encouraging people to avoid calling
delay, and instead scheduling ala BlinkWithoutDelay.
With buffering, when write returns the task is complete. You are
assured that the data will be written. The only case where the
difference between "will be" and "has been" written matters is when
the recipient of the data and the sketch are cooperating. In which
case unbuffered writes are still not adequate. There must be a
confirmation sent from the recipient to the sketch, saying in essence
"I have handled your last message, you are free to proceed". In which
case buffered is again better than unbuffered, as buffered I/O makes
the conversation go faster..
The status quo is wrong. If you don't need cooperation with the
recipient, it should be buffered. If you do need cooperation,
unbuffered is even worse, as it does not guarantee proper
coordination, and makes coordination more expensive.
If I'm wrong and there is a valid need for unbuffered writes, you'll
need that behavior maybe 1% of the time. Heck, let's say 10% of the
time. Why set up the default to be correct/better 10% of the time, and
incorrect/worse 90% of the time?
You are correct, we should distinguish between disabling input
buffering vs output buffering.
giuliano
On Jun 10, 2010, at 11:02 PM, Brett Hagman wrote:
>
>> I'm eager to hear if anyone can justify unbuffered mode. If so,
>> perhaps
>> in addition to enableBuffering(bool), we could also provide
>> disableBuffering(). It reads a whole lot nicer.
>
> I think the majority of people would expect the function calls to
> behave in a blocking fashion. I.e. Most people would expect that
> once the function returns, the task is complete. Now, you or I, on
> the other hand, may expect something completely different.
>
> This is what I think David may have heard rumbling around.
>
> I think keeping status quo for HardwareSerial write() blocking is
> best - I can imagine a few scripts behaving differently if switched
> to non-blocking.
>
>
>> But if they do, why would you want to make unbuffered the default?
>> 90%+
>> will not understand what disableBuffering does. Heck, they're
>> unlikely
>> to ever even find it it the doc ;-> We sure aren't likely to add it
>> to
>> the serial example code. So, the typical Arduino user wouldn't call
>> disableBuffering, and would be doomed to needlessly slow output.
>
> Actually, I'm scratching my head at what disableBuffering does.
> Disable input and/or output buffering? Does that mean that the
> buffer is actually not used, freeing up space?
>
> I'd vote for calling it blocking - and be explicit for output.
>
> void setOutputBlocking(boolean value);
>
> While we're at it... it might be nice to make read() blocking as well.
>
> void setInputBlocking(boolean value);
>
> Currently read() is not blocking. If blocking is set, then instead
> of returning -1 when nothing is in the queue, it will just wait
> until a char is received and return that value.
>
>
> ----
>
> class HardwareSerial : public Stream
> {
> ...
> public:
> void setInputBlocking(boolean v) { inputBlocking = v; }
> void setOutputBlocking(boolean v) { outputBlocking = v; }
> private:
> boolean inputBlocking;
> boolean outputBlocking;
> ...
> }
>
> ----
>
> void HardwareSerial::HardwareSerial
> : inputBlocking(false),
> outputBlocking(true)
> {
> ...
> }
>
> ...
>
> void HardwareSerial::write(uint8_t)
> {
> // load data into __txfifo
> ...
> //
> if (outputBlocking)
> while (__txfifo->count > 0);
> }
>
> int HardwareSerial::read(void)
> {
> if (__rxfifo->count > 0)
> // return data from top of __rxfifo
> else
> if (inputBlocking)
> {
> while (__rxfifo->count == 0);
> // return data from top of __rxfifo
> }
> }
> ----
>
>
> _______________________________________________
___________________________________________________
Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe.
> Does anyone want to take a shot at an implementation of a buffered
> serial output?
Done:
http://code.google.com/p/rogue-code/source/browse/#svn/Arduino/cores/arduino-ubercore/trunk/cores/arduino-ubercore
(yeah... ubercore - for the lack of a better name) Please go crazy on
code review - it's open to non-members.
You can pull the full hardware core (ubercore) and test it out with
0018. The boards are labeled as (UberCore) ****. Install the core in
sketchbook/hardware.
(FYI: I already know there is a problem with the ATmega8 compile -
need a special case for the UBBRL & UBRRH - maybe I should just fall
back to using the two registers instead of the single 16 bit register
on the superseded controllers.)
> This might be something we wait until Arduino 1.0 to include. Brett,
> can you say a bit more about your compatibility concerns?
I agree. There isn't really any rush to get it out, but it would be
nice to see it sooner rather than later.
RE: Compatibility concerns - as Giuliano has said, most likely people
would not notice the difference. I just could imagine a few
situations where blocking transmit would be expected by the average
person. I'm probably being overly cautious (again).
b
_______________________________________________
___________________________________________________
Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe.
Oh... I forgot to add:
The FIFO class is from Alex's (Alexander Brevig's) SimpleFIFO class -
kudos to AB!
The great side effect of including the FIFO class, is that users can
use the class as well for whatever they need.
I think we may need to tweak the FIFO code though, since I see a lot
of modulo math - which, if the buffer sizes are not powers of 2, can
really suck up some cycles. The changes should be easy.
Here is the source on AB's code repository:
http://code.google.com/p/alexanderbrevig/source/browse/trunk/Arduino/DataStorage/SimpleFIFO/SimpleFIFO.h
b
_______________________________________________
___________________________________________________
Posted on the Developers mailing list. Go to http://arduino.cc/mailman/listinfo/developers_arduino.cc to subscribe.