xref: /haiku/src/kits/shared/WeakReferenceable.cpp (revision ed24eb5ff12640d052171c6a7feba37fab8a75d1)
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 = -11;
33 
34 	do {
35 		count = atomic_get(&fUseCount);
36 		if (count == 0)
37 			return NULL;
38 	} while (atomic_test_and_set(&fUseCount, count + 1, count) != count);
39 
40 	return fObject;
41 }
42 
43 
44 bool
45 WeakPointer::Put()
46 {
47 	if (atomic_add(&fUseCount, -1) == 1) {
48 		delete fObject;
49 		return true;
50 	}
51 
52 	return false;
53 }
54 
55 
56 int32
57 WeakPointer::UseCount() const
58 {
59 	return fUseCount;
60 }
61 
62 
63 void
64 WeakPointer::GetUnchecked()
65 {
66 	atomic_add(&fUseCount, 1);
67 }
68 
69 
70 //	#pragma -
71 
72 
73 BWeakReferenceable::BWeakReferenceable()
74 	:
75 	fPointer(new(std::nothrow) WeakPointer(this))
76 {
77 }
78 
79 
80 BWeakReferenceable::~BWeakReferenceable()
81 {
82 	if (fPointer->UseCount() == 1)
83 		atomic_test_and_set(&fPointer->fUseCount, 0, 1);
84 
85 	if (fPointer->UseCount() != 0) {
86 		char message[256];
87 		snprintf(message, sizeof(message), "deleting referenceable object %p with "
88 			"reference count (%" B_PRId32 ")", this, fPointer->UseCount());
89 		debugger(message);
90 	}
91 
92 	fPointer->ReleaseReference();
93 }
94 
95 
96 status_t
97 BWeakReferenceable::InitCheck()
98 {
99 	if (fPointer == NULL)
100 		return B_NO_MEMORY;
101 	return B_OK;
102 }
103 
104 
105 WeakPointer*
106 BWeakReferenceable::GetWeakPointer()
107 {
108 	fPointer->AcquireReference();
109 	return fPointer;
110 }
111 
112 
113 }	// namespace BPrivate
114