Lunchbox  1.15.0
Multi-threaded C++ toolbox library for all application developers creating high-performance multi-threaded programs.
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:
126  LUNCHBOX_API Referenced();
127 
129  Referenced( const Referenced& )
130  : _refCount( 0 )
131  , _hasBeenDeleted( false )
132 #ifdef LUNCHBOX_REFERENCED_DEBUG
133  , _holders()
134 #endif
135  {}
136 
138  LUNCHBOX_API virtual ~Referenced();
139 
141  // cppcheck-suppress operatorEqVarError
142  Referenced& operator = ( const Referenced& /*rhs*/ ) { return *this; }
143 
144  LUNCHBOX_API virtual void notifyFree();
145 
146 private:
147  mutable a_int32_t _refCount;
148  bool _hasBeenDeleted;
149 
150 #ifdef LUNCHBOX_REFERENCED_DEBUG
151  typedef PtrHash< const void*, std::string > HolderHash;
152  mutable Lockable< HolderHash, SpinLock > _holders;
153 #endif
154 };
155 }
156 
157 namespace boost
158 {
160 inline void intrusive_ptr_add_ref( lunchbox::Referenced* referenced )
161 {
162  referenced->ref();
163 }
164 
166 inline void intrusive_ptr_release( lunchbox::Referenced* referenced )
167 {
168  referenced->unref();
169 }
170 }
171 
172 #endif //LUNCHBOX_REFERENCED_H
std::ostream & enableFlush(std::ostream &os)
Re-enable flushing of the Log stream.
Defines export visibility macros for library Lunchbox.
bool unref(const void *holder=0) const
Decrease the reference count.
Definition: referenced.h:78
A hash for pointer keys.
Definition: hash.h:27
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
std::ostream & disableHeader(std::ostream &os)
Disable printing of the Log header for subsequent lines.
void ref(const void *holder=0) const
Increase the reference count.
Definition: referenced.h:49
std::string backtrace(const size_t skipFrames)
Get the current call stack.
Base class for referenced objects.
Definition: referenced.h:45
Abstraction layer and common utilities for multi-threaded programming.
Definition: algorithm.h:32
Referenced & operator=(const Referenced &)
Assign another object to this object.
Definition: referenced.h:142
virtual ~Referenced()
Destruct a reference-counted object.
A scoped mutex.
Definition: scopedMutex.h:59
static Log & instance()
The per-thread logger.
Referenced()
Construct a new reference-counted object.
int64_t getTime64() const
Referenced(const Referenced &)
Construct a new copy of a reference-counted object.
Definition: referenced.h:129
int32_t getRefCount() const
Definition: referenced.h:103
std::ostream & disableFlush(std::ostream &os)
Disable flushing of the Log stream.