I decided that my serial_ptr implemented a variant at the wrong level
of indirection.  So now I'm trying out intrusive_ptr with a variant at the
pointee level.  This is what my code looks like now:


//-----------------------------------------------------------------------
    class TRecord
    {
    public:             // Interface
                        TRecord(void)
                            : ID_(0)                { }
                        TRecord(int ID)
                            : ID_(ID)               { }
        virtual        ~TRecord(void)               { }

        void            swap(TRecord& Record)       { std::swap(ID_,
Record.ID_); }

        int             ID(void) const              { return ID_; }
    private:            // Implementation
        int             ID_;
    };

//-----------------------------------------------------------------------
    template <typename T>
    class TCountedRecord
    {
    public:             // Interface
                        TCountedRecord(void)
                            : Count_(0)             { }
                        TCountedRecord(int ID)
                            : Count_(0)             { new (Value_)
TRecord(ID); }
                       ~TCountedRecord(void);

        bool            IsRecord(void) const;       // No-throw
        unsigned        Count(void) const;          // No-throw
        int             ID(void) const;
                        operator T const&(void) const;
                        operator T&(void);

        T*              AddRef(void);
        void            Release(void);              // No-throw
    private:            // Implementation
        typedef boost::detail::lightweight_mutex mutex_type;

        mutable
        mutex_type      Mutex_;
        unsigned        Count_;
        char            Value_[sizeof(T)];
    };

//-----------------------------------------------------------------------
    template <typename T>
    void intrusive_ptr_add_ref(TCountedRecord<T>* p)
    {
        p->AddRef();
    }

//-----------------------------------------------------------------------
    template <typename T>
    void intrusive_ptr_release(TCountedRecord<T>* p)
    {
        p->Release();
    }

This code is still being designed, so I haven't tried it.  It might not
work as expected.  The idea is that my database records will
derive from TRecord, and my pointers will be intrusive_ptrs to
TCountedRecord<T>.

In case it's not obvious, TCountedRecord is a variant of TRecord
and T.  The idea is when I just get record IDs, a TCountedRecord
stores a TRecord with the ID in it.  When I get a full record, I use
placement new to install it over the TRecord.

I have several issues, however.  First, the variant doesn't support
inheritance hierarchies very well.  If I have U derived from T, my
problem is that TCountedRecord<U> isn't derived from
TCountedRecord<T>, and so I can't use dynamic_pointer_cast<>
to cast between my intrusive_ptrs.  That's not a problem with
dynamic_pointer_cast<>, of course.  The problem is that I can't
store base pointers at all, since the pointers aren't related.

Second, I don't like having to use placement new to construct
my records, but I can't use inheritance, because I don't always
have all the data to construct a full record immediately.  So the
variant essentially implements "partial construction".  If I could
just have T, rather than variant<TRecord, T>, and only construct
the TRecord sub-object, that would be ideal, but obviously, not
C++.

Another solution is to use a pointer in TCountedRecord instead
of a value.  However, that introduces an unnecessary level of
indirection (though I might be forced to resort to that).  Another
thing that's not obvious from the interface is that I'm using the
count as the variant tag.  A 0 means that a TRecord is present,
and a non-0 means an actual record is present.

Any suggestions on how to deal with polymorphism, or
restructure the design differently are appreciated.

Also, I think Boost could use a value-based variant type.

Dave




_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Reply via email to