37
39
NUX_IMPLEMENT_OBJECT_TYPE (Object);
38
40
NUX_IMPLEMENT_GLOBAL_OBJECT (ObjectStats);
40
// int ObjectStats::_total_allocated_size = 0;
41
// int ObjectStats::_number_of_objects = 0;
42
// ObjectStats::AllocationList ObjectStats::_allocation_list;
44
ObjectStats::AllocationList::AllocationList()
49
ObjectStats::AllocationList::~AllocationList()
54
42
void ObjectStats::Constructor()
56
_total_allocated_size = 0;
44
_total_allocated_size= 0;
57
45
_number_of_objects = 0;
60
48
void ObjectStats::Destructor()
50
#if defined(NUX_DEBUG)
62
51
if (_number_of_objects)
64
LOG_DEBUG(logger) << _number_of_objects << " undeleted objects.";
53
std::cerr << "[ObjectStats::Destructor] "
54
<< _number_of_objects << " undeleted objects.\n\t"
55
<< _allocation_list.size() << " items in allocation list.\n";
67
#if defined(NUX_DEBUG)
68
AllocationList::iterator it;
69
for (it = _allocation_list.begin(); it != _allocation_list.end(); it++)
59
for (auto ptr : _allocation_list)
71
Object* obj = NUX_STATIC_CAST (Object*, (*it));
72
LOG_DEBUG(logger) << "Undeleted object: Type "
73
<< obj->Type().m_Name << ", "
74
<< obj->_allocation_file_name.GetTCharPtr()
75
<< "line " << obj->_allocation_line_number;
61
Object* obj = static_cast<Object*>(ptr);
62
std::cerr << "\t" << ++index << " Undeleted object: Type "
63
<< obj->Type().name << ", "
64
<< obj->GetAllocationLoation() << "\n";
200
189
const void *ptr = dynamic_cast<const void *> (this);
202
191
// Search for ptr in allocation_list
192
#if defined(NUX_OS_WINDOWS) && !defined(NUX_VISUAL_STUDIO_2010)
193
std::list<void*>::iterator i = std::find(GObjectStats._allocation_list.begin(),
194
GObjectStats._allocation_list.end(), ptr);
203
196
auto i = std::find(GObjectStats._allocation_list.begin(),
204
197
GObjectStats._allocation_list.end(), ptr);
205
199
return i != GObjectStats._allocation_list.end();
213
207
//////////////////////////////////////////////////////////////////////
215
209
Object::Object(bool OwnTheReference, NUX_FILE_LINE_DECL)
210
: allocation_file_name_(__Nux_FileName__)
211
, allocation_line_number_(__Nux_LineNumber__)
212
, reference_count_(new NThreadSafeCounter())
213
, objectptr_count_(new NThreadSafeCounter())
217
_allocation_file_name = __Nux_FileName__;
218
_allocation_line_number = __Nux_LineNumber__;
220
_reference_count = new NThreadSafeCounter();
221
_weak_reference_count = new NThreadSafeCounter();
222
_objectptr_count = new NThreadSafeCounter();
223
_destroyed = new bool(false);
225
_reference_count->Set (1);
226
_weak_reference_count->Set (1);
228
SetOwnedReference (OwnTheReference);
215
reference_count_->Set(1);
216
SetOwnedReference(OwnTheReference);
231
219
Object::~Object()
235
if (IsHeapAllocated ())
237
// If the object has properly been UnReference, it should have gone through Destroy(). if that is the case then
238
// _reference_count should be NULL or its value (returned by GetValue ()) should be equal to 0;
239
// We can use this to detect when delete is called directly on an object.
240
nuxAssertMsg((_reference_count == 0) || (_reference_count && (_reference_count->GetValue () == 0)),
241
TEXT("[Object::~Object] Invalid object destruction. Make sure to call UnReference or Dispose (if the object has never been referenced) on the object.\nObject allocated at: %s [%d]"),
242
_allocation_file_name.GetTCharPtr (),
243
_allocation_line_number);
245
nuxAssertMsg((_weak_reference_count == 0) || (_weak_reference_count && (_weak_reference_count->GetValue () > 0)),
246
TEXT("[Object::~Object] Invalid value of the weak reference count pointer. Make sure to call UnReference or Dispose (if the object has never been referenced) on the object.\nObject allocated at: %s [%d]"),
247
_allocation_file_name.GetTCharPtr (),
248
_allocation_line_number);
250
if ((_reference_count == 0) && (_weak_reference_count == 0))
256
// There is a smart pointer holding a weak reference to this object. It is the responsibility
257
// of the last smart pointer to delete '_destroyed'.
262
delete _reference_count;
263
delete _weak_reference_count;
264
delete _objectptr_count;
221
if (IsHeapAllocated())
223
// If the object has properly been UnReference, it should have gone
224
// through Destroy(). if that is the case then _reference_count should
225
// be NULL or its value (returned by GetValue ()) should be equal to 0;
226
// We can use this to detect when delete is called directly on an
228
if (reference_count_->GetValue() > 0)
230
LOG_WARN(logger) << "Invalid object destruction, still has "
231
<< reference_count_->GetValue() << " references."
232
<< "\nObject allocated at: " << GetAllocationLoation();
235
delete reference_count_;
236
delete objectptr_count_;
269
239
bool Object::Reference()
271
if (!IsHeapAllocated ())
273
LOG_ERROR(logger) << "Trying to reference an object that was not heap allocated. "
274
<< "\nObject allocated at: " << GetAllocationLoation();
278
if (_reference_count->GetValue() == 0 || *_destroyed)
280
// If this happens, all bets are off, and this may crash.
281
LOG_ERROR(logger) << "Trying to reference an object that has been deleted."
282
<< "\nObject allocated at: " << GetAllocationLoation();
241
if (!IsHeapAllocated())
243
LOG_WARN(logger) << "Trying to reference an object that was not heap allocated."
244
<< "\nObject allocated at: " << GetAllocationLoation();
300
261
if (!IsHeapAllocated())
302
LOG_ERROR(logger) << "Trying to un-reference an object that was not heap allocated. "
303
<< "\nObject allocated at: " << GetAllocationLoation();
263
LOG_WARN(logger) << "Trying to un-reference an object that was not heap allocated."
264
<< "\nObject allocated at: " << GetAllocationLoation();
307
if (_objectptr_count->GetValue() == _reference_count->GetValue())
268
if (objectptr_count_->GetValue() == reference_count_->GetValue())
309
270
// There are ObjectPtr's hosting this object. Release all of them to
310
271
// destroy this object. This prevent from calling UnReference () many
311
272
// times and destroying the object when there are ObjectPtr's hosting
312
273
// it. This method should not be called directly in that case.
313
LOG_ERROR(logger) << "There are ObjectPtr hosting this object. "
314
<< "Release all of them to destroy this object. "
315
<< "\nObject allocated at: " << GetAllocationLoation();
274
LOG_WARN(logger) << "There are ObjectPtr hosting this object. "
275
<< "Release all of them to destroy this object. "
276
<< "\nObject allocated at: " << GetAllocationLoation();
319
_reference_count->Decrement();
320
_weak_reference_count->Decrement();
280
reference_count_->Decrement();
322
if (_reference_count->GetValue() == 0)
282
if (reference_count_->GetValue() == 0)
350
310
bool Object::Dispose()
352
// The intent of the Dispose call is to destroy objects with a float reference (reference count is equal to 1 and
353
// the '_owns_the_reference' flag is set to false). In Nux, only widgets object can have a floating reference.
354
// And widgets are only visible if added to the widget tree.
355
// When an object with a floating reference is added to the widget tree, it becomes "owned'. It looses it
356
// floating reference status but it still has a reference count number of 1.
357
// In practice, since widgets must be added to the widget tree, there should never be a need to call Dispose
312
// The intent of the Dispose call is to destroy objects with a float
313
// reference (reference count is equal to 1 and the '_owns_the_reference'
314
// flag is set to false). In Nux, only widgets object can have a floating
315
// reference. And widgets are only visible if added to the widget tree.
316
// When an object with a floating reference is added to the widget tree,
317
// it becomes "owned'. It looses it floating reference status but it still
318
// has a reference count number of 1. In practice, since widgets must be
319
// added to the widget tree, there should never be a need to call Dispose
358
320
// (except in a few cases).
360
// Dispose() was designed to only destroy objects with floating references, while UnReference() destroys objects
361
// that are "owned" . That is now relaxed. Dispose() calls UnReference().
322
// Dispose() was designed to only destroy objects with floating
323
// references, while UnReference() destroys objects that are "owned".
324
// That is now relaxed. Dispose() calls UnReference().
363
325
return UnReference();
366
328
void Object::Destroy()
368
if (!IsHeapAllocated ())
370
LOG_ERROR(logger) << "Trying to destroy an object that was not heap allocated. "
371
<< "\nObject allocated at: " << GetAllocationLoation();
375
nuxAssert (_reference_count->GetValue() == 0);
377
if ((_reference_count->GetValue() == 0) && (_weak_reference_count->GetValue() == 0) && (_objectptr_count->GetValue() == 0))
379
delete _reference_count;
380
delete _weak_reference_count;
381
delete _objectptr_count;
382
_reference_count = 0;
383
_weak_reference_count = 0;
384
_objectptr_count = 0;
388
if ((_weak_reference_count == NULL) && (_objectptr_count->GetValue() == 0))
390
nuxDebugMsg (TEXT ("[Object::Destroy] Error on object allocated at %s [%d]:")
391
, _allocation_file_name.GetTCharPtr ()
392
, _allocation_line_number);
393
nuxAssertMsg (0, TEXT("[Object::Destroy] Invalid pointer for the weak reference count."));
396
if ((_weak_reference_count->GetValue() == 0) && (_objectptr_count->GetValue() == 0))
398
nuxDebugMsg (TEXT ("[Object::Destroy] Error on object allocated at %s [%d]:")
399
, _allocation_file_name.GetTCharPtr ()
400
, _allocation_line_number);
401
nuxAssertMsg (0, TEXT("[Object::Destroy] Invalid value of the weak reference count."));
405
330
static int delete_depth = 0;
332
// Weak smart pointers will clear their pointers when they get this signal.
407
333
object_destroyed.emit(this);
408
std::string obj_type(this->Type().m_Name);
334
const char* obj_type = this->Type().name;
409
335
LOG_TRACE(logger) << "Depth: " << delete_depth << ", about to delete "
410
336
<< obj_type << " allocated at " << GetAllocationLoation();
416
void Object::IncrementWeakCounter()
418
if (!IsHeapAllocated ())
420
LOG_ERROR(logger) << "Trying to increment weak counter on an object that was not heap allocated. "
421
<< "\nObject allocated at: " << GetAllocationLoation();
425
_weak_reference_count->Increment();
428
void Object::DecrementWeakCounter()
430
if (!IsHeapAllocated())
432
LOG_ERROR(logger) << "Trying to decrement weak counter on an object that was not heap allocated. "
433
<< "\nObject allocated at: " << GetAllocationLoation();
437
_weak_reference_count->Decrement();
440
342
int Object::GetReferenceCount() const
442
return _reference_count->GetValue();
445
int Object::GetWeakReferenceCount() const
447
return _weak_reference_count->GetValue();
344
return reference_count_->GetValue();
450
347
std::string Object::GetAllocationLoation() const
452
349
std::ostringstream sout;
453
sout << _allocation_file_name.GetTCharPtr()
454
<< ":" << _allocation_line_number;
350
sout << allocation_file_name_ << ":" << allocation_line_number_;
455
351
return sout.str();