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