bool CThreadLocalStorage::AllocateAndSetStorageValue(const HTLSKEYSELECTOR &hksKeySelector,
	tlsindextype iValueIndex, tlsvaluetype vValueData, CTLSValueDestructor fnValueDestructor)
{
	OU_ASSERT(OU_IN_SIZET_RANGE(DecodeInstanceKindFromKeySelector(hksKeySelector), SIK__MIN, SIK__MAX));

	bool bResult = false;
	
	do
	{
		ESTORAGEINSTANCEKIND ikInstanceKind = (ESTORAGEINSTANCEKIND)DecodeInstanceKindFromKeySelector(hksKeySelector);
		CTLSStorageInstance *psiStorageInstance = g_apsiStorageGlobalInstances[ikInstanceKind];

		CTLSStorageBlock *psbStorageBlock;

		if (!psiStorageInstance->FindFreeStorageBlock(psbStorageBlock))
		{
			break;
		}

		SetKeyStorageBlock(hksKeySelector, psbStorageBlock);

		psbStorageBlock->SetValueData(iValueIndex, vValueData);
		psbStorageBlock->SetValueDestructor(iValueIndex, fnValueDestructor);
	
		bResult = true;
	}
	while (false);
	
	return bResult;
}
bool CThreadLocalStorage::AllocateAndSetStorageValue(
	tlsindextype iValueIndex, tlsvaluetype vValueData, CTLSValueDestructor fnValueDestructor)
{
	bool bResult = false;
	
	do
	{
		CTLSStorageInstance *psiStorageInstance = g_psiStorageGlobalInstance;

		CTLSStorageBlock *psbStorageBlock;

		if (!psiStorageInstance->FindFreeStorageBlock(psbStorageBlock))
		{
			break;
		}

		const HTLSKEY &hskStorageKey = psiStorageInstance->RetrieveStorageKey();
		SetKeyStorageBlock(hskStorageKey, psbStorageBlock);

		psbStorageBlock->SetValueData(iValueIndex, vValueData);
		psbStorageBlock->SetValueDestructor(iValueIndex, fnValueDestructor);
	
		bResult = true;
	}
	while (false);
	
	return bResult;
}
bool CTLSInitialization::InitializeTLSAPIValidated(unsigned int uiInstanceKind, 
	tlsindextype iValueCount, unsigned int uiInitializationFlags)
{
	OU_ASSERT(g_apsiStorageGlobalInstances[uiInstanceKind] == NULL);

	bool bResult = false;
	
	CTLSStorageInstance *psiStorageInstance;

	do
	{
		// Use static methods instead of constructor/destructor 
		// to avoid overloading operators new/delete and for 
		// uniformity with CTLSStorageArray class
		psiStorageInstance = CTLSStorageInstance::AllocateInstance(iValueCount, uiInitializationFlags);
		
		if (!psiStorageInstance)
		{
			break;
		}

		if (!psiStorageInstance->Init((ESTORAGEINSTANCEKIND)uiInstanceKind))
		{
			break;
		}

		g_apsiStorageGlobalInstances[uiInstanceKind] = psiStorageInstance;
	
		bResult = true;
	}
	while (false);
	
	if (!bResult)
	{
		if (psiStorageInstance)
		{
			psiStorageInstance->FreeInstance();
		}
	}

	return bResult;
}
void CTLSInitialization::CleanupOnThreadExit()
{
	CTLSStorageInstance *psiStorageInstance = g_psiStorageGlobalInstance;

	if (psiStorageInstance->GetIsThreadManualCleanup())
	{
		const HTLSKEY &hskStorageKey = g_psiStorageGlobalInstance->RetrieveStorageKey();
		CTLSStorageBlock *psbStorageBlock = CThreadLocalStorage::GetKeyStorageBlock(hskStorageKey);
		
		if (psbStorageBlock)
		{
			psiStorageInstance->FreeStorageBlockOnThreadExit(psbStorageBlock);

			CThreadLocalStorage::SetKeyStorageBlock(hskStorageKey, NULL);
		}
	}
	else
	{
		OU_ASSERT(false); // The method is not supposed to be called if manual cleanup was not requested on initialization
	}
}
void CTLSInitialization::CleanupOnThreadExit()
{
	const ESTORAGEINSTANCEKIND ikInstanceKind = SIK_MANUALCLEANUP;
	CTLSStorageInstance *psiStorageInstance = g_apsiStorageGlobalInstances[ikInstanceKind];

	if (psiStorageInstance != NULL)
	{
		OU_ASSERT(psiStorageInstance->GetIsThreadManualCleanup());

		const HTLSKEYSELECTOR &hksKeySelector = EncodeKeySelectorFromStorageKind(ikInstanceKind);
		CTLSStorageBlock *psbStorageBlock = CThreadLocalStorage::GetKeyStorageBlock(hksKeySelector);
		
		if (psbStorageBlock)
		{
			psiStorageInstance->FreeStorageBlockOnThreadExit(psbStorageBlock);

			CThreadLocalStorage::SetKeyStorageBlock(hksKeySelector, NULL);
		}
	}
	else
	{
		OU_ASSERT(false); // The method is not supposed to be called if manual cleanup was not requested on initialization
	}
}