Horde3D

Next-Generation Graphics Engine
It is currently 08.11.2024, 23:33

All times are UTC + 1 hour




Post new topic Reply to topic  [ 1 post ] 
Author Message
 Post subject: loose_ptr<T> code
PostPosted: 08.11.2011, 01:37 
Offline

Joined: 19.11.2007, 19:35
Posts: 218
In my opinion weak_ptr is one of the best parts about shared_ptr.

I didn't want to start adding shared_ptr's in but didn't want to have some insane management going on either so I whipped together this invasive guy so I could get loose_ptr<T> from anyone who inherits from enable_loose_ptr.

Then my manager just had to to periodically prune the ones that had gone bad while it was checking to see if it still cared about the good ones.

So I thought I'd share. If you read up on weak_ptr and enabled_shared_from_this<T> you should be able to get how it works pretty easily (unlike weak_ptr this will work with variables on the stack too).

Code:
#pragma once
// Copyright (C) 2011 - Jonathan Sandusky
// MIT License - read it here http://www.opensource.org/licenses/mit-license.php

//
// an invasive pointer that gets reset when the target object is destroyed
// (polymorphism is not supported here)
//
template<class TYPE> class loose_ptr {
    loose_ptr<TYPE>& operator=(int);  // prevent "obj=0;" because it doesn't work right
private:
    TYPE* ptr_;
    loose_ptr* next_;
public:
    // default constructor
    loose_ptr() : ptr_(0), next_(0) {}
    // construct from dumb pointer
    loose_ptr(TYPE* p) : ptr_(0), next_(0) {set(p);}
    // construct from derived class dumb pointer
    template<class T> loose_ptr(T* p) : ptr_(0), next_(0) {set(p);}
    // construct from smart_ptr, shared_ptr, etc.
    template<class T> loose_ptr(const T& t) : ptr_(0), next_(0) {set(t.get());}
    // copy constructor (specialization of above)
    loose_ptr(const loose_ptr& rhs) : ptr_(0), next_(0) {set(rhs.ptr_);}
    // destructor
    ~loose_ptr() {set(0);}

    TYPE* ptr() const {return ptr_;}
    TYPE* get() const {return ptr_;}
    TYPE* operator->() const {assert(ptr_); return ptr_;}
    TYPE& operator*() const {assert(ptr_); return *ptr_;}

    bool operator==(TYPE* p) const {return p == ptr_;}
    bool operator!=(TYPE* p) const {return p != ptr_;}

    bool expired() const {return !ptr_;}

    class incomplete_class;
    operator const incomplete_class*() const {return (const incomplete_class*)ptr_;}

    // assign from dumb pointer
    loose_ptr& operator=(TYPE* p) {set(p); return *this;}
    // assign from smart_ptr, shared_ptr, etc.
    template<class T> loose_ptr& operator=(const T& t) {set(t.get()); return *this;}
    // assignment operator (specialization of above)
    loose_ptr& operator=(const loose_ptr& rhs) {set(rhs.ptr_); return *this;}

    void reset(TYPE* aPtr = 0) {set(aPtr);}
    void set(TYPE* aPtr)
    {
        if (aPtr != ptr_) {
            const enable_loose_ptr<TYPE>* ptr = ptr_;
            if (ptr != 0) {
                if (ptr->loose_ptr_head_ == this) {
                    ptr->loose_ptr_head_ = next_;
                } else {
                    loose_ptr* prev = 0;
                    for (loose_ptr* p = ptr->loose_ptr_head_; p && p != this; prev = p, p = p->next_);
                    assert(prev && prev->next_ == this);
                    if (prev && prev->next_ == this)
                        prev->next_ = next_;
                }
                next_ = 0;
            }
            ptr = ptr_ = aPtr;
            if (ptr_) {
                next_ = ptr->loose_ptr_head_;
                ptr->loose_ptr_head_ = this;
            }
        }
    }
};


//
// required base class for objects that can have loose pointers to them
//
template<class TYPE> class enable_loose_ptr {
public:
    // default constructor
    enable_loose_ptr() : loose_ptr_head_(0)
    {
    }
    // copy constructor
    enable_loose_ptr(const enable_loose_ptr&) : loose_ptr_head_(0)
    {
    }
    // destructor
    ~enable_loose_ptr()
    {
        while (loose_ptr_head_)
            loose_ptr_head_->set(0);
    }
    // assignment operator
    enable_loose_ptr& operator=(const enable_loose_ptr&)
    {
    }
private:
    friend class loose_ptr<TYPE>;
    mutable loose_ptr<TYPE>* loose_ptr_head_;
};


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 1 post ] 

All times are UTC + 1 hour


Who is online

Users browsing this forum: No registered users and 78 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
cron
Powered by phpBB® Forum Software © phpBB Group