blob: 1742ab57e3ee48de88fb2b8e6938897728e326c0 [file] [log] [blame]
/*
*******************************************************************************
*
* Copyright (C) 2008-2013, International Business Machines
* Corporation and others. All Rights Reserved.
*
*******************************************************************************
* file name: mutex.cpp
* encoding: US-ASCII
* tab size: 8 (not used)
* indentation:4
*/
#include "unicode/utypes.h"
#include "mutex.h"
#include "uassert.h"
U_NAMESPACE_BEGIN
void *SimpleSingleton::getInstance(InstantiatorFn *instantiator, const void *context,
UErrorCode &errorCode) {
if(U_FAILURE(errorCode)) {
return NULL;
}
if (umtx_loadAcquire(fInitOnce.fState) == 2) {
return fInstance;
}
if (umtx_initImplPreInit(fInitOnce)) {
fInstance = instantiator(context, errorCode);
umtx_initImplPostInit(fInitOnce, fInstance != NULL);
}
return fInstance;
}
/*
* Three states:
*
* Initial state: Instance creation not attempted yet.
* fInstance=NULL && U_SUCCESS(fErrorCode)
*
* Instance creation run & succeeded:
* fInstance!=NULL && U_SUCCESS(fErrorCode)
*
* Instance creation & failed:
* fInstance=NULL && U_FAILURE(fErrorCode)
* We will not attempt again to create the instance.
*
* The instantiator function will be called only once, whether it succeeds or fails.
* The controlling state is maintained by the UInitOnce object, not by
* fInstance and fErrorCode.
* The values of fInstance and fErrorCode must only be set between pre and post init(),
* where they are in a controlled memory environment.
*/
void *TriStateSingleton::getInstance(InstantiatorFn *instantiator, const void *context,
UErrorCode &errorCode) {
if(U_FAILURE(errorCode)) {
return NULL;
}
if (umtx_loadAcquire(fInitOnce.fState) == 2) {
errorCode = fErrorCode;
return fInstance;
}
if (umtx_initImplPreInit(fInitOnce)) {
errorCode = U_ZERO_ERROR;
fInstance = instantiator(context, errorCode);
fErrorCode = errorCode;
umtx_initImplPostInit(fInitOnce, TRUE);
}
return fInstance;
}
void TriStateSingleton::reset() {
fInstance=NULL;
fErrorCode=U_ZERO_ERROR;
fInitOnce.reset();
}
#if UCONFIG_NO_SERVICE
/* If UCONFIG_NO_SERVICE, then there is no invocation of Mutex elsewhere in
common, so add one here to force an export */
static Mutex *aMutex = 0;
/* UCONFIG_NO_SERVICE */
#endif
U_NAMESPACE_END