1 /* 2 * Copyright 2005-2009, Ingo Weinhold, ingo_weinhold@gmx.de. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7 #include <Referenceable.h> 8 9 #include <debugger.h> 10 11 //#define TRACE_REFERENCEABLE 12 #ifdef TRACE_REFERENCEABLE 13 # include <tracing.h> 14 # define TRACE(x, ...) ktrace_printf(x, __VA_ARGS__); 15 #else 16 # define TRACE(x, ...) 17 #endif 18 19 20 BReferenceable::BReferenceable() 21 : 22 fReferenceCount(1) 23 { 24 } 25 26 27 BReferenceable::~BReferenceable() 28 { 29 #ifdef DEBUG 30 bool enterDebugger = false; 31 if (fReferenceCount == 1) { 32 // Simple heuristic to test if this object was allocated 33 // on the stack: check if this is within 1KB in either 34 // direction of the current stack address, and the reference 35 // count is 1. If so, we don't flag a warning since that would 36 // imply the object was allocated/destroyed on the stack 37 // without any references being acquired or released. 38 char test; 39 size_t testOffset = (addr_t)this - (addr_t)&test; 40 if (testOffset > 1024 || -testOffset > 1024) { 41 // might still be a stack object, check the thread's 42 // stack range to be sure. 43 thread_info info; 44 status_t result = get_thread_info(find_thread(NULL), &info); 45 if (result != B_OK || this < info.stack_base 46 || this > info.stack_end) { 47 enterDebugger = true; 48 } 49 } 50 } else if (fReferenceCount != 0) 51 enterDebugger = true; 52 53 if (enterDebugger) 54 debugger("Deleted referenceable object with non-zero ref count."); 55 #endif 56 } 57 58 59 int32 60 BReferenceable::AcquireReference() 61 { 62 int32 previousReferenceCount = atomic_add(&fReferenceCount, 1); 63 if (previousReferenceCount == 0) 64 FirstReferenceAcquired(); 65 66 TRACE("%p: acquire %ld\n", this, fReferenceCount); 67 68 return previousReferenceCount; 69 } 70 71 72 int32 73 BReferenceable::ReleaseReference() 74 { 75 int32 previousReferenceCount = atomic_add(&fReferenceCount, -1); 76 TRACE("%p: release %ld\n", this, fReferenceCount); 77 if (previousReferenceCount == 1) 78 LastReferenceReleased(); 79 return previousReferenceCount; 80 } 81 82 83 void 84 BReferenceable::FirstReferenceAcquired() 85 { 86 } 87 88 89 void 90 BReferenceable::LastReferenceReleased() 91 { 92 delete this; 93 } 94