//===========================================================================// // File: m_chain.cc // // Project: MUNGA Brick: Connection Engine // // Contents: Implementation details of chains and their iterators // //---------------------------------------------------------------------------// // Date Who Modification // // -------- --- ---------------------------------------------------------- // // 09/29/94 ECH Initial coding. // // 10/20/94 JMA Fixed style stuff. Merged with CHNITR.HPP, and added // // operator functions to iterator // // 10/23/94 ECH Added greater deletion safety // // 10/28/94 JMA Made compatible with SGI CC // // 11/03/94 ECH Made compatible with BC4.0 // // 12/12/94 ECH Changed release handling // //---------------------------------------------------------------------------// // Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // // PROPRIETARY AND CONFIDENTIAL // //===========================================================================// #include "StuffHeaders.hpp" //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ChainLink ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ MemoryBlock* ChainLink::s_AllocatedMemory = NULL; // //############################################################################# //############################################################################# // void ChainLink::InitializeClass(size_t block_count) { Verify(!s_AllocatedMemory); s_AllocatedMemory = new MemoryBlock( sizeof(ChainLink), block_count, block_count>>2, "Stuff::ChainLink", g_ConnectionEngineHeap ); } // //############################################################################# //############################################################################# // void ChainLink::TerminateClass() { delete s_AllocatedMemory; s_AllocatedMemory = NULL; } // //############################################################################# // ~ChainLink //############################################################################# // ChainLink::~ChainLink() { Check_Object(this); Check_Object(m_chain); // //------------------------ // Unlink the forward link //------------------------ // if (m_nextChainLink) { Check_Object(m_nextChainLink); m_nextChainLink->m_prevChainLink = m_prevChainLink; } else { Verify(m_chain->m_tail == this); m_chain->m_tail = m_prevChainLink; } // //------------------------- // Unlink the backward link //------------------------- // if (m_prevChainLink) { Check_Object(m_prevChainLink); m_prevChainLink->m_nextChainLink = m_nextChainLink; } else { Verify(m_chain->m_head == this); m_chain->m_head = m_nextChainLink; } // //------------------------------------------ // Remove this link from any plug references //------------------------------------------ // m_nextChainLink = NULL; m_prevChainLink = NULL; ReleaseFromPlug(); } // //############################################################################# // ChainLink //############################################################################# // ChainLink::ChainLink( Chain *m_chain, Plug *plug, ChainLink *next_link, ChainLink *prev_link ): m_chain(m_chain), m_plug(plug) { // //------------------------- // ChainLink into existing m_chain //------------------------- // AddToPlug(plug); m_nextChainLink = next_link; m_prevChainLink = prev_link; if (prev_link) { Check_Object(prev_link); prev_link->m_nextChainLink = this; } if (next_link) { Check_Object(next_link); next_link->m_prevChainLink = this; } } // //############################################################################# // ReleaseFromPlug //############################################################################# // void ChainLink::ReleaseFromPlug() { Check_Object(this); // //----------------------------------------------------- // Remove this link from the plugs current set of links //----------------------------------------------------- // Check_Object(m_plug); ChainLink *link = m_plug->m_chainLinkHead; Check_Object(link); if (link == this) { if (m_nextPlugLink != this) m_plug->m_chainLinkHead = m_nextPlugLink; else { m_nextPlugLink = m_plug->m_chainLinkHead = NULL; return; } } while (link->m_nextPlugLink != this) { Check_Object(this); link = link->m_nextPlugLink; } link->m_nextPlugLink = m_nextPlugLink; m_nextPlugLink = NULL; } // //############################################################################# // AddToPlug //############################################################################# // void ChainLink::AddToPlug(Plug *plug) { Check_Object(this); Check_Object(plug); if (!plug->m_chainLinkHead) m_nextPlugLink = this; else { Check_Object(plug->m_chainLinkHead); m_nextPlugLink = plug->m_chainLinkHead->m_nextPlugLink; plug->m_chainLinkHead->m_nextPlugLink = this; } plug->m_chainLinkHead = this; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Chain ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // //############################################################################# // ~Chain //############################################################################# // Chain::~Chain() { Check_Object(this); ChainLink *link = m_head; while (link) { Check_Object(link); ChainLink *next = link->m_nextChainLink; Check_Object(link); delete link; link = next; } } // //############################################################################# // AddImplementation //############################################################################# // void Chain::AddPlug(Plug *plug) { Check_Object(this); m_tail = new ChainLink(this, plug, NULL, m_tail); if (!m_head) m_head = m_tail; } // //########################################################################### // IsPlugMember //########################################################################### // void Chain::DeletePlugs() { ChainLink *link = m_head; while (link) { Check_Object(link); ChainLink *next = link->m_nextChainLink; Check_Object(link); Check_Object(link->GetPlug()); delete link->GetPlug(); link = next; } } // //########################################################################### // GetNthImplementation //########################################################################### // void* Chain::GetNthItem(unsigned index) { Check_Object(this); unsigned count = 0; for (ChainLink *link = m_head; link != NULL; link = link->m_nextChainLink) { Check_Object(link); if (count == index) return link->m_plug; count++; } return NULL; } // //########################################################################### // GetSize //########################################################################### // unsigned Chain::GetSize() { Check_Object(this); unsigned count=0; for (ChainLink *link = m_head; link != NULL; link = link->m_nextChainLink) { Check_Object(link); count++; } return count; } // //############################################################################# // InsertChainLink //############################################################################# // ChainLink* Chain::InsertChainLink( Plug *plug, ChainLink *current_link ) { Check_Object(this); Check_Object(plug); Check_Object(current_link); ChainLink *new_link = new ChainLink( this, plug, current_link, current_link->m_prevChainLink ); Register_Object(new_link); if (!new_link->m_prevChainLink) { Verify(m_head == current_link); m_head = new_link; } return new_link; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ChainIterator ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // //########################################################################### // GetNthImplementation //########################################################################### // void* ChainIterator::GetNthItem(unsigned index) { Check_Object(this); unsigned count = 0; for ( ChainLink *link = m_chain->m_head; link != NULL; link = link->m_nextChainLink ) { Check_Object(link); if (count == index) { m_currentLink = link; return m_currentLink->m_plug; } count++; } return NULL; } // //########################################################################### // Remove //########################################################################### // void ChainIterator::Remove() { Check_Object(this); ChainLink *oldLink = m_currentLink; Check_Object(m_currentLink); m_currentLink = m_currentLink->m_nextChainLink; Check_Object(oldLink); delete oldLink; } // //########################################################################### // InsertImplementation //########################################################################### // void ChainIterator::InsertPlug(Plug *plug) { Check_Object(this); m_currentLink = m_chain->InsertChainLink(plug, m_currentLink); Check_Object(m_currentLink); }