|
Boost : |
From: Jonathan Turkanis (technews_at_[hidden])
Date: 2005-03-10 16:00:00
Rob Stewart wrote:
> From: "Jonathan Turkanis" <technews_at_[hidden]>
>> Rob Stewart wrote:
>>> From: "Jonathan Turkanis" <technews_at_[hidden]>
>>> How about putting a state variable in filters, sources, and sinks
>>> to indicate EAGAIN, EOF, and GOOD. Then, functions that only
>>> read or write a single character can return a bool, and functions
>>> that read or write multiple characters can return a count. If
>>> the bool is false or the count is zero, the code can query the
>>> state to determine whether EAGAIN or EOF occurred. That keeps
>>> the error indication in the return value simple and even leaves
>>> room for adding additional error states should that prove
>>> necessary. Hard errors can still be signaled via exception.
>>
>> This was one of the options I seriously considered. I believe the
>> very first version of the library I posted had this feature. I tend
>> to think it would make life harder for people writing filters and
>> devices to force them to implement an additional function. As things
>> stand, you can often get by with a implementing a single function,
>> and it works pretty well. Also, it makes it harder to fit standard
>> streams and stream bufferss into the framework: stream buffers don't
>> have a state indicator at all; streams do, but it doesn't map well
>> to good/eof/eagain.
>
> Excellent points. I think your current direction is appropriate
> in light of these things.
Good. Thanks.
>>> Yes, they are more readable, but if you don't document the
>>> implementation of those functions, library users will expect to
>>> use them in all situations. Thus, switching to async from sync
>>> I/O will be less of a stylistic change. (That also leaves room
>>> for you to change the implementation details if need be.)
> I meant that if the library user only knows to write "eof(c),"
> and doesn't know that "c == EOF" is an alternative spelling
> because you don't document it, then the user will only ever write
> "eof(c)" whether they are writing a blocking or non-blocking
> filter.
Okay, I understand.
> Whether blocking filters traffic char_traits, while non-blocking
> uses basic_character is a separate question, but I think the
> answer should be obvious: use basic_character in both places.
I agree.
> Then, library users can remain oblivious to char_traits if they
> don't already know about it.
Or if they already know about it they can start to try to forget about it. ;-)
I've started writing some non-blocking filters, and they don't look so bad, as
long as they process one character at a time. So my inclination is to make all
filters non-blocking except for a couple of convenience filters which process an
entire document at a time. In that case, get will always return basic_character.
One more possibility is this:
enum eof_type {
eof
};
enum would_block_type {
would_block
};
template<typename Ch>
class basic_character {
basic_character(Ch = Ch());
basic_character(eof_type);
basic_character(would_block_type);
operator Ch () const;
operator safe_bool () const;
bool operator==(eof_type) const;
bool operator!=(eof_type) const;
bool operator==(would_block_type) const;
bool operator!=(would_block_type) const;
// All the other operators we discussed
};
This would allow the usage:
if (c == eof) { ... }
if (c == would_block) { ... }
How do you like this?
>> This is a real problem with eagain, since testing may not reveal the
>> error unless eagain happens to occur at the right place in a
>> character sequence.
>
> You'll need special test sources and sinks that can be configured
> to produce "would_block" after N calls.
I'm think I might use file devices which process a random number of characters
at a time.
>>> You could return a special
>>> type in lieu of bool, and basic_character in lieu of char_type,
>>> which require inspecting whether they indicate an error
>>> condition. If that query is not done, the destructor can
>>> complain.
>>
>> Could you elaborate? It sounds like it could lead to very poor
>> performance.
>
> I just mean that querying the status sets a flag in the object
> that the dtor checks. If the flag wasn't set, then the dtor
> complains. The complaint code could be an assertion or maybe a
> message printed on stderr. You can even conditionally compile
> away the checks.
That's what I though you meant. I think this might be a good idea for a debug
mode.
Thanks again!
Jonathan
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk