[Boost-users] How to make multi_index_container work with std::unique_ptr?

77 views
Skip to first unread message

Jayden Shui

unread,
Dec 20, 2011, 1:31:18 PM12/20/11
to boost...@lists.boost.org
Hi All,

If the elements of a multi_index_container are std::unique_ptr, it doesn't seem to work because the assignment operator of std::unique_ptr is private. Any way to let it work? If I change unique_ptr to shared_ptr, it works. But I need a good performance. Or is there anyway to work around to get pointer container performance with multi index power?

Thanks a lot!

Jayden

Igor R

unread,
Dec 20, 2011, 2:14:07 PM12/20/11
to boost...@lists.boost.org


Why do you think it would affect your program performance? Have you
run profiler, or it's just a guess?
I use MIC with shared_ptr a lot and it never was a bottleneck.
_______________________________________________
Boost-users mailing list
Boost...@lists.boost.org
http://lists.boost.org/mailman/listinfo.cgi/boost-users

Jayden Shui

unread,
Dec 20, 2011, 2:54:26 PM12/20/11
to boost...@lists.boost.org
It is just my guess. In fact I need MIC with shared_ptr to a scoped_ptr. The shared_ptr is used to count number of uses, while the scoped_ptr used to handle polymorphic objects. I feel a little nervous with that.

Andrew Holden

unread,
Dec 20, 2011, 3:02:56 PM12/20/11
to boost...@lists.boost.org
On Tuesday, December 20, 2011 2:54 PM, Jayden Shui wrote:
>
> It is just my guess. In fact I need MIC with shared_ptr to a
> scoped_ptr. The shared_ptr is used to count number of uses,
> while the scoped_ptr used to handle polymorphic objects. I
> feel a little nervous with that.

There should be no need for both pointer types. Shared_ptr handles
polymorphic objects just fine.

A MIC holding shared_ptrs to your base class should do what you need,
and the overhead associated with the shared_ptr should be negligible.

Jayden Shui

unread,
Dec 20, 2011, 3:53:58 PM12/20/11
to boost...@lists.boost.org
My case is like that: I have a number of polymorphic objects which can be used or referenced by other objects. I put them (the polymorphic objects) in MIC. And if one changes its type (not only its value), its users know it automatically by shared_ptr. I think I need MIC with shared_ptr pointing to scoped_ptr. Am I right? Or is there other way to easy handle it? Thanks a lot.

Igor R

unread,
Dec 20, 2011, 5:23:54 PM12/20/11
to boost...@lists.boost.org
Please don't top-post.

> My case is like that: I have a number of polymorphic objects which can be
> used or referenced by other objects. I put them (the polymorphic objects) in
> MIC. And if one changes its type (not only its value), its users know it
> automatically by shared_ptr. I think I need MIC with shared_ptr pointing to
> scoped_ptr. Am I right? Or is there other way to easy handle it?

How can an object change its type?! In c++ type is a compile-type attribute.
Perhaps you mean that you erase an object from the container and add
another one, or replace some object. In any case, shared_ptr would be
fine.

Jayden Shui

unread,
Dec 20, 2011, 5:38:53 PM12/20/11
to boost...@lists.boost.org
What I mean is dynamic changing. For example

class B {public: virtual ~B()}  // Base class.
class D1 : public B {}            // D1 derived from B
class D2 : public B {}            // D1 derived from B

scoped_ptr<B> p = new D1;   // pointing to D1
p.reset(new D2);    // change pointing to D2

If they are shared between owners and users, I need type

       shared_ptr<scoped_ptr<B>> 

But this type make my code hard to develop and also read.

Any good way? Thanks

Igor R

unread,
Dec 20, 2011, 6:01:36 PM12/20/11
to boost...@lists.boost.org
> What I mean is dynamic changing. For example
>
> class B {public: virtual ~B()}  // Base class.
> class D1 : public B {}            // D1 derived from B
> class D2 : public B {}            // D1 derived from B
>
> scoped_ptr<B> p = new D1;   // pointing to D1
> p.reset(new D2);    // change pointing to D2
>
> If they are shared between owners and users, I need type
>
>        shared_ptr<scoped_ptr<B>>
>
> But this type make my code hard to develop and also read.

And what's wrong with just shared_ptr<B>? Why do you need the
additional level of indirection?

Jayden Shui

unread,
Dec 20, 2011, 6:41:06 PM12/20/11
to boost...@lists.boost.org
On Tue, Dec 20, 2011 at 6:01 PM, Igor R <boost...@gmail.com> wrote:
> What I mean is dynamic changing. For example
>
> class B {public: virtual ~B()}  // Base class.
> class D1 : public B {}            // D1 derived from B
> class D2 : public B {}            // D1 derived from B
>
> scoped_ptr<B> p = new D1;   // pointing to D1
> p.reset(new D2);    // change pointing to D2
>
> If they are shared between owners and users, I need type
>
>        shared_ptr<scoped_ptr<B>>
>
> But this type make my code hard to develop and also read.

And what's wrong with just shared_ptr<B>? Why do you need the
additional level of indirection?

For example

int main()
{
    shared_ptr<B> p(new D1);
    shared_ptr<B> user1 = p;  // User1 uses p
    p.reset(new D2); // p changes pointed type to D2, user1 still points to D1
    return 0;
}
 

or 

int main()
{
    shared_ptr<B> p(new D1);
    shared_ptr<B>* user2 = &p;  // User2 uses p, but the p.use_count() is still 1.
    p.reset(new D2); // p changes pointed  type to D2, *user2 points to D1
    return 0;
}

Thanks.

Igor R

unread,
Dec 21, 2011, 4:54:20 AM12/21/11
to boost...@lists.boost.org
>> And what's wrong with just shared_ptr<B>? Why do you need the
>> additional level of indirection?
>>
> For example
>
> int main()
> {
>     shared_ptr<B> p(new D1);
>     shared_ptr<B> user1 = p;  // User1 uses p
>     p.reset(new D2); // p changes pointed type to D2, user1 still points to
> D1
>     return 0;
> }
>
>
> or
>
> int main()
> {
>     shared_ptr<B> p(new D1);
>     shared_ptr<B>* user2 = &p;  // User2 uses p, but the p.use_count() is
> still 1.
>     p.reset(new D2); // p changes pointed  type to D2, *user2 points to D1
>     return 0;
> }


Ok, so you actually want the following:
1) The container itself shouldn't have "strong" references to your objects
2) An object can be recreated/replaced when it doesn't have any strong
references.
Am I right?

If so, store weak_ptr<Base> in your container:

// pseudo-code
int main()
{
multi_index_container<
weak_ptr<B>,
// some indices
> container;
shared_ptr<B> p(new D1);
container.insert(p);

// at some futher stage:
auto iterator = container.find(someKey);
auto p = iterator->lock();
// if the weak_ptr expired, i.e. no other clients use object, you
may re-create it
if (!p)
recreateIt();
}

Note, however, that there's one pitfall here: if weak_ptr expiration
affects the keys, you'll have to "refresh" MIC indices somehow.

Jayden Shui

unread,
Dec 21, 2011, 7:51:01 AM12/21/11
to boost...@lists.boost.org
Hi, Igore,

I'd like to first thank you for keeping helping me one this problem. I'd like to try to make my requirements clear by some pseudo codes.

int main()
{
   multi_index_container<
       shared_ptr<scoped_ptr<B>>,
       ..named_index..
   > container;     // container own the objects.
   
   // Insert object M of type D1 into container
   container.insert(shared_ptr<new scoped_ptr<B>(new D1("M")));
   // more inserts follows.

   // A user uses an object in the container.
   User user;
   user.Use(*container.find("M"));

   // Erase object M may be invalid if A is used. Thus we count its number of uses
   if (container.find("M")->use_count() == 1)
   {
       container.erase("M");
   }

  // Replace object M in the container to N of type D2. user use object N now since it share info with container.
  itorator it = container.find("M");
  shared_ptr<scoped_ptr<B>>& ppb = *it;
  (*ppb).reset(new D2("N"));
  container.replace(it, ppb);  
   
}

I am look for simple ways (not double pointer) to implement those requirements.

Best regards,

Jayden

Reply all
Reply to author
Forward
0 new messages