xref: /haiku/src/kits/support/Referenceable.cpp (revision 822e8462075a234cd2bd4fc82d353a584346692d)
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