diff --git a/src/apps/debugger/TeamMemoryBlockManager.cpp b/src/apps/debugger/TeamMemoryBlockManager.cpp index 12ed410aa6..7921636805 100644 --- a/src/apps/debugger/TeamMemoryBlockManager.cpp +++ b/src/apps/debugger/TeamMemoryBlockManager.cpp @@ -44,12 +44,10 @@ struct TeamMemoryBlockManager::MemoryBlockEntry : Key { Key(block->BaseAddress()), block(block) { - block->AcquireReference(); } ~MemoryBlockEntry() { - block->ReleaseReference(); } }; @@ -109,16 +107,11 @@ TeamMemoryBlockManager::Init() if (result != B_OK) return result; - fDeadBlocks = new(std::nothrow) MemoryBlockTable(); + fDeadBlocks = new(std::nothrow) DeadBlockTable(); if (fDeadBlocks == NULL) return B_NO_MEMORY; - ObjectDeleter deadDeleter(fDeadBlocks); - result = fDeadBlocks->Init(); - if (result != B_OK) - return result; activeDeleter.Detach(); - deadDeleter.Detach(); return B_OK; } @@ -131,29 +124,34 @@ TeamMemoryBlockManager::GetMemoryBlock(target_addr_t address) address &= ~B_PAGE_SIZE - 1; MemoryBlockEntry* entry = fActiveBlocks->Lookup(address); - if (entry == NULL) { - TeamMemoryBlock* block = new(std::nothrow) TeamMemoryBlock(address, - this); - if (block == NULL) - return NULL; + if (entry != NULL) { + if (entry->block->AcquireReference() != 0) + return entry->block; - entry = new(std::nothrow) MemoryBlockEntry(block); - if (entry == NULL) { - delete block; - return NULL; - } - - fActiveBlocks->Insert(entry); - } - - int32 refCount = entry->block->AcquireReference(); - if (refCount == 0) { // this block already had its last reference released, - // move it to the dead list and retrieve a new one instead. + // move it to the dead list and create a new one instead. _MarkDeadBlock(address); - return GetMemoryBlock(address); } + TeamMemoryBlockOwner* owner = new(std::nothrow) TeamMemoryBlockOwner(this); + if (owner == NULL) + return NULL; + ObjectDeleter ownerDeleter(owner); + + TeamMemoryBlock* block = new(std::nothrow) TeamMemoryBlock(address, + owner); + if (block == NULL) + return NULL; + ObjectDeleter blockDeleter(block); + + entry = new(std::nothrow) MemoryBlockEntry(block); + if (entry == NULL) + return NULL; + + ownerDeleter.Detach(); + blockDeleter.Detach(); + fActiveBlocks->Insert(entry); + return entry->block; } @@ -179,11 +177,11 @@ TeamMemoryBlockManager::_Cleanup() void TeamMemoryBlockManager::_MarkDeadBlock(target_addr_t address) { - AutoLocker lock(fLock); MemoryBlockEntry* entry = fActiveBlocks->Lookup(address); if (entry != NULL) { fActiveBlocks->Remove(entry); - fDeadBlocks->Insert(entry); + fDeadBlocks->Insert(entry->block); + delete entry; } } @@ -199,10 +197,31 @@ TeamMemoryBlockManager::_RemoveBlock(target_addr_t address) return; } - entry = fDeadBlocks->Lookup(address); - if (entry != NULL) { - fDeadBlocks->Remove(entry); - delete entry; + DeadBlockTable::Iterator iterator = fDeadBlocks->GetIterator(); + while (iterator.HasNext()) { + TeamMemoryBlock* block = iterator.Next(); + if (block->BaseAddress() == address) { + fDeadBlocks->Remove(block); + break; + } } } + +TeamMemoryBlockOwner::TeamMemoryBlockOwner(TeamMemoryBlockManager* manager) + : + fBlockManager(manager) +{ +} + + +TeamMemoryBlockOwner::~TeamMemoryBlockOwner() +{ +} + + +void +TeamMemoryBlockOwner::RemoveBlock(TeamMemoryBlock* block) +{ + fBlockManager->_RemoveBlock(block->BaseAddress()); +} diff --git a/src/apps/debugger/TeamMemoryBlockManager.h b/src/apps/debugger/TeamMemoryBlockManager.h index c9ecb521e4..2405454f68 100644 --- a/src/apps/debugger/TeamMemoryBlockManager.h +++ b/src/apps/debugger/TeamMemoryBlockManager.h @@ -8,10 +8,12 @@ #include #include +#include #include #include "Types.h" + struct MemoryBlockHashDefinition; class TeamMemoryBlock; @@ -31,6 +33,7 @@ private: struct MemoryBlockEntry; struct MemoryBlockHashDefinition; typedef BOpenHashTable MemoryBlockTable; + typedef DoublyLinkedList DeadBlockTable; private: void _Cleanup(); @@ -38,12 +41,26 @@ private: void _RemoveBlock(target_addr_t address); private: - friend class TeamMemoryBlock; + friend class TeamMemoryBlockOwner; private: BLocker fLock; MemoryBlockTable* fActiveBlocks; - MemoryBlockTable* fDeadBlocks; + DeadBlockTable* fDeadBlocks; +}; + + +class TeamMemoryBlockOwner +{ +public: + TeamMemoryBlockOwner( + TeamMemoryBlockManager* manager); + ~TeamMemoryBlockOwner(); + + void RemoveBlock(TeamMemoryBlock* block); + +private: + TeamMemoryBlockManager* fBlockManager; }; diff --git a/src/apps/debugger/model/TeamMemoryBlock.cpp b/src/apps/debugger/model/TeamMemoryBlock.cpp index b20ec90f8c..f5869d91be 100644 --- a/src/apps/debugger/model/TeamMemoryBlock.cpp +++ b/src/apps/debugger/model/TeamMemoryBlock.cpp @@ -16,17 +16,18 @@ TeamMemoryBlock::TeamMemoryBlock(target_addr_t baseAddress, - TeamMemoryBlockManager* manager) + TeamMemoryBlockOwner* owner) : fValid(false), fBaseAddress(baseAddress), - fBlockManager(manager) + fBlockOwner(owner) { } TeamMemoryBlock::~TeamMemoryBlock() { + delete fBlockOwner; } @@ -88,9 +89,9 @@ TeamMemoryBlock::NotifyDataRetrieved() void TeamMemoryBlock::LastReferenceReleased() { - fBlockManager->_RemoveBlock(fBaseAddress); + fBlockOwner->RemoveBlock(this); - BReferenceable::LastReferenceReleased(); + delete this; } diff --git a/src/apps/debugger/model/TeamMemoryBlock.h b/src/apps/debugger/model/TeamMemoryBlock.h index ba82d4a718..d5dabfda80 100644 --- a/src/apps/debugger/model/TeamMemoryBlock.h +++ b/src/apps/debugger/model/TeamMemoryBlock.h @@ -15,16 +15,17 @@ #include "Types.h" -class TeamMemoryBlockManager; +class TeamMemoryBlockOwner; -class TeamMemoryBlock : public BReferenceable { +class TeamMemoryBlock : public BReferenceable, + public DoublyLinkedListLinkImpl { public: class Listener; public: TeamMemoryBlock(target_addr_t baseAddress, - TeamMemoryBlockManager* manager); + TeamMemoryBlockOwner* owner); ~TeamMemoryBlock(); void AddListener(Listener* listener); @@ -52,8 +53,8 @@ private: target_addr_t fBaseAddress; uint8 fData[B_PAGE_SIZE]; ListenerList fListeners; - TeamMemoryBlockManager* - fBlockManager; + TeamMemoryBlockOwner* + fBlockOwner; BLocker fLock; };