This is the mail archive of the
mailing list for the libstdc++ project.
Re: [PATCH] basic_filebuf: 45628 + non-modal I/O
(returning a private thread to the list)
On Sep 22, 2010, at 4:45 PM, Paolo Carlini wrote:
>> Why do we want to export the symbol, even when it is defined?
> basic_filebuf is explicitly instantiated, for char and wchar_t. In
> general the entire explicitly instantiated classes are exported, I never
> really studied in details these *very* old general choices, probably we
> could be more precise now that the inliner is more trustworthy and
> likewise we have extern templates working well and *always* available
> (wasn't the case at the beginning of v3!). To be honest, I don't think
> we should spend so much time on these issues just now, however, seem
> more suited for when we'll break the ABI (when exactly? I don't know, we
> are still discussing the issue with Jason and other people working on
> the C++ front-end).
OK. It's unfortunate that the ABI encompasses every aspect of the runtime data structure. For example, I've already broken user-derived filebuf classes that assume _M_reading will always be false after seekoff. If the user overrode filebuf::overflow, and the first thing it does is call our implementation, and that call was inlined, my change (or any change) to overflow may lead to corrupt state. The very existence of dylib functions and variables with respect to the program (including anything inserted by the inliner) depends on their operational semantics.
Moving forward, we won't have to worry about that at all for functions not called outside the dylib. Which can be ensured with the private access qualifier.
There are two ABI issues: breaking executables and breaking code. We could follow the frontend to a smarter mangling and gain nothing because we want to support all legacy code married to the internals of basic_filebuf. Or we could break old code by marking things private, yet still support the old executables by keeping the same implementation.
Also note, most of the implementation here is behind virtual functions. If we simply don't care about user code which directly accesses _M_reading and _M_writing, it's safe to eliminate/redefine those variables, because they won't be accessed except by virtual calls (which can't be inlined) or inlined direct calls to the virtual functions (a tiny minority, which may break anyway under my change to operational semantics). The non-virtual functions, open and close, only perform zero-initialization which is desirable anyway.
>> I guess I'm a little perplexed at the access policy in basic_filebuf, why everything is protected and not private.
> Well, basic_filebuf has a virtual destructor, people can derive from it,
> protected makes sense, in very general terms. But for sure I agree that
> there are some blurred cases. If you want to present a careful analysis
> about protected vs private for the various classes in the implementation
> and then propose tweaks I think people would be interested.
If users actually in practice derive from the classes, we should provide an interface which allows functionality for them and flexibility for us. But if they don't, marking everything (except the streambuf base class) private would make more sense than protected. There's plenty of functionality they can already access through setp, setg, etc, and intercepting virtual calls. For example, _M_write and _M_read may be eliminated precisely because they are redundant.
Do we know more about actual usage of filebuf derivatives than the testsuite reveals?