Lunchbox  1.17.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; }
105 #ifdef LUNCHBOX_REFERENCED_DEBUG
106  void printHolders(std::ostream& os) const
107  {
108  os << disableFlush << disableHeader << std::endl;
109  {
110  ScopedFastRead mutex(_holders);
111  for (HolderHash::const_iterator i = _holders->begin();
112  i != _holders->end(); ++i)
113  {
114  os << "Holder " << i->first << ": " << i->second << std::endl;
115  }
116  }
117  os << enableHeader << enableFlush;
118  }
119 #else
120  void printHolders(std::ostream&) const {}
121 #endif
122 
123 protected:
125  LUNCHBOX_API Referenced();
126 
128  Referenced(const Referenced&)
129  : _refCount(0)
130  , _hasBeenDeleted(false)
131 #ifdef LUNCHBOX_REFERENCED_DEBUG
132  , _holders()
133 #endif
134  {
135  }
136 
138  LUNCHBOX_API virtual ~Referenced();
139 
141  // cppcheck-suppress operatorEqVarError
142  Referenced& operator=(const Referenced& /*rhs*/) { return *this; }
143  LUNCHBOX_API virtual void notifyFree();
144 
145 private:
146  mutable a_int32_t _refCount;
147  bool _hasBeenDeleted;
148 
149 #ifdef LUNCHBOX_REFERENCED_DEBUG
150  typedef PtrHash<const void*, std::string> HolderHash;
151  mutable Lockable<HolderHash, SpinLock> _holders;
152 #endif
153 };
154 }
155 
156 namespace boost
157 {
159 inline void intrusive_ptr_add_ref(lunchbox::Referenced* referenced)
160 {
161  referenced->ref();
162 }
163 
165 inline void intrusive_ptr_release(lunchbox::Referenced* referenced)
166 {
167  referenced->unref();
168 }
169 }
170 
171 #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:29
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:35
A scoped mutex.
Definition: scopedMutex.h:82
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:29
Referenced & operator=(const Referenced &)
Assign another object to this object.
Definition: referenced.h:142
virtual ~Referenced()
Destruct a reference-counted object.
static Log & instance()
The per-thread logger.
Referenced()
Construct a new reference-counted object.
A scoped shared mutex.
Definition: scopedMutex.h:35
int64_t getTime64() const
Referenced(const Referenced &)
Construct a new copy of a reference-counted object.
Definition: referenced.h:128
int32_t getRefCount() const
Definition: referenced.h:103
std::ostream & disableFlush(std::ostream &os)
Disable flushing of the Log stream.