os/kernelhwsrv/kernel/eka/euser/cbase/ub_obj.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 // Copyright (c) 1994-2009 Nokia Corporation and/or its subsidiary(-ies).
     2 // All rights reserved.
     3 // This component and the accompanying materials are made available
     4 // under the terms of the License "Eclipse Public License v1.0"
     5 // which accompanies this distribution, and is available
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
     7 //
     8 // Initial Contributors:
     9 // Nokia Corporation - initial contribution.
    10 //
    11 // Contributors:
    12 //
    13 // Description:
    14 // e32\euser\cbase\ub_obj.cpp
    15 // 
    16 //
    17 
    18 #include "ub_std.h"
    19 
    20 const TInt KObjectIxGranularity=8;
    21 const TInt KObjectConMinSize=8;		// must be power of 2 or 3*power of 2
    22 const TInt KObjectConIxGranularity=4;
    23 const TInt KObjectIndexMask=0x7fff;
    24 const TInt KObjectMaxIndex=0x7fff;
    25 const TInt KObjectInstanceShift=16;
    26 const TInt KObjectInstanceMask=0x3fff; 
    27 const TInt KObjectUniqueIDShift=16;
    28 const TInt KObjectUniqueIDMask=0xffff;
    29 const TInt KObjectIxMaxHandles=0x8000;
    30 const TInt KObjectConIxMaxSize=0x10000-1;
    31 
    32 inline TInt index(TInt aHandle)
    33 	{return(aHandle&KObjectIndexMask);}
    34 inline TInt instance(TInt aHandle)
    35 	{return((aHandle>>KObjectInstanceShift)&KObjectInstanceMask);}
    36 inline TInt instanceLimit(TInt& aCount)
    37 	{return ((aCount&KObjectInstanceMask)==0) ? ((++aCount)&KObjectInstanceMask) : aCount&KObjectInstanceMask;}
    38 inline TInt makeHandle(TInt anIndex,TInt anInstance)
    39 	{return((TInt)((anInstance<<KObjectInstanceShift)|anIndex));}
    40 
    41 inline TInt uniqueID(TInt aHandle)
    42 	{return((aHandle>>KObjectUniqueIDShift)&KObjectUniqueIDMask);}
    43 inline TInt makeFindHandle(TInt anIndex,TInt anUniqueID)
    44 	{return((TInt)((anUniqueID<<KObjectUniqueIDShift)|anIndex));}
    45 
    46 /**
    47 @internalComponent
    48 */
    49 enum {ENotOwnerID};
    50 
    51 LOCAL_C void makeFullName(TFullName &aFullName,const CObject *anOwner,const TDesC &aName)
    52 //
    53 // Make a name from its owner name and aName.
    54 //
    55 	{
    56 
    57 	aFullName.Zero();
    58 	if (anOwner)
    59 		{
    60         makeFullName(aFullName,anOwner->Owner(),anOwner->Name());
    61 		aFullName+=_L("::");
    62 		}
    63 	aFullName+=aName;
    64 	}
    65 
    66 
    67 
    68 
    69 /**
    70 Constructs the object and initializes the reference count to one. 
    71 
    72 Once constructed, a reference counting object cannot be deleted until its 
    73 reference count is reduced to zero. 
    74 
    75 @see CObject::Close
    76 */
    77 EXPORT_C CObject::CObject()
    78 	{
    79 
    80 //	iContainer=NULL;
    81 //	iOwner=NULL;
    82 //	iName=NULL;
    83 	iAccessCount=1;
    84 	}
    85 
    86 
    87 
    88 
    89 /**
    90 Destructor.
    91 
    92 It removes this reference counting object from its object container,
    93 a CObjectCon type.
    94 
    95 @panic E32USER-CBase 33 if the reference count is not zero when
    96        the destructor is called.
    97 
    98 @see CObjectCon
    99 */
   100 EXPORT_C CObject::~CObject()
   101 	{
   102 
   103 	__ASSERT_ALWAYS(AccessCount()==0,Panic(EObjObjectStillReferenced));
   104 	User::Free(iName);
   105 	if (iContainer)
   106 		{
   107 		CObjectCon *p=iContainer;
   108 		iContainer=NULL;
   109 		p->Remove(this);
   110 		}
   111 	}
   112 
   113 
   114 
   115 
   116 /**
   117 Opens this reference counting object.
   118 
   119 The default behaviour increments the reference count by one and
   120 returns KErrNone. 
   121 Where a derived class implements its own version of this function, it must 
   122 either use the protected member function Inc() to increment the reference 
   123 count or make a base call to this function.
   124 
   125 @return KErrNone.
   126 */
   127 EXPORT_C TInt CObject::Open()
   128 	{
   129 
   130 	Inc();
   131 	return(KErrNone);
   132 	}
   133 
   134 
   135 
   136 
   137 /**
   138 Closes this reference counting object.
   139 
   140 The default behaviour decrements the reference count by one. If this becomes 
   141 zero, then the function deletes this reference counting object.
   142 
   143 Where a derived class implements its own version of this function, it can 
   144 use the protected member function Dec() to decrement the reference count or 
   145 make a base call to this function.
   146 
   147 @panic E32USER-CBase 34 if the reference count is negative when this
   148        function is called.
   149 */
   150 EXPORT_C void CObject::Close()
   151 	{
   152 
   153 	Dec();
   154 	__ASSERT_ALWAYS(AccessCount()>=0,Panic(EObjNegativeAccessCount));
   155 	if (AccessCount()==0)
   156 		delete this;
   157 	}
   158 
   159 
   160 
   161 
   162 LOCAL_C TName GetLocalObjectName(const CObject *anObj)
   163 	{
   164 	TName n=_L("Local-");
   165 	n.AppendNumFixedWidth((TInt)anObj,EHex,8);
   166 	return n;
   167 	}
   168 
   169 
   170 
   171 
   172 /**
   173 Gets the name of this reference counting object.
   174 
   175 The default behaviour provided by this function depends on whether a name 
   176 has been explicitly set into the object:
   177 
   178 if a name has previously been set, then the function returns that name.
   179 
   180 if a name has not been set, then the function builds a default name. This 
   181 is fourteen characters and has the format: LOCAL-nnnnnnnn where nnnnnnnn is 
   182 the hexadecimal character representation of this reference counting object's 
   183 address. This default name is, therefore, guaranteed to be unique within the 
   184 current process.
   185 
   186 @return A modifiable buffer descriptor with a defined maximum length containing 
   187         the name of this reference counting object.
   188 */
   189 EXPORT_C TName CObject::Name() const
   190 	{
   191 	if (iName)
   192 		return(*iName);
   193 	return GetLocalObjectName(this);
   194 	}
   195 
   196 
   197 
   198 
   199 /**
   200 Gets the full name of this reference counting object.
   201 
   202 By default, the full name is a concatenation of this reference counting
   203 object's name with the full name of its owning reference counting object.
   204 
   205 @return A modifiable buffer descriptor with a defined maximum length containing 
   206         the full name of this reference counting object.
   207 */
   208 EXPORT_C TFullName CObject::FullName() const
   209 	{
   210 
   211 	TFullName n;
   212 	makeFullName(n,Owner(),Name());
   213 	return(n);
   214 	}
   215 
   216 
   217 
   218 
   219 /**
   220 Sets or clears this reference counting object's name.
   221 
   222 To set the name, the specified descriptor must contain the name to be set. 
   223 Once the name has been successfully set, then the specified source descriptor 
   224 can be discarded.
   225 
   226 To clear an existing name, specify a NULL argument.
   227 
   228 @param aName A pointer to the descriptor containing the name to be set, or 
   229              NULL if an existing name is to be cleared.
   230 
   231 @return KErrNone, if the function is successful;
   232         KerrNoMemory, if there is insufficient memory available.
   233 
   234 @panic USER 11 if the length of aName is greater than KMaxName
   235        for a 16-bit descriptor.
   236 @panic USER 23 if the length of aName is greater than KMaxName
   237        for an 8-bit descriptor.
   238 */
   239 EXPORT_C TInt CObject::SetName(const TDesC *aName)
   240 	{
   241 
   242 	User::Free(iName);
   243 	iName=NULL;
   244 	if (aName!=NULL)
   245 		{
   246 		iName=aName->Alloc();
   247 		if (iName==NULL)
   248 			return(KErrNoMemory);
   249 		}
   250 	return(KErrNone);
   251 	}
   252 
   253 
   254 
   255 
   256 /**
   257 Sets or clears this reference counting object's name, and leaves on error.
   258 
   259 To set the name, the specified descriptor must contain the name to be set. 
   260 Once the name has been successfully set, then the specified source descriptor 
   261 can be discarded.
   262 
   263 To clear an existing name, specify a NULL argument.
   264 
   265 The function leaves if there is insufficient memory.
   266 
   267 @param aName A pointer to the descriptor containing the name to be set, or 
   268              NULL if an existing name is to be cleared.
   269 
   270 @panic USER 11 if the length of aName is greater than KMaxName
   271        for a 16-bit descriptor.
   272 @panic USER 23 if the length of aName is greater than KMaxName
   273        for an 8-bit descriptor.
   274 */
   275 EXPORT_C void CObject::SetNameL(const TDesC *aName)
   276 	{
   277 
   278 	User::Free(iName);
   279 	iName=NULL;
   280 	if (aName!=NULL)
   281 		iName=aName->AllocL();
   282 	}
   283 
   284 
   285 
   286 
   287 /**
   288 Extension function
   289 
   290 
   291 */
   292 EXPORT_C TInt CObject::Extension_(TUint aExtensionId, TAny*& a0, TAny* a1)
   293 	{
   294 	return CBase::Extension_(aExtensionId, a0, a1);
   295 	}
   296 
   297 
   298 
   299 
   300 /**
   301 Creates a new object index.
   302 
   303 @return A pointer to the newly created object index.
   304 */
   305 EXPORT_C CObjectIx* CObjectIx::NewL()
   306 	{
   307 
   308 	return new(ELeave) CObjectIx;
   309 	}
   310 
   311 
   312 
   313 
   314 /**
   315 Default constructor.
   316 */
   317 EXPORT_C CObjectIx::CObjectIx()
   318 	: iNextInstance(1), iFree(-1)
   319 	{
   320 	}
   321 
   322 
   323 
   324 
   325 /**
   326 Destructor.
   327 
   328 Frees all resources owned by the object index, prior to its destruction.
   329 In particular, it calls Close() on all reference counting objects in the index.
   330 
   331 @see CObject::Close
   332 */
   333 EXPORT_C CObjectIx::~CObjectIx()
   334 	{
   335 	// We have to be very careful here. Calling Close() on the objects in the array
   336 	// may result in other entries being removed from the array before we delete
   337 	// them here, and may result in the array being ReAlloc()ed, corrupting the removed
   338 	// entries, hence we must check the iHighWaterMark value each time round the loop.
   339 	TInt i=-1;
   340 	while(++i<iHighWaterMark)
   341 		{
   342 		SObjectIxRec* pS=iObjects+i;
   343 		CObject *pO=pS->obj;
   344 		if (pO)
   345 			{
   346 			pO->Close();
   347 			pS->obj=NULL;	// invalidate entry after closing it
   348 			}
   349 		}
   350 	delete iObjects;
   351 	}
   352 
   353 
   354 
   355 /**
   356 Adds the specified reference counting object into this object index and
   357 returns the handle number that represents it.
   358 
   359 @param anObj The reference counting object to be added to this object index.
   360 
   361 @return The handle number.
   362 */
   363 EXPORT_C TInt CObjectIx::AddL(CObject* anObj)
   364 	{
   365 	TInt index=iFree; //iFree contains the index of the first empty slot or -1 if there is no such.
   366 	if (index<0) //Check if the free list is empty
   367 		{
   368 		// The free list is empty, so more slots must be allocated.
   369 		if (iHighWaterMark==KObjectIxMaxHandles)
   370  			User::LeaveNoMemory();
   371 		
   372 		//Those are internal checking of the object consistency
   373 		__ASSERT_DEBUG(iAllocated==iHighWaterMark,Panic(EObjInconsistent));
   374 		__ASSERT_DEBUG(iAllocated==iNumEntries,Panic(EObjInconsistent));
   375 		
   376 		//Double allocated memory
   377 		TInt newAlloc=iAllocated ? 2*iAllocated : KObjectIxGranularity;
   378 		if(newAlloc>KObjectIxMaxHandles)
   379  			newAlloc=KObjectIxMaxHandles;
   380 		SObjectIxRec* pA=(SObjectIxRec*)User::ReAllocL(iObjects, newAlloc*sizeof(SObjectIxRec));
   381 		iObjects=pA;
   382 
   383 		//NOTE: There is no need to initialize newly allocated memory (e.g. to zero iObjects) as it all goes
   384 		//beyond HWM and will be not considered when search in At(...) or operator[]() methods. 
   385 		//As the free list is initially ordered, each slot must go to the states as follows:
   386 		//-Created as the part of the free list beyond HWM. - uninitialized and not searched in any method.
   387 		//-In use  - initialized.
   388 		//-The part of the free list within HWM - initialized to zero.
   389 		//Also, UpdateState() does not reorder free list beyond HWM but keep it preserverd.
   390 
   391 		iAllocated=newAlloc;					//Update the number of allocated slots
   392 		iUpdateDisabled = iAllocated/2;//The number of Remove() calls before the object update (free list, HWM,...)
   393 
   394 		//Connect all newly allocated slots into the list and set 'index' to point to the first one.
   395 		index=newAlloc-1;
   396 		pA[index].nextEmpty = -1;
   397 		while (iHighWaterMark <= --index) 
   398 			pA[index].nextEmpty=index+1;
   399 		index++;
   400 		}
   401 
   402 	//At this point, 'index' variable points to the slot that will be used for the new entry.
   403 	//It also represents the first element in the list of empty slots.
   404 
   405 	SObjectIxRec *pS=iObjects+index; // pS points to the object that will be used for the new entry.
   406 	iFree=pS->nextEmpty;			 // Update iFree to point to the next empty slot. 
   407 	
   408 	//Initialize data of the new element of the array.
   409 	pS->obj=anObj;
   410 	pS->str.uniqueID=(TUint16)anObj->UniqueID();
   411 	pS->str.instance=(TUint16)instanceLimit(iNextInstance);
   412 	
   413 	iNextInstance++;
   414 	
   415 	if (index>=iHighWaterMark)	//Update HWM to points to the slot after the last in use.
   416 		iHighWaterMark=index+1;
   417 	
   418 	++iNumEntries;
   419 
   420 	__ASSERT_DEBUG( (iFree==-1 && iAllocated==iHighWaterMark && iAllocated==iNumEntries)
   421 				  ||(iFree!=-1 && iAllocated>iNumEntries),Panic(EObjInconsistent));
   422 	
   423 	return(makeHandle(index,pS->str.instance)); //Create and return the handle
   424 	}
   425 
   426 
   427 
   428 
   429 /**
   430 Removes the reference counting object identified by handle number from this 
   431 object index and closes it.
   432 
   433 If the reference counting object cannot be closed, because CObjectIx::ENoClose 
   434 is ORed into the handle number, then it is neither removed from the object 
   435 index nor closed.
   436 
   437 @param aHandle The handle number of the reference counting object to be removed 
   438                and closed.
   439                
   440 @panic E32USER-CBase 37 if aHandle does not represent an object known to this
   441                         object index.
   442 */
   443 EXPORT_C void CObjectIx::Remove(TInt aHandle)
   444 	{
   445 	if (aHandle&ENoClose)
   446 		return;
   447 	TInt i=index(aHandle);
   448 	__ASSERT_ALWAYS(i<iHighWaterMark,Panic(EObjRemoveBadHandle));
   449 	SObjectIxRec* pR=iObjects+i;
   450 	CObject *pO=pR->obj;
   451 	if (!pO || pR->str.instance!=instance(aHandle) || pR->str.uniqueID!=pO->UniqueID())
   452 		Panic(EObjRemoveBadHandle);
   453 	pO->Close();
   454 	pR->obj=NULL;
   455 
   456 	if(--iNumEntries)
   457 		{	
   458 		// Add the entry onto the free list
   459 		pR->nextEmpty=iFree;
   460 		iFree=i;
   461 
   462 		if(iUpdateDisabled) 
   463 			iUpdateDisabled--; //Count down till state update is enabled again.
   464 
   465 		if (									 //Update the states(HWM, resort free list & memory shrink) if:
   466 			(!iUpdateDisabled) &&				 //There were a number of Remove() calls since the last ReAlloc
   467 			(iAllocated>=2*KObjectIxGranularity))//Allocated memory is above the limit.
   468 			{
   469 			UpdateState();
   470 			iUpdateDisabled = iAllocated/2;//The number of Remove() calls before the next update comes.
   471 			}
   472 		}
   473 	else
   474 		{
   475 		//There is no any CObject left. Reset the object to initial state (except iNextInstance)
   476 		delete iObjects;
   477 		iObjects=NULL;
   478 		iAllocated=0;
   479 		iHighWaterMark=0;
   480 		iFree=-1;		  //Empty free list
   481 		}
   482 
   483 	//This is internal checking of the object consistency
   484 	__ASSERT_DEBUG( (iFree==-1 && iAllocated==iHighWaterMark && iAllocated==iNumEntries)
   485 				  ||(iFree!=-1 && iAllocated>iNumEntries),Panic(EObjInconsistent));
   486 	}
   487 
   488 
   489 //1. Reorder free list.
   490 //2. Update iHighWaterMark. This is the only place where HWM is decreased, while it can be increased during AddL().
   491 //3. Shrinks the heap memory (pointed by iObjects) if it can be at least halved.
   492 //The function is entered with at least one occupied slot in iObjects array.
   493 //The array is searched from its end. Special care is given to the  case where
   494 //HWM is less then KObjectIxGranularity as the size of the arrey does not go below it.
   495 void CObjectIx::UpdateState()
   496 	{
   497 	TBool toShrink = EFalse;
   498 	TBool foundFreeBelowLimit = EFalse;//Used to handle spacial case when HWM is below the minimum alloc. limit
   499 	TInt newHWM = 0;
   500 
   501 	//Start from the HWM as all slots beyond are free and sorted already.
   502 	TInt current = iHighWaterMark;
   503 	TInt prevFreeSlot = iHighWaterMark == iAllocated ? -1 : iHighWaterMark;
   504 	while (--current>=0)
   505 		{
   506 		if (iObjects[current].obj)
   507 			{
   508 			//This is the slot with the valid entry. Check if this is the last in the array.
   509 			if(!newHWM)
   510 				{
   511 				//This is the first occupied slot we found => It is new HWM.
   512 				newHWM=current+1;
   513 				if (current < iAllocated/2)
   514 					{
   515 					//At this point we decide to shrink memory.
   516 					toShrink = ETrue;
   517 					//Once we find HWM and decide to shrink, all slots after that point should be removed
   518 					//from the free list as that memory will be freed. The exception is the case when HWM is below
   519 					//the minimum of allocated memory (8 slots as the moment).
   520 					if((current >= KObjectIxGranularity) || (!foundFreeBelowLimit))
   521 						prevFreeSlot = -1; //The next free slot to find will be the last one in the list.
   522 					}
   523 				}
   524 			}
   525 		else
   526 			{
   527 			//This is the free slot.
   528 			if ((!newHWM) && (!foundFreeBelowLimit) &&(current<KObjectIxGranularity))
   529 				{
   530 				//The special case. 
   531 				//We just reached the first free slot below minimum alloc. size and still we found no occupied slots.
   532 				iObjects[current].nextEmpty = -1; //This will be the end of free list.
   533 				foundFreeBelowLimit = ETrue; //Mark that we found the special case
   534 				}
   535 			else
   536 				{
   537 				iObjects[current].nextEmpty = prevFreeSlot;//Link the empty slot in the free list.
   538 				}
   539 			prevFreeSlot = current;
   540 			}
   541 		}
   542 
   543 	iHighWaterMark = newHWM;
   544 	iFree = prevFreeSlot;
   545 
   546 	if (toShrink)
   547 		{
   548 		//Do not reallocate less then the initial value.
   549 		iAllocated = Max(newHWM,KObjectIxGranularity);
   550 		//Update member data and re-allocate memory. ReAlloc cannot return NULL as we are asking for less memory.
   551 		iObjects=(SObjectIxRec*)User::ReAlloc(iObjects,iAllocated*sizeof(SObjectIxRec));
   552 		}
   553 	}
   554 
   555 
   556 
   557 /**
   558 Gets the number of occurrences of the specified reference counting object
   559 within this object index.
   560 
   561 Note that the same reference counting object can be added to an object index 
   562 more than once.
   563 
   564 @param anObject The reference counting object.
   565 
   566 @return The number of occurrences.
   567 */
   568 EXPORT_C TInt CObjectIx::Count(CObject* anObject) const
   569 	{
   570 
   571 	TInt n=0;
   572 	if (iHighWaterMark)
   573 		{
   574 		SObjectIxRec* pS=iObjects;
   575 		SObjectIxRec* pE=pS+iHighWaterMark;
   576 		do
   577 			{
   578 			if (pS->obj==anObject)
   579 				n++;
   580 			} while (++pS<pE);
   581 		}
   582 	return n;
   583 	}
   584 
   585 
   586 
   587 
   588 #ifndef __COBJECT_MACHINE_CODED__
   589 /**
   590 Gets a pointer to the reference counting object with the specified handle
   591 number and matching unique ID.
   592 
   593 @param aHandle   The handle number of the reference counting object.
   594 @param aUniqueID The unique ID.
   595 
   596 @return A pointer to the reference counting object. If there is no matching 
   597         object, then this is NULL.
   598 */
   599 EXPORT_C CObject *CObjectIx::At(TInt aHandle,TInt aUniqueID)
   600 	{
   601 	TInt i=index(aHandle);
   602 	if (i>=iHighWaterMark)
   603 		return NULL;
   604 	SObjectIxRec *pS=iObjects+i;
   605 	if (pS->str.instance!=instance(aHandle) || pS->str.uniqueID!=aUniqueID)
   606 		return NULL;
   607 	return pS->obj;
   608 	}
   609 
   610 
   611 
   612 
   613 /**
   614 Gets a pointer to the reference counting object with the specified
   615 handle number.
   616 
   617 @param aHandle The handle number of the reference counting object.
   618 
   619 @return A pointer to the reference counting object. If there is no matching 
   620         object, then this is NULL.
   621 */
   622 EXPORT_C CObject *CObjectIx::At(TInt aHandle)
   623 	{
   624 	TInt i=index(aHandle);
   625 	if (i>=iHighWaterMark)
   626 		return NULL;
   627 	SObjectIxRec *pS=iObjects+i;
   628 	if (pS->str.instance!=instance(aHandle))
   629 		return NULL;
   630 	return pS->obj;
   631 	}
   632 #endif
   633 
   634 
   635 
   636 
   637 
   638 /**
   639 Constructs and returns the handle number representing the specified reference 
   640 counting object within this object index.
   641 	
   642 @param anObj The reference counting object.
   643 
   644 @return The handle number representing the reference counting object;
   645         KErrNotFound, if the reference counting object could not be found
   646         within the object index.
   647 */
   648 EXPORT_C TInt CObjectIx::At(const CObject* anObj) const
   649 	{
   650 
   651 	if (iHighWaterMark)
   652 		{
   653 		SObjectIxRec* pS=iObjects;
   654 		SObjectIxRec* pE=pS+iHighWaterMark;
   655 		TInt i=0;
   656 		while(pS<pE && pS->obj!=anObj)
   657 			pS++, i++;
   658 		if (pS<pE)
   659 			return(makeHandle(i,pS->str.instance));
   660 		}
   661 	return KErrNotFound;
   662 	}
   663 
   664 
   665 
   666 
   667 /**
   668 Gets a pointer to the reference counting object with the specified handle
   669 number and matching unique ID.
   670 
   671 @param aHandle   The handle number of the reference counting object.
   672 @param aUniqueID The unique ID.
   673 
   674 @return A pointer to the reference counting object.
   675 
   676 @leave KErrBadHandle if there is no matching object.
   677 */
   678 EXPORT_C CObject *CObjectIx::AtL(TInt aHandle,TInt aUniqueID)
   679 	{
   680 
   681 	CObject* pO=At(aHandle,aUniqueID);
   682 	if (!pO)
   683 		User::Leave(KErrBadHandle);
   684 	return pO;
   685 	}
   686 
   687 
   688 
   689 
   690 /**
   691 Gets a pointer to the reference counting object with the specified handle
   692 number.
   693 
   694 @param aHandle The handle number of the reference counting object.
   695 
   696 @return A pointer to the reference counting object.
   697 
   698 @leave KErrBadHandle if there is no matching object.
   699 */
   700 EXPORT_C CObject *CObjectIx::AtL(TInt aHandle)
   701 	{
   702 
   703 	CObject* pO=At(aHandle);
   704 	if (!pO)
   705 		User::Leave(KErrBadHandle);
   706 	return pO;
   707 	}
   708 
   709 
   710 
   711 
   712 #ifndef __COBJECT_MACHINE_CODED__
   713 /**
   714 Gets a pointer to a reference counting object located at the specified offset 
   715 within the object index.
   716 
   717 @param anIndex The offset of the reference counting object within the object 
   718                index. Offset is relative to zero. 
   719                
   720 @return A pointer to the reference counting object.
   721 
   722 @panic E32USER-CBase 21 if the value of anIndex is negative or is greater than
   723                         or equal to the total number of objects held by
   724                         the index.
   725 */
   726 EXPORT_C CObject* CObjectIx::operator[](TInt anIndex)
   727 	{
   728 
   729 	__ASSERT_ALWAYS(anIndex>=0 && anIndex<iHighWaterMark,Panic(EArrayIndexOutOfRange));
   730 	return iObjects[anIndex].obj;
   731 	}
   732 #else
   733 GLDEF_C void PanicCObjectIxIndexOutOfRange(void)
   734 	{
   735 	Panic(EArrayIndexOutOfRange);
   736 	}
   737 #endif
   738 
   739 
   740 
   741 
   742 /**
   743 Creates an object container.
   744 
   745 Open code rarely, if ever, explicitly calls this function. Instead, call the 
   746 CreateL() member function of the container index, CObjectConIx, which uses 
   747 this function in its implementation.
   748 
   749 @return A pointer to the new object container.
   750 
   751 @see CObjectConIx::CreateL
   752 */
   753 EXPORT_C CObjectCon* CObjectCon::NewL()
   754 	{
   755 
   756 	return new(ELeave) CObjectCon(ENotOwnerID);
   757 	}
   758 
   759 
   760 
   761 
   762 /**
   763 Constructor taking a unique Id. 
   764 
   765 @param aUniqueID The unique Id value.
   766 */
   767 EXPORT_C CObjectCon::CObjectCon(TInt aUniqueID)
   768 	: iUniqueID(aUniqueID)
   769 	{
   770 //	iAllocated=0;
   771 //	iCount=0;
   772 //	iObjects=NULL;
   773 	}
   774 
   775 
   776 
   777 
   778 /**
   779 Destructor.
   780 
   781 Frees all resources owned by the object container, prior to its destruction.
   782 
   783 In particular, it destroys all contained reference counting objects.
   784 
   785 @see CObject
   786 */
   787 EXPORT_C CObjectCon::~CObjectCon()
   788 	{
   789 
   790 	if (iUniqueID!=ENotOwnerID && iCount)
   791 		{
   792 		// Careful here in case deleting one object causes other objects in the array
   793 		// to be removed and Count to change.
   794 		TInt i=-1;
   795 		while(++i<iCount)
   796 			{
   797 			CObject* pS=iObjects[i];
   798 			delete pS;
   799 			}
   800 		}
   801 	delete iObjects;
   802 	}
   803 
   804 
   805 
   806 
   807 /**
   808 Adds a reference counting object to this object container.
   809 
   810 If the specified reference counting object has a name, it must be valid,
   811 otherwise the function leaves with KErrBadName; in addition, the reference
   812 counting object's full name must be unique to this object container, otherwise
   813 the function leaves with KErrAlreadyExists.
   814 
   815 If the specified reference counting object has no name, then the object itself 
   816 must be unique to the object container, i.e. the object container should not 
   817 already contain the same reference counting object, otherwise the function 
   818 leaves with KErrAlreadyExists.
   819 
   820 @param anObj A pointer to the reference counting object to be added.
   821 */
   822 EXPORT_C void CObjectCon::AddL(CObject* anObj)
   823 	{
   824 
   825 	User::LeaveIfError(CheckUniqueFullName(anObj));
   826 	if (iCount==iAllocated)
   827 		{
   828 		TInt newAlloc;
   829 		if (iAllocated==0)
   830 			newAlloc = KObjectConMinSize;
   831 		else
   832 			{
   833 			// increase in sequence 8, 12, 16, 24, ... , 2^n, 3*2^n-1, ...
   834 			// can't get sign problems since iAllocated can't exceed 0x20000000
   835 			newAlloc = iAllocated + (iAllocated>>1) - ((iAllocated&(iAllocated-1))>>2);
   836 			}
   837 		iObjects=(CObject**)User::ReAllocL(iObjects, newAlloc*sizeof(CObject*));
   838 		iAllocated=newAlloc;
   839 		}
   840 	iObjects[iCount++]=anObj;
   841 	if (iUniqueID!=ENotOwnerID)
   842 		anObj->iContainer=this;
   843 	}
   844 
   845 
   846 
   847 
   848 /**
   849 Removes a reference counting object from this object container.
   850 
   851 The specified reference counting object is destroyed on removal.
   852 
   853 @param anObj A pointer to the reference counting object to be removed.
   854 
   855 @panic E32USER-CBase 35 if the reference counting object is not held by this
   856                         object container.
   857 */
   858 EXPORT_C void CObjectCon::Remove(CObject *anObj)
   859 	{
   860 	CObject** pS=iObjects;
   861 	CObject** pE=pS+iCount;
   862 	while(pS<pE)
   863 		{
   864 		if (*pS==anObj)
   865 			{
   866 			Mem::Move((TAny*)pS,(TAny*)(pS+1),TInt(pE)-TInt(pS)-sizeof(CObject*));
   867 			TInt used = --iCount;
   868 			if (used)	// if now empty, free all memory
   869 				{
   870 				if (iAllocated > KObjectConMinSize)	// don't shrink below minimum size
   871 					{
   872 					// calculate next size down
   873 					TInt newAlloc = iAllocated - (iAllocated>>2) - ((iAllocated&(iAllocated-1))>>3);
   874 
   875 					// shrink if half full or 64 less than next size down, whichever comes first
   876 					if (used <= Max(iAllocated>>1, newAlloc-64))
   877 						{
   878 						iObjects=(CObject**)User::ReAlloc(iObjects,newAlloc*sizeof(CObject*));
   879 						iAllocated=newAlloc;
   880 						}
   881 					}
   882 				}
   883 			else
   884 				{
   885 				delete iObjects;
   886 				iObjects=NULL;
   887 				iAllocated=0;
   888 				}
   889 			if (iUniqueID!=ENotOwnerID && anObj->iContainer)
   890 				{
   891 //
   892 // An object's destructor can scan the container so its best
   893 // to remove the object from the container before destroying it.
   894 //
   895 				anObj->iContainer=NULL;
   896 				delete anObj;
   897 				}
   898 			return;
   899 			}
   900 		pS++;
   901 		}
   902 	Panic(EObjRemoveObjectNotFound);
   903 	}
   904 
   905 
   906 
   907 
   908 #ifndef __COBJECT_MACHINE_CODED__
   909 /**
   910 Gets a pointer to the reference counting object located at the specified offset 
   911 within the object container.
   912 
   913 @param anIndex The offset of the reference counting object within the object 
   914                container. Offset is relative to zero.
   915 
   916 @return A pointer to the owning reference counting object.
   917 
   918 @panic E32USER-CBase 21 if anIndex is negative or is greater than or equal to
   919                         the total number of objects held by the container.
   920 */
   921 EXPORT_C CObject *CObjectCon::operator[](TInt anIndex)
   922 	{
   923 	__ASSERT_ALWAYS(anIndex>=0 && anIndex<iCount, Panic(EArrayIndexOutOfRange));
   924 	return iObjects[anIndex];
   925 	}
   926 
   927 
   928 
   929 
   930 /**
   931 Gets a pointer to the reference counting object with the specified find-handle 
   932 number.
   933 
   934 A find-handle number is an integer which uniquely identifies a reference
   935 counting object with respect to its object container.
   936 
   937 @param aFindHandle The find-handle number of the reference counting object. 
   938                    The unique Id part of this number must be the same as the
   939                    unique Id of this container.
   940                    The index part of the find-handle number must be
   941                    a valid index. 
   942 
   943 @return A pointer to the reference counting object.
   944 
   945 @panic E32User-CBase 38 if the unique Id part of aFindHandle is not the same as
   946                         the unique Id of this container.
   947 @panic E32User-CBase 39 if the index part of aFindHandle is negative or greater
   948                         than or equal to the total number of reference counting
   949                         objects held by this object container.
   950 */
   951 EXPORT_C CObject *CObjectCon::At(TInt aFindHandle) const
   952 	{
   953 
   954 	__ASSERT_ALWAYS(uniqueID(aFindHandle)==iUniqueID,Panic(EObjFindBadHandle));
   955 	TInt ix=index(aFindHandle);
   956 	__ASSERT_ALWAYS(ix<iCount,Panic(EObjFindIndexOutOfRange));
   957 	return iObjects[ix];
   958 	}
   959 
   960 
   961 
   962 
   963 /**
   964 Gets a pointer to the reference counting object with the specified find-handle 
   965 number, and leaves on error..
   966 
   967 A find-handle number is an integer which uniquely identifies a reference
   968 counting object with respect to its object container.
   969 
   970 @param aFindHandle The find-handle number of the reference counting object. 
   971                    The unique Id part of this number must be the same as
   972                    the unique Id of this container.
   973                    The index part of the find-handle number must be
   974                    a valid index. 
   975 
   976 @return A pointer to the reference counting object.
   977 
   978 @leave KErrBadHandle if the unique Id part of aFindHandle is not the same as
   979                      the unique Id of this container.
   980 @leave KErrArgument if the index part of aFindHandle is negative or greater
   981                     than or equal to the total number of reference counting
   982                     objects held by this object container.
   983 */
   984 EXPORT_C CObject *CObjectCon::AtL(TInt aFindHandle) const
   985 	{
   986 
   987 	__ASSERT_ALWAYS(uniqueID(aFindHandle)==iUniqueID,User::Leave(KErrBadHandle));
   988 	TInt ix=index(aFindHandle);
   989 	__ASSERT_ALWAYS(ix<iCount,User::Leave(KErrArgument));
   990 	return iObjects[ix];
   991 	}
   992 #else
   993 GLDEF_C void PanicCObjectConFindBadHandle(void)
   994 	{
   995 	Panic(EObjFindBadHandle);
   996 	}
   997 
   998 
   999 
  1000 
  1001 
  1002 GLDEF_C void PanicCObjectConFindIndexOutOfRange(void)
  1003 	{
  1004 	Panic(EObjFindIndexOutOfRange);
  1005 	}
  1006 
  1007 GLDEF_C void PanicCObjectConIndexOutOfRange(void)
  1008 	{
  1009 	Panic(EArrayIndexOutOfRange);
  1010 	}
  1011 #endif
  1012 
  1013 
  1014 
  1015 
  1016 /**
  1017 Checks whether a specified name is a valid CObject name.
  1018 
  1019 A name is deemed to be invalid, if it contains any of the characters:
  1020 "*", "?", ":" i.e. the characters: asterisk, question mark and single colon.
  1021 
  1022 @param aName A reference to the descriptor containing the name to be checked.
  1023 
  1024 @return KErrBadName, if the name is invalid. KErrNone, otherwise.
  1025 
  1026 @see CObject
  1027 */
  1028 EXPORT_C TInt User::ValidateName(const TDesC &aName)
  1029 	{
  1030 #ifdef _UNICODE
  1031 	TUint16* pName = const_cast<TUint16*>(aName.Ptr());
  1032 #else
  1033 	TUint8*	pName = const_cast<TUint8*>(aName.Ptr());
  1034 #endif
  1035 	TInt pNameLen = aName.Length();
  1036 	for(;pNameLen;pName++,pNameLen--)
  1037 		if(*pName>0x7e || *pName<0x20 || *pName=='*' || *pName=='?' || *pName==':')
  1038 			return(KErrBadName);
  1039 	return(KErrNone);
  1040 	}
  1041 
  1042 
  1043 
  1044 
  1045 /**
  1046 Checks that a name will be unique.
  1047 
  1048 The function checks that no reference counting object exists in this object
  1049 container with the same full name as that generated from the specified name
  1050 and the specified owning reference counting object.
  1051 
  1052 This is a useful test to ensure that the name for a potential new reference
  1053 counting object will result in a unique full name.
  1054 
  1055 @param anOwner A pointer to a potential owning reference counting object.
  1056 @param aName   The name for a potential new reference counting object.
  1057 
  1058 @return KErrNone, if the full name does not already exist in this
  1059         object container;
  1060         KErrBadName, if the specified name is invalid;
  1061         KErrAlreadyExists, if a reference counting object with the same
  1062         fullname as the generated one already exists in this object container.
  1063 */
  1064 EXPORT_C TInt CObjectCon::CheckUniqueFullName(const CObject *anOwner,const TDesC &aName) const
  1065 	{
  1066 
  1067 	TInt r=User::ValidateName(aName);
  1068 	if (r==KErrNone)
  1069 		{
  1070 		TFullName n;
  1071 		makeFullName(n,anOwner,aName);
  1072 		TFullName res;
  1073 		TInt h=0;
  1074 		if (FindByFullName(h,n,res)==KErrNone)
  1075 			r=KErrAlreadyExists;
  1076 		}
  1077 	return(r);
  1078 	}
  1079 
  1080 
  1081 
  1082 
  1083 /**
  1084 @internalComponent
  1085 
  1086 protected recursive function for use by CheckUniqueFullName
  1087 */
  1088 TBool CObjectCon::NamesMatch(const CObject* anObject, const CObject* aCurrentObject) const
  1089 	{
  1090 
  1091 	if (aCurrentObject->iName==NULL) // current object has no name, therefore not the same
  1092 		return(EFalse);
  1093 	if ((anObject->Name()).Compare(aCurrentObject->Name())!=0) // short names are different, therefore not the same
  1094 		return(EFalse);
  1095 	if ((aCurrentObject->Owner()==NULL)&&(anObject->Owner()==NULL)) // same short name, no owners = same
  1096 		return (ETrue);
  1097 	if ((aCurrentObject->Owner()==NULL)||(anObject->Owner()==NULL)) // one has no owner, therefore not the same
  1098 		return(EFalse);
  1099 	return(NamesMatch(anObject->Owner(),aCurrentObject->Owner())); // go recursive
  1100 	}
  1101 
  1102 /**
  1103 @internalComponent
  1104 
  1105 protected recursive function for use by CheckUniqueFullName
  1106 */
  1107 TBool CObjectCon::NamesMatch(const CObject* anObject, const TName& anObjectName, const CObject* aCurrentObject) const
  1108 	{
  1109 
  1110 	if (aCurrentObject->iName==NULL) // current object has no name, therefore not the same
  1111 		return(EFalse);
  1112 	if (anObjectName.Compare(aCurrentObject->Name())!=0) // short names are different, therefore not the same
  1113 		return(EFalse);
  1114 	if ((aCurrentObject->Owner()==NULL)&&(anObject->Owner()==NULL)) // same short name, no owners = same
  1115 		return (ETrue);
  1116 	if ((aCurrentObject->Owner()==NULL)||(anObject->Owner()==NULL)) // one has no owner, therefore not the same
  1117 		return(EFalse);
  1118 	return(NamesMatch(anObject->Owner(),aCurrentObject->Owner())); // go recursive
  1119 	}
  1120 
  1121 
  1122 
  1123 
  1124 /**
  1125 Checks that the specified reference counting object does not already exist in 
  1126 this object container.
  1127 
  1128 Uniqueness is decided by name, if the object has a name, otherwise by pointer.
  1129 
  1130 If the reference counting object has a name, then it is unique only if there 
  1131 is no other reference counting object in the container with the same full 
  1132 name.
  1133 
  1134 If the reference counting object has no name, then it is unique only if there 
  1135 is no other reference counting object in the container with the same pointer.
  1136 
  1137 @param anObject A pointer to the reference counting object to be checked.
  1138 
  1139 @return KErrNone, if the reference counting object does not already exist in 
  1140         this object container;
  1141         KErrBadName, if the name of the reference counting 
  1142         object is invalid;
  1143         KErrAlreadyExists, if the reference counting object already exists.
  1144 */
  1145 EXPORT_C TInt CObjectCon::CheckUniqueFullName(const CObject* anObject) const
  1146 	{
  1147 
  1148 	TName name(anObject->Name());
  1149 	TInt r=User::ValidateName(name);
  1150 	if (r!=KErrNone)
  1151 		return r;
  1152 
  1153 	if (!iCount)
  1154 		return KErrNone;
  1155 
  1156 	CObject** pS=iObjects;
  1157 	CObject** pE=pS+iCount;
  1158 
  1159 	// if it's name is null, just need to check it's not already there
  1160 	if (!anObject->iName)
  1161 		{
  1162 		do
  1163 			{
  1164 			if (*pS==anObject)
  1165 				return KErrAlreadyExists;
  1166 			} while(++pS<pE);
  1167 		return KErrNone;
  1168 		}
  1169 
  1170 	do
  1171 		{
  1172 		if (NamesMatch(anObject,name,*pS))
  1173 			return KErrAlreadyExists;
  1174 		} while(++pS<pE);
  1175 	return KErrNone;
  1176 	}
  1177 
  1178 
  1179 
  1180 
  1181 /**
  1182 Searches for the reference counting object whose name matches the specified 
  1183 match pattern.
  1184 
  1185 The search starts at the reference counting object following the one associated 
  1186 with the specified find-handle number. If the specified find-handle number 
  1187 is zero, then searching starts at the beginning of the object container.
  1188 
  1189 Notes:
  1190 
  1191 1. names are folded for the purpose of pattern matching
  1192 
  1193 2. if the specified find-handle number is non-zero, then the unique Id part of 
  1194    the number must be the same as the unique Id of this container.
  1195 
  1196 @param aFindHandle On entry, contains the find-handle number of a reference 
  1197                    counting object from where searching is to start, or zero.
  1198                    On return, if an object is found, then this is set to the
  1199                    find-handle number of that object; 
  1200                    if no object is found, then this is set to a generated
  1201                    number, the index part of which has the value 0x7fff.
  1202                    If the object container is empty, then this 
  1203                    reference is not changed.
  1204 @param aMatch      The match pattern.
  1205 @param aName       A modifiable buffer descriptor with a defined maximum 
  1206                    length. On return, if an object is found, then this
  1207                    contains the name of that object; if no object is found,
  1208                    then the length of this descriptor is set to zero. 
  1209                    If the object container is empty, then this reference is
  1210                    not changed.
  1211                    
  1212 @return KErrNone, if a matching reference counting object is found;
  1213         KErrNotFound, if no matching reference counting object can be found or
  1214         the object container is empty.
  1215 
  1216 @panic E32User-CBase 38 if aFindHandle is non-zero and the unique Id part of 
  1217                         it is not the same as the unique Id of this container.
  1218 */
  1219 EXPORT_C TInt CObjectCon::FindByName(TInt &aFindHandle,const TDesC &aMatch,TName &aName) const
  1220 	{
  1221 
  1222 	if (!iCount)
  1223 		return KErrNotFound;
  1224 	TInt ix=0;
  1225 	if (aFindHandle!=0)
  1226 		{
  1227 		__ASSERT_ALWAYS(uniqueID(aFindHandle)==iUniqueID,Panic(EObjFindBadHandle));
  1228 		ix=index(aFindHandle)+1;
  1229 		};
  1230 	CObject** pS=iObjects;
  1231 	CObject** pE=pS+iCount;
  1232 	pS+=ix;
  1233 	while(pS<pE)
  1234 		{
  1235 		aName=(*pS++)->Name();
  1236 		if (aName.MatchF(aMatch)!=KErrNotFound)
  1237 			{
  1238 			aFindHandle=makeFindHandle(ix,iUniqueID);
  1239 			return KErrNone;
  1240 			}
  1241 		ix++;
  1242 		}
  1243 	aName.Zero();
  1244 	aFindHandle=makeFindHandle(KObjectMaxIndex,iUniqueID);
  1245 	return KErrNotFound;
  1246 	}
  1247 
  1248 
  1249 
  1250 
  1251 /**
  1252 Searches for the reference counting object whose full name matches the
  1253 specified match pattern.
  1254 
  1255 The search starts at the reference counting object following the one associated 
  1256 with the specified find-handle number. If the specified find-handle number 
  1257 is zero, then searching starts at the beginning of the object container.
  1258 
  1259 Notes:
  1260 
  1261 1. names are folded for the purpose of pattern matching
  1262 
  1263 2. if the specified find-handle number is non-zero, then the unique Id part of 
  1264    the number must be the same as the unique Id of this container.
  1265 
  1266 @param aFindHandle On entry, contains the find-handle number of a reference 
  1267                    counting object from where searching is to start or zero.
  1268                    On return, if an object is found, then this is set to the
  1269                    find-handle number of that object; 
  1270                    if no object is found, then this is set to a generated
  1271                    number, the index part of which has the value 0x7fff.
  1272                    If the object container is empty, then this reference is
  1273                    not changed.
  1274 @param aMatch      The match pattern.
  1275 @param aFullName   A modifiable buffer descriptor with a defined maximum length. 
  1276                    On return, if an object is found, then this contains the
  1277                    full name of that object;
  1278                    if no object is found, then the length of this descriptor
  1279                    is set to zero.
  1280                    If the object container is empty, then this reference is not
  1281                    changed.
  1282                    
  1283 @return KErrNone, if a matching reference counting object is found;
  1284         KErrNotFound, if no matching reference counting object can be found or
  1285         the object container is empty.
  1286 
  1287 @panic E32User-CBase 38 if aFindHandle is non-zero and the unique Id part of 
  1288                         it is not the same as the unique Id of this container.
  1289 */
  1290 EXPORT_C TInt CObjectCon::FindByFullName(TInt &aFindHandle,const TDesC &aMatch,TFullName &aFullName) const
  1291 	{
  1292 
  1293 	if (!iCount)
  1294 		return KErrNotFound;
  1295 	TInt ix=0;
  1296 	if (aFindHandle!=0)
  1297 		{
  1298 		__ASSERT_ALWAYS(uniqueID(aFindHandle)==iUniqueID,Panic(EObjFindBadHandle));
  1299 		ix=index(aFindHandle)+1;
  1300 		};
  1301 	CObject** pS=iObjects;
  1302 	CObject** pE=pS+iCount;
  1303 	pS+=ix;
  1304 	while(pS<pE)
  1305 		{
  1306 		aFullName=(*pS++)->FullName();
  1307 		if (aFullName.MatchF(aMatch)!=KErrNotFound)
  1308 			{
  1309 			aFindHandle=makeFindHandle(ix,iUniqueID);
  1310 			return KErrNone;
  1311 			}
  1312 		ix++;
  1313 		}
  1314 	aFullName.Zero();
  1315 	aFindHandle=makeFindHandle(KObjectMaxIndex,UniqueID());
  1316 	return KErrNotFound;
  1317 	}
  1318 
  1319 
  1320 
  1321 
  1322 /**
  1323 Creates a new container index.
  1324 
  1325 @return A pointer to the newly created container index.
  1326 */
  1327 EXPORT_C CObjectConIx* CObjectConIx::NewL()
  1328 	{
  1329 
  1330 	return new(ELeave) CObjectConIx;
  1331 	}
  1332 
  1333 
  1334 
  1335 
  1336 /**
  1337 Default constructor.
  1338 */
  1339 EXPORT_C CObjectConIx::CObjectConIx()
  1340 	: iNextUniqueID(1)
  1341 	{
  1342 	}
  1343 
  1344 
  1345 
  1346 
  1347 /**
  1348 Destructor.
  1349 
  1350 Frees all resources owned by the container index, prior to its destruction.
  1351 
  1352 In particular, it destroys all of its contained object containers.
  1353 */
  1354 EXPORT_C CObjectConIx::~CObjectConIx()
  1355 	{
  1356 	if (iCount)
  1357 		{
  1358 		TInt i=-1;
  1359 		while(++i<iCount)
  1360 			{
  1361 			CObjectCon* pS=iContainers[i];
  1362 			delete pS;
  1363 			}
  1364 		}
  1365 	delete iContainers;
  1366 	}
  1367 
  1368 
  1369 
  1370 
  1371 /**
  1372 @internalComponent
  1373 
  1374 Actually create the container
  1375 */
  1376 EXPORT_C void CObjectConIx::CreateContainerL(CObjectCon*& aContainer)
  1377 	{
  1378 
  1379 	aContainer=CObjectCon::NewL();
  1380 	if (iUniqueIDHasWrapped)
  1381 		{
  1382 		// Must search for next free id
  1383 		while (LookupByUniqueId(iNextUniqueID) != NULL)
  1384 			{
  1385 			++iNextUniqueID;
  1386 			if (iNextUniqueID == 0)
  1387 				iNextUniqueID = 1;
  1388 			}
  1389 		}
  1390 	aContainer->iUniqueID=iNextUniqueID;
  1391 	if (iCount==iAllocated)
  1392 		{
  1393 		TInt newAlloc=iAllocated+KObjectConIxGranularity;
  1394 		iContainers=(CObjectCon**)User::ReAllocL(iContainers, newAlloc*sizeof(CObjectCon*));
  1395 		iAllocated=newAlloc;
  1396 		}
  1397 	iContainers[iCount++]=aContainer;
  1398 	}
  1399 
  1400 
  1401 
  1402 
  1403 /**
  1404 Creates a new object container and adds it into this container
  1405 index's collection.
  1406 
  1407 In addition to creating the object container, the function assigns
  1408 the next available unique ID to it.
  1409 
  1410 @return A pointer to the new object container.
  1411 */
  1412 EXPORT_C CObjectCon* CObjectConIx::CreateL()
  1413 	{
  1414 
  1415 	if (iCount == KObjectConIxMaxSize)
  1416 		User::Leave(KErrOverflow);
  1417 	CObjectCon* pC=NULL;
  1418 	TRAPD(r,CreateContainerL(pC))
  1419 	if (r!=KErrNone)
  1420 		{
  1421 		delete pC;
  1422 		User::Leave(r);
  1423 		}
  1424 	++iNextUniqueID;
  1425 	if (iNextUniqueID == 0)
  1426 		{
  1427 		iNextUniqueID = 1;
  1428 		iUniqueIDHasWrapped = 1;
  1429 		}
  1430 	return pC;
  1431 	}
  1432 
  1433 
  1434 
  1435 
  1436 /**
  1437 Removes the specified object container from this container index and
  1438 deletes it.
  1439 
  1440 @param aCon A pointer to the object container to be removed. If the pointer is NULL,
  1441             the function just returns.
  1442 
  1443 @panic E32USER-CBASE 36 if the object container cannnot be found.
  1444 */
  1445 EXPORT_C void CObjectConIx::Remove(CObjectCon* aCon)
  1446 	{
  1447 	if (!aCon)
  1448 		return;
  1449 	CObjectCon** pS=iContainers;
  1450 	CObjectCon** pE=pS+iCount;
  1451 	while(pS<pE)
  1452 		{
  1453 		if (*pS==aCon)
  1454 			{
  1455 			Mem::Move((TAny*)pS,(TAny*)(pS+1),TInt(pE)-TInt(pS)-sizeof(CObjectCon*));
  1456 			TInt newAlloc=--iCount;
  1457 			if (iCount == 0)
  1458 				iUniqueIDHasWrapped = 0;
  1459 			newAlloc=(newAlloc+(KObjectConIxGranularity-1))&~(KObjectConIxGranularity-1);
  1460 			if (newAlloc!=iAllocated)
  1461 				{
  1462 				if (newAlloc)
  1463 					iContainers=(CObjectCon**)User::ReAlloc(iContainers,newAlloc*sizeof(CObjectCon*));
  1464 				else
  1465 					{
  1466 					delete iContainers;
  1467 					iContainers=NULL;
  1468 					}
  1469 				iAllocated=newAlloc;
  1470 				}
  1471 			delete aCon;
  1472 			return;
  1473 			}
  1474 		pS++;
  1475 		}
  1476 	Panic(EObjRemoveContainerNotFound);
  1477 	}
  1478 
  1479 
  1480 
  1481 
  1482 /**
  1483 Gets a pointer to the object container with the specified unique ID, or NULL.
  1484 */
  1485 CObjectCon* CObjectConIx::LookupByUniqueId(TInt aUniqueId) const
  1486 	{
  1487 	
  1488 	CObjectCon** pS=iContainers;
  1489 	CObjectCon** pE=pS+iCount;
  1490 	while(pS<pE)
  1491 		{
  1492 		CObjectCon *pO=*pS++;
  1493 		if (pO->iUniqueID==aUniqueId)
  1494 			return pO;
  1495 		}
  1496 	return NULL;
  1497 	}
  1498 
  1499 
  1500 
  1501 
  1502 /**
  1503 Gets a pointer to the object container with the unique ID from the specified
  1504 find handle.
  1505 
  1506 @param aFindHandle The find handle.
  1507 
  1508 @return A pointer to the object container with a matching unique ID. If no 
  1509         matching object container can be found, then this is NULL.
  1510 */
  1511 EXPORT_C CObjectCon* CObjectConIx::Lookup(TInt aFindHandle) const
  1512 	{
  1513 
  1514 	return LookupByUniqueId(uniqueID(aFindHandle));
  1515 	}
  1516