File indexing completed on 2024-12-22 04:17:22

0001 /* This file is derived from the KDE libraries
0002    Copyright (c) 1999 Waldo Bastian <bastian@kde.org>
0003    Copyright (c) 2004 The University of Toronto <netterfield@astro.utoronto.ca>
0004 
0005    This library is free software; you can redistribute it and/or
0006    modify it under the terms of the GNU Library General Public
0007    License version 2 as published by the Free Software Foundation.
0008 
0009    This library is distributed in the hope that it will be useful,
0010    but WITHOUT ANY WARRANTY; without even the implied warranty of
0011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0012    Library General Public License for more details.
0013 */
0014 #ifndef SharedPTR_H
0015 #define SharedPTR_H
0016 
0017 #include <QSemaphore>
0018 #include <QDebug>
0019 
0020 //#define KST_DEBUG_SHARED
0021 #ifdef KST_DEBUG_SHARED
0022 #define KST_DBG if (true)
0023 #else
0024 #define KST_DBG if (false)
0025 #endif
0026 
0027 // NOTE: In order to preserve binary compatibility with plugins, you must
0028 //       not add, remove, or change member variables or virtual functions.
0029 //       You must also not remove or change non-virtual functions.
0030 
0031 // See KSharedPtr in KDE libraries for more information
0032 
0033 namespace Kst {
0034 
0035 #define SEMAPHORE_COUNT 999999
0036 
0037 class Shared {
0038 public:
0039    /**
0040     * Standard constructor.  This will initialize the reference count
0041     * on this object to 0.
0042     */
0043    Shared() : sem(SEMAPHORE_COUNT) { }
0044 
0045    /**
0046     * Copy constructor.  This will @em not actually copy the objects
0047     * but it will initialize the reference count on this object to 0.
0048     */
0049    Shared( const Shared & ) : sem(SEMAPHORE_COUNT) { }
0050 
0051    /**
0052     * Overloaded assignment operator.
0053     */
0054    Shared &operator=(const Shared & ) { return *this; }
0055 
0056    /**
0057     * Increases the reference count by one.
0058     */
0059    void _KShared_ref() const {
0060      sem.acquire(1);
0061      KST_DBG qDebug() << "KShared_ref: " << (void*)this << " -> " << _KShared_count() << endl;
0062    }
0063 
0064    /**
0065     * Releases a reference (decreases the reference count by one).  If
0066     * the count goes to 0, this object will delete itself.
0067     */
0068    void _KShared_unref() const {
0069      sem.release(1);
0070      KST_DBG qDebug() << "KShared_unref: " << (void*)this << " -> " << _KShared_count() << endl;
0071      if (SEMAPHORE_COUNT == sem.available()) delete this;
0072    }
0073 
0074    /**
0075     * Return the current number of references held.
0076     *
0077     * @return Number of references
0078     */
0079    int _KShared_count() const { return SEMAPHORE_COUNT - sem.available(); }
0080 
0081 protected:
0082    virtual ~Shared() { }
0083 
0084 private:
0085    mutable QSemaphore sem;
0086 };
0087 
0088 
0089 template< class T >
0090 struct SharedPtr
0091 {
0092 public:
0093   /**
0094    * Creates a null pointer.
0095    */
0096   SharedPtr() : ptr(0) { isPtrValid(); }
0097 
0098   /**
0099    * Creates a new pointer.
0100    * @param t the pointer
0101    */
0102   SharedPtr( T* t ) : ptr(t) { if (isPtrValid()) ptr->_KShared_ref(); }
0103 
0104   /**
0105    * Copies a pointer.
0106    * @param p the pointer to copy
0107    */
0108   SharedPtr( const SharedPtr& p )
0109     : ptr(p.ptr) { if (isPtrValid()) ptr->_KShared_ref(); }
0110 
0111   template<class Y> SharedPtr(SharedPtr<Y>& p)
0112     : ptr(p.data()) { if (isPtrValid()) ptr->_KShared_ref(); }
0113 
0114   /**
0115    * Unreferences the object that this pointer points to. If it was
0116    * the last reference, the object will be deleted.
0117    */
0118   ~SharedPtr() { if (isPtrValid()) ptr->_KShared_unref(); }
0119 
0120   SharedPtr<T>& operator= ( const SharedPtr<T>& p ) {
0121     isPtrValid();
0122     if ( ptr == p.ptr ) return *this;
0123     if (isPtrValid()) ptr->_KShared_unref();
0124     ptr = p.ptr;
0125     if (isPtrValid()) ptr->_KShared_ref();
0126     return *this;
0127   }
0128 
0129   template<class Y>
0130   SharedPtr<T>& operator=(SharedPtr<Y>& p) {
0131     isPtrValid();
0132     if (ptr == p.data()) return *this;
0133     if (isPtrValid()) ptr->_KShared_unref();
0134     ptr = p.data();
0135     if (isPtrValid()) ptr->_KShared_ref();
0136     return *this;
0137   }
0138 
0139   SharedPtr<T>& operator= ( T* p ) {
0140     isPtrValid();
0141     if (ptr == p) return *this;
0142     if (isPtrValid()) ptr->_KShared_unref();
0143     ptr = p;
0144     if (isPtrValid()) ptr->_KShared_ref();
0145     return *this;
0146   }
0147 
0148   bool operator== ( const SharedPtr<T>& p ) const { isPtrValid(); return ( ptr == p.ptr ); }
0149   bool operator!= ( const SharedPtr<T>& p ) const { isPtrValid(); return ( ptr != p.ptr ); }
0150   bool operator== ( const T* p ) const { isPtrValid(); return ( ptr == p ); }
0151   bool operator!= ( const T* p ) const { isPtrValid(); return ( ptr != p ); }
0152   bool operator!() const { isPtrValid(); return ( ptr == 0 ); }
0153   operator T*() const { isPtrValid(); return ptr; }
0154 
0155   /**
0156    * Returns the pointer.
0157    * @return the pointer
0158    */
0159   T* data() { isPtrValid(); return ptr; }
0160 
0161   /**
0162    * Returns the pointer.
0163    * @return the pointer
0164    */
0165   const T* data() const { isPtrValid(); return ptr; }
0166 
0167   const T& operator*() const  { Q_ASSERT(isPtrValid()); return *ptr; }
0168   T& operator*()              { Q_ASSERT(isPtrValid()); return *ptr; }
0169   const T* operator->() const { Q_ASSERT(isPtrValid()); return ptr; }
0170   T* operator->()             { Q_ASSERT(isPtrValid()); return ptr; }
0171 
0172   /**
0173    * Returns the number of references.
0174    * @return the number of references
0175    */
0176   int count() const { Q_ASSERT(isPtrValid()); return ptr->_KShared_count(); } // for debugging purposes
0177 
0178 
0179   bool isPtrValid() const { return ptr != 0; }
0180 
0181 private:
0182   T* ptr;
0183 };
0184 
0185 
0186 template <typename T, typename U>
0187 inline SharedPtr<T> kst_cast(SharedPtr<U> object) {
0188   return qobject_cast<T*>(object.data());
0189 }
0190 
0191 // FIXME: make this safe
0192 template <typename T>
0193 inline SharedPtr<T> kst_cast(QObject *object) {
0194   return qobject_cast<T*>(object);
0195 }
0196 
0197 }
0198 #endif