Lunchbox  1.9.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
referenced.h
1 
2 /* Copyright (c) 2005-2014, Stefan Eilemann <eile@equalizergraphics.com>
3  *
4  * This library is free software; you can redistribute it and/or modify it under
5  * the terms of the GNU Lesser General Public License version 2.1 as published
6  * by the Free Software Foundation.
7  *
8  * This library is distributed in the hope that it will be useful, but WITHOUT
9  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
10  * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
11  * details.
12  *
13  * You should have received a copy of the GNU Lesser General Public License
14  * along with this library; if not, write to the Free Software Foundation, Inc.,
15  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
16  */
17 
18 #ifndef LUNCHBOX_REFERENCED_H
19 #define LUNCHBOX_REFERENCED_H
20 
21 #include <lunchbox/api.h> // for LUNCHBOX_API
22 #include <lunchbox/atomic.h> // member
23 #include <lunchbox/debug.h> // for LBERROR
24 
25 //#define LUNCHBOX_REFERENCED_DEBUG
26 #ifdef LUNCHBOX_REFERENCED_DEBUG
27 # include <lunchbox/clock.h>
28 # include <lunchbox/hash.h>
29 # include <lunchbox/lockable.h>
30 # include <lunchbox/scopedMutex.h>
31 # include <lunchbox/spinLock.h>
32 #endif
33 
34 namespace lunchbox
35 {
46 {
47 public:
49  void ref( const void* holder LB_UNUSED = 0 ) const
50  {
51 #ifndef NDEBUG
52  LBASSERT( !_hasBeenDeleted );
53 #endif
54  ++_refCount;
55 
56 #ifdef LUNCHBOX_REFERENCED_DEBUG
57  if( holder )
58  {
59  std::stringstream cs;
60  cs << "Thread " << Log::instance().getThreadName() << " @ "
61  << Log::instance().getClock().getTime64() << " rc " << _refCount
62  << " from " << backtrace;
63  ScopedFastWrite mutex( _holders );
64  HolderHash::iterator i = _holders->find( holder );
65  LBASSERTINFO( i == _holders->end(), i->second );
66  _holders.data[ holder ] = cs.str();
67  }
68 #endif
69  }
70 
78  bool unref( const void* holder LB_UNUSED = 0 ) const
79  {
80 #ifndef NDEBUG
81  LBASSERT( !_hasBeenDeleted );
82 #endif
83  LBASSERT( _refCount > 0 );
84  const bool last = (--_refCount==0);
85 
86 #ifdef LUNCHBOX_REFERENCED_DEBUG
87  if( holder )
88  {
89  ScopedFastWrite mutex( _holders );
90  HolderHash::iterator i = _holders->find( holder );
91  LBASSERT( i != _holders->end( ));
92  _holders->erase( i );
93  LBASSERT( _holders->find( holder ) == _holders->end( ));
94  }
95 #endif
96 
97  if( last )
98  const_cast< Referenced* >( this )->notifyFree();
99  return last;
100  }
101 
103  int32_t getRefCount() const { return _refCount; }
104 
106 #ifdef LUNCHBOX_REFERENCED_DEBUG
107  void printHolders( std::ostream& os ) const
108  {
109  os << disableFlush << disableHeader << std::endl;
110  {
111  ScopedFastRead mutex( _holders );
112  for( HolderHash::const_iterator i = _holders->begin();
113  i != _holders->end(); ++i )
114  {
115  os << "Holder " << i->first << ": " << i->second << std::endl;
116  }
117  }
118  os << enableHeader << enableFlush;
119  }
120 #else
121  void printHolders( std::ostream& ) const {}
122 #endif
123 
124 protected:
127  : _refCount( 0 )
128  , _hasBeenDeleted( false )
129  {}
130 
133  : _refCount( 0 )
134  , _hasBeenDeleted( false )
135 #ifdef LUNCHBOX_REFERENCED_DEBUG
136  , _holders()
137 #endif
138  {}
139 
141  virtual ~Referenced()
142  {
143  LBASSERT( !_hasBeenDeleted );
144  _hasBeenDeleted = true;
145  LBASSERTINFO( _refCount == 0,
146  "Deleting object with ref count " << _refCount );
147  }
148 
150  // cppcheck-suppress operatorEqVarError
151  Referenced& operator = ( const Referenced& /*rhs*/ ) { return *this; }
152 
153  LUNCHBOX_API virtual void notifyFree();
154 
155 private:
156  mutable a_int32_t _refCount;
157  bool _hasBeenDeleted;
158 
159 #ifdef LUNCHBOX_REFERENCED_DEBUG
160  typedef PtrHash< const void*, std::string > HolderHash;
161  mutable Lockable< HolderHash, SpinLock > _holders;
162 #endif
163 };
164 }
165 
166 namespace boost
167 {
169 inline void intrusive_ptr_add_ref( lunchbox::Referenced* referenced )
170 {
171  referenced->ref();
172 }
173 
175 inline void intrusive_ptr_release( lunchbox::Referenced* referenced )
176 {
177  referenced->unref();
178 }
179 }
180 
181 #endif //LUNCHBOX_REFERENCED_H
Defines export visibility macros for Lunchbox.
LUNCHBOX_API std::string backtrace(const size_t skipFrames)
Get the current call stack.
A hash for pointer keys.
Definition: hash.h:27
LUNCHBOX_API int64_t getTime64() const
LUNCHBOX_API std::ostream & enableFlush(std::ostream &os)
Re-enable flushing of the Log stream.
LUNCHBOX_API std::ostream & disableHeader(std::ostream &os)
Disable printing of the Log header for subsequent lines.
LUNCHBOX_API std::ostream & enableHeader(std::ostream &os)
Re-enable printing of the Log header.
A convenience structure to hold data together with a lock for access.
Definition: lockable.h:32
void ref(const void *holder LB_UNUSED=0) const
Increase the reference count.
Definition: referenced.h:49
bool unref(const void *holder LB_UNUSED=0) const
Decrease the reference count.
Definition: referenced.h:78
Base class for referenced objects.
Definition: referenced.h:45
static LUNCHBOX_API Log & instance()
The per-thread logger.
Referenced & operator=(const Referenced &)
Assign another object to this object.
Definition: referenced.h:151
LUNCHBOX_API std::ostream & disableFlush(std::ostream &os)
Disable flushing of the Log stream.
virtual ~Referenced()
Destruct a reference-counted object.
Definition: referenced.h:141
A scoped mutex.
Definition: scopedMutex.h:59
Referenced()
Construct a new reference-counted object.
Definition: referenced.h:126
Referenced(const Referenced &)
Construct a new copy of a reference-counted object.
Definition: referenced.h:132
int32_t getRefCount() const
Definition: referenced.h:103