mpx/commonframework/common/src/mpxheapmanager.cpp
changeset 0 a2952bb97e68
child 50 762d760dcfdf
equal deleted inserted replaced
-1:000000000000 0:a2952bb97e68
       
     1 /*
       
     2 * Copyright (c) 2006 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  Implementation of heap manager 
       
    15 *
       
    16 */
       
    17 
       
    18 #include <hal.h>
       
    19 #include <centralrepository.h>
       
    20 #include <mpxprivatecrkeys.h>
       
    21 #include <mpxdata.h>
       
    22 #include <mpxlog.h>
       
    23 #include "mpxheapmanager.h"
       
    24 
       
    25 _LIT(KMPXChunkNameV2,"MPX_DATA");
       
    26 _LIT(KMPXMutexNameV2,"MPX_MUTEX");
       
    27 
       
    28 const TInt KMPXBytesPerMB = 0x100000;   // bytes of 1 MB, 1024*1024
       
    29 #ifdef __WINS__
       
    30 const TInt KMPXMaxHeapDefaultSize=8; // MB
       
    31 #else
       
    32 const TInt KMPXMaxHeapDefaultSize=15; // MB
       
    33 #endif
       
    34 const TInt KMPXMinHeapSize=0x10000;     // 64KB
       
    35 const TInt KMPXChunkAdjustSize=0x40000; // 256KB
       
    36 #ifdef __ENABLE_MPX_GARBAGE_COLLECTOR
       
    37 const TInt KMPXGarbageCollectorClientThreshold=1000;//GC
       
    38 #endif // __ENABLE_MPX_GARBAGE_COLLECTOR
       
    39 
       
    40 #define MPX_NEXT_CELL(p) ((RMPXHeapCell*)(((TUint8*)p)+p->iLen))
       
    41 #define MPX_NEXT_FREE_CELL(ch,p) (p->iNextOffset?Ptr<RMPXHeapCell>(ch, p->iNextOffset):NULL)
       
    42 
       
    43 // -----------------------------------------------------------------------------
       
    44 // RMPXHeapManager::TClientContext::TClientContext
       
    45 // -----------------------------------------------------------------------------
       
    46 //
       
    47 RMPXHeapManager::TClientContext::TClientContext()
       
    48     : iTid(KNullThreadId),iCount(0),iBase(0)
       
    49     {
       
    50     }
       
    51 
       
    52 // -----------------------------------------------------------------------------
       
    53 // RMPXHeapManager::TClientContext::TClientContext
       
    54 // -----------------------------------------------------------------------------
       
    55 //
       
    56 RMPXHeapManager::TClientContext::TClientContext(
       
    57     TUint8* aBase,
       
    58     TInt aChunkHandle,
       
    59     TInt aMutexHandle) :
       
    60     iTid(RThread().Id()),
       
    61     iCount(0),
       
    62     iBase(aBase)
       
    63     {
       
    64     iChunk.SetHandle(aChunkHandle);
       
    65     iMutex.SetHandle(aMutexHandle);
       
    66     }
       
    67 
       
    68 // -----------------------------------------------------------------------------
       
    69 // RMPXHeapManager::RMPXHeapManager
       
    70 // -----------------------------------------------------------------------------
       
    71 //
       
    72 RMPXHeapManager::RMPXHeapManager(const RChunk& aChunk)
       
    73     : iEndOffset(aChunk.Size()),iCounter(0)
       
    74 #ifdef __ENABLE_MPX_GARBAGE_COLLECTOR
       
    75     ,iDeadContextIndex(KErrNotFound)
       
    76 #endif // __ENABLE_MPX_GARBAGE_COLLECTOR
       
    77     {
       
    78     TInt hmSize = sizeof(RMPXHeapManager); 
       
    79     MPX_ASSERT_WORD_ALIGNED(aChunk.Base()+hmSize);
       
    80     //
       
    81     // Create first free heap cell
       
    82     //
       
    83     RMPXHeapCell* cell=new(aChunk.Base()+hmSize)RMPXHeapCell(0,iEndOffset-hmSize);
       
    84     // set up free cell list header
       
    85     iFree.iNextOffset = hmSize;
       
    86     iFree.iLen = 0;
       
    87     iUsedMemory = hmSize;
       
    88     }
       
    89 
       
    90 // -----------------------------------------------------------------------------
       
    91 // RMPXHeapManager::HeapMemoryInfoL
       
    92 // -----------------------------------------------------------------------------
       
    93 //
       
    94 void RMPXHeapManager::HeapMemoryInfoL(TInt& aTotal, TInt& aUsed)
       
    95     {
       
    96     TUint h = RMPXHeapManager::ClientHandle();
       
    97     if (!h)
       
    98         {
       
    99         User::Leave(KErrNotFound);
       
   100         }
       
   101     RMPXHeapManager& hm = RMPXHeapManager::HeapManager(h);
       
   102     aUsed = hm.iUsedMemory;
       
   103     HAL::Get(HALData::EMemoryRAMFree, aTotal);
       
   104     aTotal +=aUsed;
       
   105     if (aTotal > hm.iMaxMemory)
       
   106         {
       
   107         aTotal = hm.iMaxMemory;
       
   108         }
       
   109     }
       
   110 
       
   111 // -----------------------------------------------------------------------------
       
   112 // RMPXHeapManager::ClientHandle
       
   113 // -----------------------------------------------------------------------------
       
   114 //
       
   115 TUint RMPXHeapManager::ClientHandle()
       
   116     {
       
   117     // First, try to retrieve the handle from TLS. Although slow, this seems to be
       
   118     // faster than openeing the chunk, though probably requires further testing. It
       
   119     // will be in TLS if another client from this thread has previously called this
       
   120     // method
       
   121     //
       
   122     TUint h=(TUint)Dll::Tls();
       
   123     RMPXHeapManager* m=NULL;
       
   124     if (h==0)
       
   125         {
       
   126         // Must be first client in this thread, so try opening the chunk, but
       
   127         // first, create a "critical section" on this code to protect against multiple
       
   128         // threads creating the chunk/heap at the same time
       
   129         //
       
   130         RMutex mx;
       
   131         TInt n=2;
       
   132         TInt r=KErrNotFound;
       
   133         while(r!=KErrNone && n--)
       
   134             {
       
   135             r=mx.OpenGlobal(KMPXMutexNameV2,EOwnerThread);
       
   136             if (r==KErrNotFound)
       
   137                 {
       
   138                 r=mx.CreateGlobal(KMPXMutexNameV2,EOwnerThread);
       
   139                 }
       
   140             };
       
   141         if (r==KErrNone)
       
   142             {
       
   143             mx.Wait();
       
   144             //
       
   145             TUint8* base=NULL;
       
   146             RChunk c;
       
   147             r=c.OpenGlobal(KMPXChunkNameV2,EFalse,EOwnerThread);
       
   148             if (r==KErrNotFound)
       
   149                 {
       
   150                 // Chunk not there, so this must be the first client in the system and so
       
   151                 // the chunk must be created
       
   152                 //
       
   153                 // Get maximum size of memory from CenRep key
       
   154                 CRepository* rep(NULL);
       
   155                 // Set to default size
       
   156                 TInt maxMemory = KMPXMaxHeapDefaultSize;
       
   157                 TRAP_IGNORE(rep =  CRepository::NewL( KCRUidMPXSettings ));
       
   158                 if (rep)
       
   159                     {
       
   160                     rep->Get( KMPXMaxGlobalHeapSize, maxMemory );
       
   161                     delete rep;
       
   162                     }
       
   163                 // size in bytes
       
   164                 maxMemory *= KMPXBytesPerMB;
       
   165                 r=c.CreateGlobal(KMPXChunkNameV2,0,maxMemory,EOwnerThread);
       
   166                 if (r==KErrNone && c.Adjust(KMPXMinHeapSize)==KErrNone)
       
   167                     {
       
   168                     base=c.Base();
       
   169                     //
       
   170                     // Add the Heap Manager and the bottom of the chunk. Thereafter will come the
       
   171                     // data
       
   172                     //
       
   173                     MPX_ASSERT(sizeof(RMPXHeapManager)<KMPXMinHeapSize);
       
   174                     m=new(base)RMPXHeapManager(c); // Add on chunk
       
   175                     m->iMaxMemory = maxMemory;
       
   176                     }
       
   177                 }
       
   178             if (r==KErrNone)
       
   179                 {
       
   180                 if (!base)
       
   181                     {
       
   182                     base=c.Base();
       
   183                     }
       
   184                 m=reinterpret_cast<RMPXHeapManager*>(base);
       
   185                 TClientContext cc(base,c.Handle(),mx.Handle());
       
   186                 TInt index=m->ClientIndex(cc);
       
   187                 h=ClientHandle(base,index);
       
   188                 Dll::SetTls((TAny*)h);
       
   189                 mx.Signal();
       
   190                 }
       
   191             else
       
   192                 {
       
   193                 c.Close();
       
   194                 mx.Signal();
       
   195                 mx.Close();
       
   196                 m=NULL;
       
   197                 }
       
   198             }
       
   199         }
       
   200     MPX_ASSERT(h);
       
   201     return h;
       
   202     }
       
   203 
       
   204 // -----------------------------------------------------------------------------
       
   205 // RMPXHeapManager::Find
       
   206 // -----------------------------------------------------------------------------
       
   207 //
       
   208 TInt RMPXHeapManager::Find(const TThreadId& aTid)
       
   209     {
       
   210     TInt r=KErrNotFound;
       
   211     for (TInt i=0;i<ENumClients;++i)
       
   212         {
       
   213         if (iClients[i].iTid==aTid)
       
   214             {
       
   215             r=i;
       
   216             break;
       
   217             }
       
   218         }
       
   219     return r;
       
   220     }
       
   221 
       
   222 // -----------------------------------------------------------------------------
       
   223 // RMPXHeapManager::ClientIndex
       
   224 // -----------------------------------------------------------------------------
       
   225 //
       
   226 TInt RMPXHeapManager::ClientIndex(const TClientContext& aContext)
       
   227     {
       
   228     TInt i=Find(aContext.iTid);
       
   229     if (i==KErrNotFound)
       
   230         {
       
   231         i=Find(KNullThreadId); // First unused slot
       
   232         MPX_ASSERT(i>=0); // Run out of space (num threads > ENumClients)
       
   233         iClients[i]=aContext;
       
   234         }
       
   235     return i;
       
   236     }
       
   237 
       
   238 // -----------------------------------------------------------------------------
       
   239 // RMPXHeapManager::AddRef
       
   240 // -----------------------------------------------------------------------------
       
   241 //
       
   242 void RMPXHeapManager::AddRef(TUint aClientHandle)
       
   243     {
       
   244     MPX_ASSERT(aClientHandle);
       
   245     TClientContext& c=iClients[ClientIndex(aClientHandle)];
       
   246     ++c.iCount;
       
   247 #ifdef __ENABLE_MPX_GARBAGE_COLLECTOR
       
   248     if (iCounter%KMPXGarbageCollectorClientThreshold==0 && iCounter)
       
   249         {//GC
       
   250         RunGc(aClientHandle);
       
   251         }
       
   252 #endif // __ENABLE_MPX_GARBAGE_COLLECTOR
       
   253     }
       
   254 
       
   255 // -----------------------------------------------------------------------------
       
   256 // RMPXHeapManager::Release()
       
   257 // -----------------------------------------------------------------------------
       
   258 //
       
   259 void RMPXHeapManager::Release(TUint aClientHandle)
       
   260     {
       
   261     MPX_ASSERT(aClientHandle);
       
   262     TClientContext& c=iClients[ClientIndex(aClientHandle)];
       
   263     if (--c.iCount==0)
       
   264         {
       
   265 #ifdef __ENABLE_MPX_GARBAGE_COLLECTOR
       
   266         c.iData.Close(aClientHandle); //GC
       
   267 #endif // __ENABLE_MPX_GARBAGE_COLLECTOR
       
   268         c.iTid=KNullThreadId; // Mark as free
       
   269         c.iMutex.Close();
       
   270         c.iChunk.Close();
       
   271         Dll::SetTls(NULL);
       
   272         }
       
   273     }
       
   274 
       
   275 // -----------------------------------------------------------------------------
       
   276 // RMPXHeapManager::HeapCell
       
   277 // -----------------------------------------------------------------------------
       
   278 //
       
   279 RMPXHeapCell* RMPXHeapManager::HeapCell(
       
   280     TUint aClientHandle,
       
   281     TInt aSize)
       
   282     {
       
   283     aSize = Align4(aSize + EHeapCellHeaderSize);
       
   284     RMPXHeapCell* lastFree(NULL);
       
   285     RMPXHeapCell* cell = DoHeapCell(aClientHandle, aSize, lastFree);
       
   286     if (!cell)
       
   287         { // try to grow chunk
       
   288         TInt r = TryToGrowHeap(aClientHandle, aSize, lastFree);
       
   289         if (KErrNone == r)
       
   290             {
       
   291             cell = DoHeapCell(aClientHandle, aSize, lastFree);
       
   292             }
       
   293         }
       
   294     if (cell)
       
   295         {
       
   296         iUsedMemory += (cell->iLen);
       
   297         }
       
   298     return cell;
       
   299     }
       
   300 
       
   301 // -----------------------------------------------------------------------------
       
   302 // RMPXHeapManager::HeapCell
       
   303 // -----------------------------------------------------------------------------
       
   304 //
       
   305 RMPXHeapCell* RMPXHeapManager::DoHeapCell(
       
   306     TUint aClientHandle,
       
   307     TInt aSize, 
       
   308     RMPXHeapCell*& aLastFree)
       
   309     {
       
   310     //
       
   311     // Start with the first cell and walk the heap until a free cell is found which
       
   312     // is big enough
       
   313     //
       
   314     RMPXHeapCell* prevCell = &iFree;
       
   315     RMPXHeapCell* cell = MPX_NEXT_FREE_CELL(aClientHandle, prevCell); 
       
   316     TInt tempOffset(0);
       
   317     for (; cell; prevCell=cell, cell=MPX_NEXT_FREE_CELL(aClientHandle, cell))
       
   318         { // scan the free list
       
   319         //cell is valid and free
       
   320         if (cell->iLen >= aSize)
       
   321             { // size is big enough
       
   322             if (cell->iLen-aSize < EMinCellSize) // leftover must larger enough to split
       
   323                 { // it isn't, so take it all
       
   324                 aSize = cell->iLen;
       
   325                 tempOffset = cell->iNextOffset;
       
   326                 MPX_ASSERT(tempOffset <= iEndOffset - EMinCellSize);
       
   327                 }
       
   328             else
       
   329                 { // Take amount and create a new free cell
       
   330                 tempOffset = Offset(aClientHandle, cell) + aSize;
       
   331                 MPX_ASSERT(tempOffset <= iEndOffset - EMinCellSize);
       
   332                 // create a new cell
       
   333                 new(Ptr<TAny>(aClientHandle,tempOffset)) 
       
   334                            RMPXHeapCell(cell->iNextOffset, cell->iLen - aSize);
       
   335                 }
       
   336             prevCell->iNextOffset = tempOffset;
       
   337             cell->iLen = aSize;
       
   338             return cell;
       
   339             }
       
   340         }
       
   341     aLastFree = prevCell;
       
   342     return NULL;
       
   343     }
       
   344 
       
   345 TInt RMPXHeapManager::TryToGrowHeap(
       
   346     TUint aClientHandle, 
       
   347     TInt aSize, 
       
   348     RMPXHeapCell* aLastFree)
       
   349     {
       
   350     TBool atEnd = IsLastCell(aClientHandle, aLastFree);
       
   351     TInt grow=Max((TInt)KMPXChunkAdjustSize, aSize);
       
   352     // Grow the chunk
       
   353     TClientContext& cc=iClients[ClientIndex(aClientHandle)];
       
   354     TInt r(KErrNoMemory);
       
   355     if (iEndOffset+grow <= iMaxMemory)
       
   356         {
       
   357         r=cc.iChunk.Adjust(iEndOffset+grow);
       
   358         if (KErrNone == r)
       
   359             {
       
   360             if (atEnd)
       
   361                 {
       
   362                 aLastFree->iLen += grow;
       
   363                 }
       
   364             else
       
   365                 { // create a new free cell
       
   366                 new (Ptr<RMPXHeapCell>(aClientHandle, iEndOffset))RMPXHeapCell(0, grow);
       
   367                 aLastFree->iNextOffset = iEndOffset;
       
   368                 }
       
   369             iEndOffset=cc.iChunk.Size();
       
   370             }
       
   371         else
       
   372             {
       
   373             MPX_DEBUG2("RMPXHeapManager::HeapCell chunk failed to grow %d", r);
       
   374             }
       
   375         }
       
   376     return r;
       
   377     }
       
   378 
       
   379 // -----------------------------------------------------------------------------
       
   380 // RMPXHeapManager::ClientCount
       
   381 // -----------------------------------------------------------------------------
       
   382 //
       
   383 TInt RMPXHeapManager::ClientCount() const
       
   384     {
       
   385     TInt c=0;
       
   386     for (TInt i=0;i<ENumClients;++i)
       
   387         {
       
   388         if (iClients[i].iTid.Id()!=KNullThreadId)
       
   389             {
       
   390             ++c;
       
   391             }
       
   392         }
       
   393     return c;
       
   394     }
       
   395 
       
   396 // -----------------------------------------------------------------------------
       
   397 // Allocate a buffer on the chunk
       
   398 // -----------------------------------------------------------------------------
       
   399 //
       
   400 TAny* RMPXHeapManager::Alloc(TUint aClientHandle,TInt aSize)
       
   401     {
       
   402     TAny* ptr=NULL;
       
   403     TInt size=Align4(aSize);
       
   404     RMPXHeapCell* cell=HeapCell(aClientHandle,size);
       
   405     if (cell)
       
   406         {
       
   407         TInt offset = RMPXHeapManager::Offset(aClientHandle, cell) + EHeapCellHeaderSize;
       
   408         ptr=Ptr<TAny>(aClientHandle,offset);
       
   409         MPX_ASSERT(ptr);
       
   410         MPX_ASSERT_WORD_ALIGNED(ptr);
       
   411         }
       
   412     return ptr;
       
   413     }
       
   414 
       
   415 // -----------------------------------------------------------------------------
       
   416 // Copy a buffer on the chunk
       
   417 // -----------------------------------------------------------------------------
       
   418 //
       
   419 TInt RMPXHeapManager::Copy(TUint aClientHandle,TAny* aSrc,TInt aSize)
       
   420     {
       
   421     TInt r=KErrNoMemory;
       
   422     TAny* ptr=Alloc(aClientHandle,aSize);
       
   423     if (ptr)
       
   424         {
       
   425         (void)Mem::Copy(ptr,aSrc,aSize);
       
   426         r=RMPXHeapManager::Offset(aClientHandle,ptr);
       
   427         }
       
   428     return r;
       
   429     }
       
   430 
       
   431 // -----------------------------------------------------------------------------
       
   432 // Frees a pointer on the chunk
       
   433 // -----------------------------------------------------------------------------
       
   434 //
       
   435 TInt RMPXHeapManager::Free(TUint aClientHandle,TAny* aPtr)
       
   436     {
       
   437     TInt cellOffset=RMPXHeapManager::Offset(aClientHandle, aPtr)-sizeof(RMPXHeapCell);
       
   438     RMPXHeapCell* cell = Ptr<RMPXHeapCell>(aClientHandle,cellOffset);
       
   439     RMPXHeapCell* prevCell = &iFree;
       
   440     RMPXHeapCell* tempCell = MPX_NEXT_FREE_CELL(aClientHandle, prevCell);
       
   441     RMPXHeapCell* nextCell(NULL);
       
   442     TInt size = cell->iLen;
       
   443     // find the position in the list for the new free cell
       
   444     for (; tempCell && tempCell<cell; 
       
   445          prevCell=tempCell, tempCell= MPX_NEXT_FREE_CELL(aClientHandle, tempCell))
       
   446         {
       
   447         }
       
   448     if (tempCell)
       
   449         { // Is there a following free cell?
       
   450         nextCell = MPX_NEXT_CELL(cell);
       
   451         if (nextCell == tempCell)
       
   452             { //Yes, merge two cells
       
   453             cell->iLen += tempCell->iLen;
       
   454             cell->iNextOffset = tempCell->iNextOffset;
       
   455             }
       
   456         else
       
   457             {
       
   458             cell->iNextOffset = RMPXHeapManager::Offset(aClientHandle, tempCell);
       
   459             }
       
   460         }
       
   461     else
       
   462         {
       
   463         cell->iNextOffset = 0; // No following free cell
       
   464         }
       
   465 
       
   466     nextCell = MPX_NEXT_CELL(prevCell);
       
   467     if (nextCell==cell) // Is it adjacent
       
   468         {
       
   469         prevCell->iLen += cell->iLen;
       
   470         prevCell->iNextOffset = cell->iNextOffset;
       
   471         cell = prevCell;
       
   472         }
       
   473     else
       
   474         {
       
   475         prevCell->iNextOffset = RMPXHeapManager::Offset(aClientHandle, cell);
       
   476         }
       
   477     
       
   478     iUsedMemory -= size;
       
   479     MPX_ASSERT(iUsedMemory > 0);
       
   480     // Shrink chunk
       
   481     // How big is the chunk now
       
   482     //
       
   483     // TInt gap=last->iBufOffset+last->iBufLen-iEndOffset;
       
   484     //if (gap>2*KMPXChunkAdjustSize)
       
   485     //   {
       
   486         // We assume that a spare capacity of KMPXChunkAdjustSize bytes
       
   487         // is all we need, so if we have more we can shrink the chunk
       
   488         //
       
   489     //    TClientContext& cc=iClients[ClientIndex(aClientHandle)];
       
   490     //    cc.iChunk.Adjust(iEndOffset-KMPXChunkAdjustSize);
       
   491     //    iEndOffset=cc.iChunk.Size();
       
   492     //    }
       
   493 
       
   494     return KErrNone;
       
   495     }
       
   496 
       
   497 // -----------------------------------------------------------------------------
       
   498 // RMPXHeapManager::Lock
       
   499 // -----------------------------------------------------------------------------
       
   500 //
       
   501 void RMPXHeapManager::Lock(TUint aClientHandle)
       
   502     {
       
   503     MPX_ASSERT(aClientHandle);
       
   504     TClientContext& cc=iClients[ClientIndex(aClientHandle)];
       
   505     cc.iMutex.Wait();
       
   506     }
       
   507 
       
   508 // -----------------------------------------------------------------------------
       
   509 // RMPXHeapManager::Unlock
       
   510 // -----------------------------------------------------------------------------
       
   511 //
       
   512 void RMPXHeapManager::Unlock(TUint aClientHandle)
       
   513     {
       
   514     MPX_ASSERT(aClientHandle);
       
   515     TClientContext& cc=iClients[ClientIndex(aClientHandle)];
       
   516     cc.iMutex.Signal();
       
   517     }
       
   518 
       
   519 // -----------------------------------------------------------------------------
       
   520 // RMPXHeapManager::Counter
       
   521 // -----------------------------------------------------------------------------
       
   522 //
       
   523 TInt RMPXHeapManager::IncrementCounter()
       
   524     {
       
   525     MPX_DEBUG3("RMPXHeapManager::Counter 0x%08x, count %d", this, iCounter);
       
   526     return ++iCounter;
       
   527     }
       
   528 
       
   529 // -----------------------------------------------------------------------------
       
   530 // RMPXHeapManager::IsLastCell
       
   531 // -----------------------------------------------------------------------------
       
   532 //
       
   533 TBool RMPXHeapManager::IsLastCell(
       
   534     TUint aClientHandle, 
       
   535     RMPXHeapCell* aCell)
       
   536     {
       
   537     return (RMPXHeapManager::Offset(aClientHandle, aCell) + aCell->iLen) == iEndOffset;
       
   538     }
       
   539 
       
   540 #ifdef __ENABLE_MPX_GARBAGE_COLLECTOR
       
   541 // -----------------------------------------------------------------------------
       
   542 // Cleans up any objects associated with threads that have died
       
   543 // -----------------------------------------------------------------------------
       
   544 //
       
   545 void RMPXHeapManager::RunGc(TUint aClientHandle)
       
   546     {//GC
       
   547     MPX_FUNC("RMPXHeapManager::RunGc");
       
   548     RThread t;
       
   549     for (TInt i=0;i<ENumClients;++i)
       
   550         {
       
   551         if (i!=ClientIndex(aClientHandle)) // No point in looking at current thread!
       
   552             {
       
   553             TClientContext& c=iClients[i];
       
   554             TThreadId tid=c.iTid;
       
   555             if (tid.Id()!=KNullThreadId)
       
   556                 {
       
   557                 TInt r=t.Open(tid,EOwnerThread);
       
   558                 if (r==KErrNone) // Thread still exists, so that's OK
       
   559                     {
       
   560                     t.Close();
       
   561                     }
       
   562                 else
       
   563                     {
       
   564                     // Cannot open the thread, but we still have an entry for it. This (may)
       
   565                     // mean that there data stranded on the heap which we must remove
       
   566                     //
       
   567                     // Remove data associated with this thread
       
   568                     //
       
   569                     TInt j = c.iData.Count()-1;
       
   570                     while (j>=0)
       
   571                         {
       
   572                         RMPXDataObject<TUint>* d=
       
   573                             (RMPXDataObject<TUint>*)c.iData.DataItem(aClientHandle,j);
       
   574                         TUint* dataHandle=d->Object(aClientHandle);
       
   575                         MMPXData* data=MMPXData::Data(aClientHandle, *dataHandle);
       
   576                         iDeadContextIndex=i;
       
   577                         data->Release(aClientHandle);
       
   578                         iDeadContextIndex=KErrNotFound;
       
   579                         j = c.iData.Count()-1;
       
   580                         }
       
   581 
       
   582                     // Now remove context, now that we've cleaned up its data
       
   583                     //
       
   584                     c.iTid=KNullThreadId; // Mark as free
       
   585                     c.iData.Close(aClientHandle);
       
   586                     }
       
   587                 }
       
   588             }
       
   589         }
       
   590     }
       
   591 
       
   592 // -----------------------------------------------------------------------------
       
   593 // RMPXHeapManager::AddData
       
   594 // -----------------------------------------------------------------------------
       
   595 //
       
   596 TInt RMPXHeapManager::AddData(TUint aClientHandle,TUint aDataHandle)
       
   597     { //GC
       
   598     TAny* ptr =Alloc(aClientHandle, sizeof(RMPXDataObject<TUint>));
       
   599     TInt r(KErrNone);
       
   600     if (ptr)
       
   601         {
       
   602         RMPXDataObject<TUint>* obj=new(ptr)RMPXDataObject<TUint>();
       
   603         obj->CopyObject(aClientHandle,aDataHandle);
       
   604         TClientContext& c=iClients[ClientIndex(aClientHandle)];
       
   605         c.iData.Append(aClientHandle,*obj);
       
   606         }
       
   607     else
       
   608         {
       
   609         r = KErrNoMemory;
       
   610         }
       
   611     return r;
       
   612     }
       
   613 
       
   614 // -----------------------------------------------------------------------------
       
   615 // RMPXHeapManager::RemoveData
       
   616 // -----------------------------------------------------------------------------
       
   617 //
       
   618 TInt RMPXHeapManager::RemoveData(
       
   619     TUint aClientHandle,
       
   620     TUint aDataHandle,
       
   621     TBool aRemoveAll)
       
   622     {//GC
       
   623     RMPXDataObject<TUint> obj;
       
   624     obj.CopyObject(aClientHandle,aDataHandle);
       
   625     TInt clientIndex = ClientIndex(aClientHandle);
       
   626     TInt ret(KErrNotFound);
       
   627 
       
   628     if (aRemoveAll && iDeadContextIndex==KErrNotFound)
       
   629         { // remove all and GC is not running
       
   630         for (TInt i=0;i<ENumClients;++i)
       
   631             {
       
   632             TClientContext& c=iClients[i];
       
   633             TThreadId tid=c.iTid;
       
   634             if (tid.Id()!=KNullThreadId)
       
   635                 { // Remove datahandle
       
   636                 ret = c.iData.Find(aClientHandle, obj);
       
   637                 if (KErrNotFound != ret)
       
   638                     {
       
   639                     c.iData.Remove(aClientHandle, ret);
       
   640                     ret = KErrNone;
       
   641                     }
       
   642                 }
       
   643             }
       
   644         }
       
   645     else
       
   646         {
       
   647         // Remove data from current context
       
   648         TClientContext& cc = (iDeadContextIndex==KErrNotFound ?
       
   649                              iClients[clientIndex] : iClients[iDeadContextIndex]);
       
   650         ret = cc.iData.Find(aClientHandle,obj);
       
   651         if (KErrNotFound != ret)
       
   652             {
       
   653             cc.iData.Remove(aClientHandle,ret);
       
   654             ret=KErrNone;
       
   655             }
       
   656         }
       
   657     obj.Close(aClientHandle);
       
   658     return ret;
       
   659     }
       
   660 #endif // __ENABLE_MPX_GARBAGE_COLLECTOR
       
   661 
       
   662 // End of file