| Index: icu51/source/common/mutex.cpp
|
| ===================================================================
|
| --- icu51/source/common/mutex.cpp (revision 0)
|
| +++ icu51/source/common/mutex.cpp (revision 0)
|
| @@ -0,0 +1,140 @@
|
| +/*
|
| +*******************************************************************************
|
| +*
|
| +* Copyright (C) 2008-2011, 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,
|
| + void *&duplicate,
|
| + UErrorCode &errorCode) {
|
| + duplicate=NULL;
|
| + if(U_FAILURE(errorCode)) {
|
| + return NULL;
|
| + }
|
| + // TODO: With atomicops.h: void *instance = (void*)Acquire_Load(&fInstance);
|
| + // and remove UMTX_ACQUIRE_BARRIER below.
|
| + void *instance=ANNOTATE_UNPROTECTED_READ(fInstance);
|
| + UMTX_ACQUIRE_BARRIER;
|
| + ANNOTATE_HAPPENS_AFTER(&fInstance);
|
| + if(instance!=NULL) {
|
| + return instance;
|
| + }
|
| +
|
| + // Attempt to create the instance.
|
| + // If a race occurs, then the losing thread will assign its new instance
|
| + // to the "duplicate" parameter, and the caller deletes it.
|
| + instance=instantiator(context, errorCode);
|
| + UMTX_RELEASE_BARRIER; // Release-barrier before fInstance=instance;
|
| + Mutex mutex;
|
| + if(fInstance==NULL && U_SUCCESS(errorCode)) {
|
| + U_ASSERT(instance!=NULL);
|
| + ANNOTATE_HAPPENS_BEFORE(&fInstance);
|
| + // TODO: With atomicops.h: Release_Store(&fInstance, (AtomicWord)instance);
|
| + // and remove UMTX_RELEASE_BARRIER above.
|
| + fInstance=instance;
|
| + } else {
|
| + duplicate=instance;
|
| + }
|
| + return fInstance;
|
| +}
|
| +
|
| +/*
|
| + * Three states:
|
| + *
|
| + * Initial state: Instance creation not attempted yet.
|
| + * fInstance=NULL && U_SUCCESS(fErrorCode)
|
| + *
|
| + * Instance creation succeeded:
|
| + * fInstance!=NULL && U_SUCCESS(fErrorCode)
|
| + *
|
| + * Instance creation failed:
|
| + * fInstance=NULL && U_FAILURE(fErrorCode)
|
| + * We will not attempt again to create the instance.
|
| + *
|
| + * fInstance changes at most once.
|
| + * fErrorCode changes at most twice (intial->failed->succeeded).
|
| + */
|
| +void *TriStateSingleton::getInstance(InstantiatorFn *instantiator, const void *context,
|
| + void *&duplicate,
|
| + UErrorCode &errorCode) {
|
| + duplicate=NULL;
|
| + if(U_FAILURE(errorCode)) {
|
| + return NULL;
|
| + }
|
| + // TODO: With atomicops.h: void *instance = (void*)Acquire_Load(&fInstance);
|
| + // and remove UMTX_ACQUIRE_BARRIER below.
|
| + void *instance=ANNOTATE_UNPROTECTED_READ(fInstance);
|
| + UMTX_ACQUIRE_BARRIER;
|
| + ANNOTATE_HAPPENS_AFTER(&fInstance);
|
| + if(instance!=NULL) {
|
| + // instance was created
|
| + return instance;
|
| + }
|
| +
|
| + // The read access to fErrorCode is thread-unsafe, but harmless because
|
| + // at worst multiple threads race to each create a new instance,
|
| + // and all losing threads delete their duplicates.
|
| + UErrorCode localErrorCode=ANNOTATE_UNPROTECTED_READ(fErrorCode);
|
| + if(U_FAILURE(localErrorCode)) {
|
| + // instance creation failed
|
| + errorCode=localErrorCode;
|
| + return NULL;
|
| + }
|
| +
|
| + // First attempt to create the instance.
|
| + // If a race occurs, then the losing thread will assign its new instance
|
| + // to the "duplicate" parameter, and the caller deletes it.
|
| + instance=instantiator(context, errorCode);
|
| + UMTX_RELEASE_BARRIER; // Release-barrier before fInstance=instance;
|
| + Mutex mutex;
|
| + if(fInstance==NULL && U_SUCCESS(errorCode)) {
|
| + // instance creation newly succeeded
|
| + U_ASSERT(instance!=NULL);
|
| + ANNOTATE_HAPPENS_BEFORE(&fInstance);
|
| + // TODO: With atomicops.h: Release_Store(&fInstance, (AtomicWord)instance);
|
| + // and remove UMTX_RELEASE_BARRIER above.
|
| + fInstance=instance;
|
| + // Set fErrorCode on the off-chance that a previous instance creation failed.
|
| + fErrorCode=errorCode;
|
| + // Completed state transition: initial->succeeded, or failed->succeeded.
|
| + } else {
|
| + // Record a duplicate if we lost the race, or
|
| + // if we got an instance but its creation failed anyway.
|
| + duplicate=instance;
|
| + if(fInstance==NULL && U_SUCCESS(fErrorCode) && U_FAILURE(errorCode)) {
|
| + // instance creation newly failed
|
| + fErrorCode=errorCode;
|
| + // Completed state transition: initial->failed.
|
| + }
|
| + }
|
| + return fInstance;
|
| +}
|
| +
|
| +void TriStateSingleton::reset() {
|
| + fInstance=NULL;
|
| + fErrorCode=U_ZERO_ERROR;
|
| +}
|
| +
|
| +#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
|
|
|
| Property changes on: icu51/source/common/mutex.cpp
|
| ___________________________________________________________________
|
| Added: svn:eol-style
|
| + LF
|
|
|
|
|