1 /************************************************************************ 2 * 3 * Copyright 2011 Jakob Leben (jakob.leben@gmail.com) 4 * 5 * This file is part of SuperCollider Qt GUI. 6 * 7 * This program is free software: you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation, either version 2 of the License, or 10 * (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program. If not, see <http://www.gnu.org/licenses/>. 19 * 20 ************************************************************************/ 21 22 #pragma once 23 24 #include "Common.h" 25 26 #include <QApplication> 27 #include <QAtomicPointer> 28 #include <QAtomicInt> 29 #include <QMutex> 30 31 namespace QtCollider { 32 33 template <typename T> class SafePtr { 34 public: SafePtr()35 SafePtr(): d(0) {} 36 SafePtr(const SafePtr & other)37 SafePtr(const SafePtr& other): d(other.d) { ref(); } 38 SafePtr(T * ptr)39 SafePtr(T* ptr): d(new Data(ptr)) {} 40 operator =(const SafePtr & other)41 SafePtr& operator=(const SafePtr& other) { 42 deref(); 43 d = other.d; 44 ref(); 45 return *this; 46 } 47 ~SafePtr()48 ~SafePtr() { deref(); } 49 operator ->() const50 T* operator->() const { return d->ptr.load(); } 51 operator *() const52 T& operator*() const { return *d->ptr.load(); } 53 operator T*() const54 operator T*() const { return (d ? d->ptr.load() : 0); } 55 ptr() const56 T* ptr() const { return (d ? d->ptr.load() : 0); } 57 id() const58 void* id() const { return (void*)d; } // useful for checking internal pointer identity 59 invalidate()60 void invalidate() { 61 qcDebugMsg(2, "SafePtr: invalidating"); 62 if (d) 63 d->ptr = 0; 64 } 65 66 private: 67 struct Data { DataQtCollider::SafePtr::Data68 Data(T* ptr_): ptr(ptr_), refCount(1) {} 69 QAtomicPointer<T> ptr; 70 QAtomicInt refCount; 71 }; 72 ref()73 void ref() { 74 if (d) { 75 d->refCount.ref(); 76 qcDebugMsg(2, QString("SafePtr: +refcount = %1").arg(d->refCount.load())); 77 } 78 } deref()79 void deref() { 80 if (d) { 81 bool ref = d->refCount.deref(); 82 qcDebugMsg(2, QString("SafePtr: -refcount = %1").arg(d->refCount.load())); 83 if (!ref) { 84 qcDebugMsg(2, "SafePtr: unreferenced!"); 85 delete d; 86 } 87 } 88 } 89 90 Data* d; 91 }; 92 93 } // namespace QtCollider 94