summaryrefslogtreecommitdiffstats
path: root/intl/icu/source/common/sharedobject.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'intl/icu/source/common/sharedobject.cpp')
-rw-r--r--intl/icu/source/common/sharedobject.cpp87
1 files changed, 87 insertions, 0 deletions
diff --git a/intl/icu/source/common/sharedobject.cpp b/intl/icu/source/common/sharedobject.cpp
new file mode 100644
index 000000000..8e5095e12
--- /dev/null
+++ b/intl/icu/source/common/sharedobject.cpp
@@ -0,0 +1,87 @@
+// Copyright (C) 2016 and later: Unicode, Inc. and others.
+// License & terms of use: http://www.unicode.org/copyright.html
+/*
+******************************************************************************
+* Copyright (C) 2015, International Business Machines
+* Corporation and others. All Rights Reserved.
+******************************************************************************
+* sharedobject.cpp
+*/
+#include "sharedobject.h"
+#include "uassert.h"
+
+U_NAMESPACE_BEGIN
+
+SharedObject::~SharedObject() {}
+
+UnifiedCacheBase::~UnifiedCacheBase() {}
+
+void
+SharedObject::addRef(UBool fromWithinCache) const {
+ umtx_atomic_inc(&totalRefCount);
+
+ // Although items in use may not be correct immediately, it
+ // will be correct eventually.
+ if (umtx_atomic_inc(&hardRefCount) == 1 && cachePtr != NULL) {
+ // If this object is cached, and the hardRefCount goes from 0 to 1,
+ // then the increment must happen from within the cache while the
+ // cache global mutex is locked. In this way, we can be rest assured
+ // that data races can't happen if the cache performs some task if
+ // the hardRefCount is zero while the global cache mutex is locked.
+ (void)fromWithinCache; // Suppress unused variable warning in non-debug builds.
+ U_ASSERT(fromWithinCache);
+ cachePtr->incrementItemsInUse();
+ }
+}
+
+void
+SharedObject::removeRef(UBool fromWithinCache) const {
+ UBool decrementItemsInUse = (umtx_atomic_dec(&hardRefCount) == 0);
+ UBool allReferencesGone = (umtx_atomic_dec(&totalRefCount) == 0);
+
+ // Although items in use may not be correct immediately, it
+ // will be correct eventually.
+ if (decrementItemsInUse && cachePtr != NULL) {
+ if (fromWithinCache) {
+ cachePtr->decrementItemsInUse();
+ } else {
+ cachePtr->decrementItemsInUseWithLockingAndEviction();
+ }
+ }
+ if (allReferencesGone) {
+ delete this;
+ }
+}
+
+void
+SharedObject::addSoftRef() const {
+ umtx_atomic_inc(&totalRefCount);
+ ++softRefCount;
+}
+
+void
+SharedObject::removeSoftRef() const {
+ --softRefCount;
+ if (umtx_atomic_dec(&totalRefCount) == 0) {
+ delete this;
+ }
+}
+
+int32_t
+SharedObject::getRefCount() const {
+ return umtx_loadAcquire(totalRefCount);
+}
+
+int32_t
+SharedObject::getHardRefCount() const {
+ return umtx_loadAcquire(hardRefCount);
+}
+
+void
+SharedObject::deleteIfZeroRefCount() const {
+ if(getRefCount() == 0) {
+ delete this;
+ }
+}
+
+U_NAMESPACE_END