|
Boost : |
Subject: [boost] [ptr_container] Questionable strong guarantee of ptr_map::insert()
From: Kazutoshi Satoda (k_satoda_at_[hidden])
Date: 2009-08-17 16:27:08
Hi,
With current implementation of ptr_map::insert(), if an exception is
thrown, the objected pointed by the passed pointer is deleted. Is this
really providing strong guarantee as documented?
I understand strong guarantee as described here.
http://www.boost.org/community/exception_safety.html
> The strong guarantee: that the operation has either completed
> successfully or thrown an exception, leaving the program state exactly
> as it was before the operation started.
I think ptr_map::insert() doesn't provide this guarantee because
deleting the object is a change of the program state.
As more concrete problem, see the attached code. I couldn't find any
way to provide strong guarantee for delayed_inserter::insert_ready()
using ptr_map. I want ready_value unchanged if an exception is thrown
during the insertion.
Looking for a solution on a similar situation, I found constructors of
shared_ptr. Its documentation clearly says that "If an exception is
thrown, delete p is called". And for auto_ptr version, it provides
strong guarantee by taking the auto_ptr as non-const reference.
I think ptr_map::insert() should follow this manner; document the
deletion on exception for raw pointer version, and provide strong
guarantee with insert(const key_type& key, std::auto_ptr<U>& x) .
The the auto_ptr& version can be a better replacement of the raw pointer
version. The required temporary of auto_ptr, instead of key_type, is
more expressive (about the purpose of the temporary), and matches the
Best Practices shown in the documentation of shared_ptr.
http://www.boost.org/libs/smart_ptr/shared_ptr.htm#BestPractices
But, introducing the auto_ptr& version seems to cause some change of
behavior in client codes using the current pass-by-value version. Is it
valid to request (create a ticket) for strong guaranteed (taking
auto_ptr&) version while having this compatibility concern?
Regards.
-- k_satoda
#include <memory>
#include "boost/ptr_container/ptr_map.hpp"
namespace ptr_map_insert_strong_guarantee_demo {
class value
{
public:
explicit value(int source);
// ...
};
class delayed_inserter
{
public:
// ...
// This is called from context that knows key and source of value,
// but doesn't know the time of insertion.
void ready_new(int key, int source)
{
// OK.
// This implementation offers strong guarantee for this call.
std::auto_ptr<value> new_value(new value(source));
ready_key = key;
ready_value = new_value;
}
// This is called from context which doesn't know key and value,
// but knows the time of insertion.
void insert_ready()
{
if (ready_value.get() != 0)
{
// I want to offer strong guarantee for this call,
// but boost::ptr_map deosn't provide the way to do that;
// *** ready_value is deleted when an exception is thrown. ***
map.insert(ready_key, ready_value);
}
}
// ...
private:
int ready_key;
std::auto_ptr<value> ready_value;
boost::ptr_map<int, value> map;
// ...
};
}
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk