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