xref: /haiku/src/kits/shared/WeakReferenceable.cpp (revision eea5774f46bba925156498abf9cb1a1165647bf7)
1 /*
2  * Copyright 2009, Axel Dörfler, axeld@pinc-software.de.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 
7 #include <WeakReferenceable.h>
8 
9 #include <stdio.h>
10 #include <OS.h>
11 
12 
13 namespace BPrivate {
14 
15 
16 WeakPointer::WeakPointer(BWeakReferenceable* object)
17 	:
18 	fUseCount(1),
19 	fObject(object)
20 {
21 }
22 
23 
24 WeakPointer::~WeakPointer()
25 {
26 }
27 
28 
29 BWeakReferenceable*
30 WeakPointer::Get()
31 {
32 	int32 count;
33 	do {
34 		count = atomic_get(&fUseCount);
35 		if (count == 0)
36 			return NULL;
37 		if (count < 0)
38 			debugger("reference (use) count is negative");
39 	} while (atomic_test_and_set(&fUseCount, count + 1, count) != count);
40 
41 	return fObject;
42 }
43 
44 
45 bool
46 WeakPointer::Put()
47 {
48 	const int32 count = atomic_add(&fUseCount, -1);
49 	if (count == 1) {
50 		delete fObject;
51 		return true;
52 	}
53 	if (count <= 0)
54 		debugger("reference (use) count is negative");
55 
56 	return false;
57 }
58 
59 
60 int32
61 WeakPointer::UseCount() const
62 {
63 	return fUseCount;
64 }
65 
66 
67 void
68 WeakPointer::GetUnchecked()
69 {
70 	atomic_add(&fUseCount, 1);
71 }
72 
73 
74 //	#pragma -
75 
76 
77 BWeakReferenceable::BWeakReferenceable()
78 	:
79 	fPointer(new(std::nothrow) WeakPointer(this))
80 {
81 }
82 
83 
84 BWeakReferenceable::~BWeakReferenceable()
85 {
86 	if (fPointer->UseCount() == 1)
87 		atomic_test_and_set(&fPointer->fUseCount, 0, 1);
88 
89 	if (fPointer->UseCount() != 0) {
90 		char message[256];
91 		snprintf(message, sizeof(message), "deleting referenceable object %p with "
92 			"reference count (%" B_PRId32 ")", this, fPointer->UseCount());
93 		debugger(message);
94 	}
95 
96 	fPointer->ReleaseReference();
97 }
98 
99 
100 status_t
101 BWeakReferenceable::InitCheck()
102 {
103 	if (fPointer == NULL)
104 		return B_NO_MEMORY;
105 	return B_OK;
106 }
107 
108 
109 WeakPointer*
110 BWeakReferenceable::GetWeakPointer()
111 {
112 	fPointer->AcquireReference();
113 	return fPointer;
114 }
115 
116 
117 }	// namespace BPrivate
118