hxglobalmgr_imp.cpp
上传用户:zhongxx05
上传日期:2007-06-06
资源大小:33641k
文件大小:10k
源码类别:

Symbian

开发平台:

C/C++

  1. /* ***** BEGIN LICENSE BLOCK ***** 
  2.  * Version: RCSL 1.0/RPSL 1.0 
  3.  *  
  4.  * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved. 
  5.  *      
  6.  * The contents of this file, and the files included with this file, are 
  7.  * subject to the current version of the RealNetworks Public Source License 
  8.  * Version 1.0 (the "RPSL") available at 
  9.  * http://www.helixcommunity.org/content/rpsl unless you have licensed 
  10.  * the file under the RealNetworks Community Source License Version 1.0 
  11.  * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl, 
  12.  * in which case the RCSL will apply. You may also obtain the license terms 
  13.  * directly from RealNetworks.  You may not use this file except in 
  14.  * compliance with the RPSL or, if you have a valid RCSL with RealNetworks 
  15.  * applicable to this file, the RCSL.  Please see the applicable RPSL or 
  16.  * RCSL for the rights, obligations and limitations governing use of the 
  17.  * contents of the file.  
  18.  *  
  19.  * This file is part of the Helix DNA Technology. RealNetworks is the 
  20.  * developer of the Original Code and owns the copyrights in the portions 
  21.  * it created. 
  22.  *  
  23.  * This file, and the files included with this file, is distributed and made 
  24.  * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
  25.  * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
  26.  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS 
  27.  * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
  28.  * 
  29.  * Technology Compatibility Kit Test Suite(s) Location: 
  30.  *    http://www.helixcommunity.org/content/tck 
  31.  * 
  32.  * Contributor(s): 
  33.  *  
  34.  * ***** END LICENSE BLOCK ***** */ 
  35. #include "hxglobalmgr_imp.h"
  36. #include "hxassert.h"
  37. #include "hxthread.h"
  38. class HXGlobalMap
  39. {
  40. public:
  41.     HXGlobalMap();
  42.     ~HXGlobalMap();
  43.     
  44.     void       Add(const int* pContext, GlobalID id, GlobalType pObj,
  45.    HXGlobalDestroyFunc fpDestroy);
  46.     void       Remove(GlobalID id);
  47.     void       RemoveAll(const int* pContext);
  48.     GlobalPtr  Get(GlobalID id) const;
  49.     BOOL       IsMember(GlobalID id) const;
  50. private: 
  51.     class MapNode
  52.     {
  53.     public:
  54. MapNode();
  55. MapNode(const int* pContext, GlobalID id, GlobalType pObj, 
  56. HXGlobalDestroyFunc fpDestroy);
  57. ~MapNode();
  58. MapNode*   GetNext() const { return m_pNext; }
  59. void       SetNext(MapNode* pNext) { m_pNext = pNext; }
  60. const int* Context() const { return m_pContext;}
  61.         GlobalID   ID() const { return m_id; }
  62. GlobalPtr  ObjPtr() { return &m_pObj; }
  63.     private:
  64. MapNode*            m_pNext;
  65. const int*          m_pContext;
  66. GlobalID            m_id;
  67. GlobalType          m_pObj;
  68. HXGlobalDestroyFunc m_fpDestroy;
  69.     };
  70.     unsigned int GetBucket(GlobalID id) const;
  71.     void     ResizeIfNeeded();
  72.     MapNode* FindNode(GlobalID id, MapNode** ppLastNode) const;
  73.     void     AddNode(MapNode* pNewNode);
  74.     int      m_bucketIndex;
  75.     int      m_bucketCount;
  76.     MapNode* m_pBuckets;
  77.     int      m_elementCount;
  78.     static const int zm_bucketCounts[];
  79. };
  80. // List of primes that are approximately double the
  81. // previous prime
  82. const int HXGlobalMap::zm_bucketCounts[] =
  83. {
  84.     3, 5, 11, 23, 53, 97, 193, 389, 
  85.     769, 1543, 3079, 6151, 12289, 
  86.     24593, 49157, 98317, 196613, 
  87.     393241, 786433, 1572869, 
  88.     3145739, 6291469, 12582917
  89. };
  90. HXGlobalMap::HXGlobalMap()
  91.     : m_bucketIndex(0)
  92.     , m_bucketCount(0)
  93.     , m_pBuckets(0)
  94.     , m_elementCount(0)
  95. {
  96.     m_bucketCount = zm_bucketCounts[m_bucketIndex];
  97.     m_pBuckets = new MapNode[m_bucketCount];
  98.     HX_ASSERT(m_pBuckets != NULL );
  99. }
  100. HXGlobalMap::~HXGlobalMap()
  101. {
  102.     for (int i = 0; i < m_bucketCount; i++)
  103.     {
  104. MapNode* pCur = m_pBuckets[i].GetNext();
  105. while (pCur)
  106. {
  107.     MapNode* pNext = pCur->GetNext();
  108.     delete pCur;
  109.     pCur = pNext;
  110. }
  111.     }
  112.     delete [] m_pBuckets;
  113.     m_pBuckets = 0;
  114.     m_bucketIndex = 0;
  115.     m_elementCount = 0;
  116. }
  117. void
  118. HXGlobalMap::Add(const int* pContext, GlobalID id, GlobalType pObj, 
  119.  HXGlobalDestroyFunc fpDestroy)
  120. {
  121.     AddNode(new MapNode(pContext, id, pObj, fpDestroy));
  122.     m_elementCount++;
  123.     ResizeIfNeeded();
  124. }
  125. void
  126. HXGlobalMap::Remove(GlobalID id)
  127. {
  128.     MapNode* pLastNode = 0;
  129.     MapNode* pCurNode = FindNode(id, &pLastNode);
  130.     if (pCurNode)
  131.     {
  132. pLastNode->SetNext(pCurNode->GetNext());
  133. delete pCurNode;
  134. m_elementCount--;
  135. ResizeIfNeeded();
  136.     }
  137. }
  138. GlobalPtr
  139. HXGlobalMap::Get(GlobalID id) const
  140. {
  141.     MapNode* pNode = FindNode(id, 0);
  142.     if (pNode)
  143.     {
  144. return pNode->ObjPtr();
  145.     }
  146.     return NULL;
  147. }
  148. BOOL
  149. HXGlobalMap::IsMember(GlobalID id) const
  150. {
  151.     return (FindNode(id, 0) != 0);
  152. }
  153. void
  154. HXGlobalMap::RemoveAll(const int* pContext)
  155. {
  156.     for (int i = 0; i < m_bucketCount; i++)
  157.     {
  158. MapNode* pLast = &m_pBuckets[i];
  159. MapNode* pCur = pLast->GetNext();
  160. while (pCur)
  161. {
  162.     if (pCur->Context() == pContext)
  163.     {
  164. MapNode* pNext = pCur->GetNext();
  165. delete pCur;
  166. m_elementCount--;
  167. pLast->SetNext(pNext);
  168. pCur = pNext;
  169.     }
  170.     else
  171.     {
  172. pLast = pCur;
  173. pCur = pCur->GetNext();
  174.     }
  175. }
  176.     }
  177.     ResizeIfNeeded();
  178. }
  179. unsigned int HXGlobalMap::GetBucket(GlobalID id) const
  180. {
  181.     unsigned int unRetVal = ((unsigned int)id) % m_bucketCount;
  182.     HX_ASSERT( unRetVal < m_bucketCount && unRetVal>=0 );
  183.     return unRetVal;
  184. }
  185. void
  186. HXGlobalMap::ResizeIfNeeded()
  187. {
  188.     MapNode* pOldBuckets = 0;
  189.     int oldBucketCount = m_bucketCount;
  190.     if ((m_elementCount > (m_bucketCount << 1)) &&
  191. (m_bucketIndex < ((int)(sizeof(zm_bucketCounts) / sizeof(int)))))
  192.     {
  193.         // Grow the map if the number of elements is
  194.         // larger than 2 times the bucket count
  195.        
  196.         m_bucketIndex++;
  197.         m_bucketCount = zm_bucketCounts[m_bucketIndex];
  198.         
  199.         pOldBuckets = m_pBuckets; // Save old map
  200.         m_pBuckets = new MapNode[m_bucketCount];
  201.     }
  202.     else if ((m_elementCount < (m_bucketCount >> 2)) &&
  203.      (m_bucketIndex > 0))
  204.     {
  205.         
  206.         // Shrink the map if the number of elements is
  207.         // smaller than 1/4th the bucket count
  208.         
  209.         pOldBuckets = m_pBuckets; // Save old map
  210.         
  211.         m_bucketIndex--;
  212.         
  213.         m_bucketCount = zm_bucketCounts[m_bucketIndex];
  214.         m_pBuckets = new MapNode[m_bucketCount];
  215.     }
  216.     
  217.     if (pOldBuckets)
  218.     {
  219.         // Transfer the nodes from the old buckets to
  220.         // the new buckets
  221.         
  222.         for (int i = 0; i < oldBucketCount; i++)
  223.         {
  224.             MapNode* pCurNode = pOldBuckets[i].GetNext();
  225.     
  226.             while(pCurNode)
  227.             {
  228.                 // Get the pointer to the next node before
  229.                 // we add the node since the AddNode() will
  230.                 // clobber it's next pointer
  231.                 MapNode* pNextNode = pCurNode->GetNext();
  232.                 
  233.                 AddNode(pCurNode);
  234.                 
  235.                 // Move onto the next node
  236.                 pCurNode = pNextNode;
  237.             }
  238.         }
  239.         
  240.         delete [] pOldBuckets;
  241.     }
  242. }
  243. HXGlobalMap::MapNode*
  244. HXGlobalMap::FindNode(GlobalID id, MapNode** ppLastNode) const
  245. {
  246.     MapNode* pRet = 0;
  247.     int bucket = GetBucket(id);
  248.     MapNode* pLastNode = &(m_pBuckets[bucket]);
  249.     MapNode* pCurNode = pLastNode->GetNext();
  250.     while(!pRet && pCurNode)
  251.     {
  252. if (pCurNode->ID() == id)
  253.     pRet = pCurNode;
  254. else
  255. {
  256.     pLastNode = pCurNode;
  257.     pCurNode = pCurNode->GetNext();
  258. }
  259.     }
  260.     if (ppLastNode)
  261. *ppLastNode = pLastNode;
  262.     return pRet;
  263. }
  264. void
  265. HXGlobalMap::AddNode(MapNode* pNewNode)
  266. {
  267.     int bucket = GetBucket(pNewNode->ID());
  268.     pNewNode->SetNext(m_pBuckets[bucket].GetNext());
  269.     m_pBuckets[bucket].SetNext(pNewNode);
  270. }
  271. HXGlobalMap::MapNode::MapNode()
  272.     : m_pNext(NULL)
  273.     , m_pContext(NULL)
  274.     , m_id(NULL)
  275.     , m_pObj(NULL)
  276.     , m_fpDestroy(NULL)
  277. {
  278. }
  279. HXGlobalMap::MapNode::MapNode(const int* pContext,
  280.       GlobalID id,
  281.       GlobalType pObj, 
  282.       HXGlobalDestroyFunc fpDestroy)
  283.     : m_pNext(NULL)
  284.     , m_pContext(pContext)
  285.     , m_id(id)
  286.     , m_pObj(pObj)
  287.     , m_fpDestroy(fpDestroy)
  288. {
  289. }
  290. HXGlobalMap::MapNode::~MapNode()
  291. {
  292.     if (m_pObj && m_fpDestroy)
  293.     {
  294. m_fpDestroy(m_pObj);
  295.     }
  296. }
  297. HXGlobalManagerImp::HXGlobalManagerImp()
  298.     : m_pMap(NULL)
  299.     , m_pMutex(NULL)
  300. {
  301.     m_pMap = new HXGlobalMap();
  302.     HX_ASSERT(m_pMap);
  303.     
  304. #if defined(THREADS_SUPPORTED) || defined(_UNIX_THREADS_SUPPORTED)
  305.     HXMutex::MakeMutex(m_pMutex);
  306. #else
  307.     HXMutex::MakeStubMutex(m_pMutex);
  308. #endif
  309. }
  310. HXGlobalManagerImp::~HXGlobalManagerImp()
  311. {
  312.     HX_DELETE(m_pMutex);
  313.     HX_DELETE(m_pMap);
  314. }
  315. GlobalPtr
  316. HXGlobalManagerImp::DoAdd(const int* pContext,
  317.        GlobalID id, 
  318.        GlobalType pObj,
  319.        HXGlobalDestroyFunc fpDestroy)
  320.       
  321. {
  322.     m_pMutex->Lock();
  323.     if (!m_pMap->IsMember(id))
  324.     {
  325.        m_pMap->Add(pContext, id, pObj, fpDestroy);
  326.     }
  327.     
  328.     GlobalPtr ptr = m_pMap->Get(id);
  329.     m_pMutex->Unlock();
  330.     return ptr;
  331. }
  332. void
  333. HXGlobalManagerImp::DoRemove(GlobalID id)
  334. {
  335.     m_pMutex->Lock();
  336.     m_pMap->Remove(id);
  337.     m_pMutex->Unlock();
  338. }
  339. GlobalPtr
  340. HXGlobalManagerImp::DoGet(GlobalID id) const
  341. {
  342.     m_pMutex->Lock();
  343.     GlobalPtr ptr = m_pMap->Get(id);
  344.     m_pMutex->Unlock();
  345.     return ptr;
  346. }
  347. void
  348. HXGlobalManagerImp::DoShutdown(const int* pContext)
  349. {
  350.     m_pMutex->Lock();
  351.     m_pMap->RemoveAll(pContext);
  352.     
  353.     m_pMutex->Unlock();
  354. }