|
Boost : |
From: Ion Gaztañaga (igaztanaga_at_[hidden])
Date: 2006-02-11 19:39:43
Hi David,
I think this Shmem review has become a general C++ usage/pattern flame
war that does not benefit Boost or Shmem itself. So I will try to make
some comments about your response. Due to my bad english, please don't
see any irony, or provocation comment in my post. I don't know enough
English to do that.
>>> If you really *must* provide 2-phase construction, then please make it
>>> a special mode that can be enabled with an #ifdef.
>> I see you have strong opinions like me. So, no ifdefs, please.
>
> Then consider making the class with 2-phase initialization a different
> type.
What I want to know is if you consider a library rejection reason if
Shmem provides *both* RAII *and* open/close functions.
>> If you only have to use the constructor to open the shared memory I
>> can't make boost::shmem::shared_memory a member of a class if the
>> class has a different lifetime than the shared memory.
>
> Use boost::optional or scoped_ptr.
Isn't optional a two phase initialization? The optional may be or not
constructed, and you have to check that before using optional. I'm
trying to avoid dynamic allocation so scoped_ptr is not a good enough
solution in my opinion.
>> Even if I have the same lifetime, maybe I have to do some
>> validations/operations to obtain the parameters for the segment that
>> can't be made (or would be really ugly and complicate to do) in the
>> member initialization list.
>
> Sorry, I can't visualize what you're describing.
I meant that with a class that wants to contain a pure-RAII object
without dynamic allocation/optional, it has to initialize the object in
the member constructor list. Imagine that depending constructor
arguments and the constructed other member, you want to open,
open_or_create or create a RAII object. Since you have to initialize
raii in the initializer list, Iyou can only use a constructor type. And
for example, to open raii I need 3 arguments, and to create raii
resource I need 4.
class Holder
{
RAII raii;
public:
Holder(/*some conditions*/)
: raii(/*Create or open depending arguments,
and other temporary results*/)
{}
};
If I have two phase construction (error handling omitted):
class Holder
{
TwoPhase twophase;
public:
Holder(/*some conditions*/)
: raii()
{
/*Depending on passed conditions, open or create*/
if()
twophase.open(/*3 arguments*/)
else
twophase.create(/*4 arguments*/)
//If we throw, the twophase destructor will free resources
}
};
I think that two phase initialization is sometimes easier two programmer
and more clear when following code. I can use optional, but the syntax
is uglier (I have to use operator->) and I think a simple member is
easier to understand.
>> Using RAII only approach I have to
>> dynamically allocate it.
>
> There's always optional.
Like I've said, optional provides two-phase initialization, which is
something you want to avoid, no? An empty optional is clearly "half-baked".
>> And to open another segment I can't reuse
>> the object, I have to destroy it and allocate a new one.
>
> There's no reason you can't make it reopenable.
You are right. But I've understood that some boosters wanted a pure
constructor/destructor approach to open/close semantics, with no
reopen(). I may have understood it wrong, though.
>> Default "empty" state (which is not the same as "zombie", because the
>> class is fully constructed) allows also move semantics between
>> classes.
>
> Having such an empty "destructible-only" state is a an unfortunate but
> necessary side effect of move optimization, but it is not necessary to
> make such objects available for immediate use as the ctor does. After
> moving away, the object is impossible for the user to touch (unless
> move() has been used explicitly).
I agree. But I only wanted to point out that move semantics need an
empty state. I agree that it's clear that normally, once moved, you
clearly don't want to use it. But consider a std::set with of
std::string objects that you have to fill from a a container of
c-strings (I think this problem was in Alexandrescu's last CUJ article).
If you want to avoid any overhead you can:
std::string temp_string;
auto it = source.begin(), itend = source.end();
for( ;it != itend, ++it)
{
temp_string = *it;
string_set.insert(std::move(temp_string));
}
Clearly, the moved object reuse can produce optimal code with move
semantics. Imagine now a container of shared_memory or file_mappings
(which are noncopyable but moveable). I think that a container of
shared_memory elements is more efficient than a container of
smart_ptr<shared_memory> and you don't need to pass through the pointer
syntax. So I think that the reuse of a moved object can produce optimal
code. And surely we will discover more uses to this "moved recycling"
concept.
>> If you can only only the constructor and the destructor to open/close
>> the segment you can't move the object to the target, since the source
>> object can't be in a constructed state without owning the shared memory.
>>
>> I really don't like the "you should ONLY do this" approach.
>
> I don't know what you mean.
When the first reviews commented the RAII absence, I immediately
proposed both RAII *and* open/close approach. The first one would
involve exceptions and the second one return values. But I've understood
that you were proposing *only* RAII approach, considering an additional
two-phase possibility approach a bad design. So I've understood that you
wanted to force me to use a RAII approach under "we should keep the
programmer away from this" excuse. I repeat: I *want* to provide RAII.
But not *only* RAII.
>> That's because what now is cool, some years later is demonized. I
>> want choice. I don't like the approach of boost::thread, so I have
>> to create a new boost::thread object every time I want to launch a
>> thread. And I'm not the only one. With boost::thread, I can't have
>> member boost::thread objects in classes (or I have to use optional<>
>> like hacks)
>>
>> No silver bullet. No Good Thing (tm). If RAII is considered a good
>> approach, I agree with you that I should provide it. But if fstream
>> is good enough for the standard library, I think it can be a good
>> model for Shmem without ifdefs.
>
> That logic is flawed. There are lots of examples of bad design in the
> standard library. fstream is hardly the worst.
Yes. But at that time, surely they were designed under "good practices"
approach. Otherwise they wouldn't be in the standard. Only time will say
if "only RAII" approach won't be broken with future language features.
>> Apart from this, little discussion, now that you are in the Shmem review
>> thread, I would love if you could find time to review it. I think that
>> your C++ knowledge is very interesting for a library that tries to put
>> STL containers in shared memory and memory mapped files.
>
> What I've been discussing here is one of the few deep aspects of my
> C++ knowledge, and one of the few aspects that you're not likely to
> get from others -- i.e. it is to some extent my unique contribution --
> yet it seems like you're not really very interested in it. That
> doesn't leave me feeling very encouraged about further participation.
I *really* understand your reasons, and I *am* interested: that's why I
*will* provide RAII (without wrappers, I repeat). But I want to have
freedom to offer also a exception-less, two phase initialization so that
the programmer has freedom to choose, without ifdefs, and ready to "move
recycling". If RAII is so good, the programmer will use it. But I want
people with no exception support (which is common is restricted
environments) or exception-alergic to have an alternative.
I think that apart from this C++ aspect of your knowledge, there is
plenty of your C++ knowledge that you can use in other aspects of the
library. And I'm really interested in them. Specially, if they are
related to correct uses or better idioms like the previous one. And I
want to support those idioms. I just want to provide some alternatives
apart from your advices.
Regards,
Ion
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk