Use atomic operation for Reference counting
authordahyeong.kim <dahyeong.kim@samsung.com>
Mon, 27 May 2013 08:20:01 +0000 (17:20 +0900)
committerdahyeong.kim <dahyeong.kim@samsung.com>
Mon, 27 May 2013 08:21:57 +0000 (17:21 +0900)
Change-Id: Icc9d415736013d641028696bbc840cdeca7c15f7
Signed-off-by: dahyeong.kim <dahyeong.kim@samsung.com>
inc/FBaseString.h
src/base/FBaseString.cpp
src/base/inc/FBase_String.h [new file with mode: 0644]

index 8cd87f9..f9b6fe0 100644 (file)
@@ -1097,7 +1097,7 @@ private:
        int __capacity;
        int __length;
        mutable int __hash;
-       mutable int* __pRefCount;
+       mutable volatile int* __pRefCount;
        mutable wchar_t* __pValue;
 
        static const float GROWTH_FACTOR;
index 03ce90e..e5ff018 100644 (file)
@@ -37,6 +37,7 @@
 #include <FBaseResult.h>
 #include <FBaseSysLog.h>
 #include <unique_ptr.h>
+#include "FBase_String.h"
 
 
 namespace Tizen { namespace Base
@@ -158,7 +159,7 @@ String::String(const String& value)
 {
        SysTryReturnVoidResult(NID_BASE, value.__length >= 0, E_OUT_OF_RANGE, "The length has to be greater than 0.");
 
-       ++(*value.__pRefCount);
+       _String::AtomicInc(value.__pRefCount);
        __pRefCount = value.__pRefCount;
 }
 
@@ -171,7 +172,7 @@ String::~String(void)
        }
        else
        {
-               (*__pRefCount)--;
+               _String::AtomicDec(__pRefCount);
                __pRefCount = null;
        }
 }
@@ -378,7 +379,7 @@ String::Append(const wchar_t* p)
                SysTryReturnResult(NID_BASE, pRefCntTemp != null, E_OUT_OF_MEMORY, "Memory allocation failed");
 
                wcsncpy(__pValue, pValue, __length);
-               (*__pRefCount)--;
+               _String::AtomicDec(__pRefCount);
                __pRefCount = pRefCntTemp.release();
        }
 
@@ -1044,7 +1045,7 @@ String::SetCapacity(int capacity)
                {
                        std::unique_ptr<int> pRefCntTemp(new (std::nothrow) int(1));
                        SysTryReturnResult(NID_BASE, pRefCntTemp != null, E_OUT_OF_MEMORY, "Memory allocation failed");
-                       (*__pRefCount)--;
+                       _String::AtomicDec(__pRefCount);
                        __pRefCount = pRefCntTemp.release();
                }
        }
@@ -1514,7 +1515,7 @@ String::ExpandCapacity(int minCapacity)
                        std::unique_ptr<int> pRefCntTemp(new (std::nothrow) int(1));
                        SysTryReturn(NID_BASE, pRefCntTemp != null, false, E_OUT_OF_MEMORY, "[%s] Memory allocation failed",
                                GetErrorMessage(E_OUT_OF_MEMORY));
-                       (*__pRefCount)--;
+                       _String::AtomicDec(__pRefCount);
                        __pRefCount = pRefCntTemp.release();
                }
        }
@@ -1546,7 +1547,7 @@ String::CopyOnWrite(int capacity)
 
        wcsncpy(__pValue, pValue, __length);
        __pValue[__length] = '\0';
-       --(*__pRefCount);
+       _String::AtomicDec(__pRefCount);
        __pRefCount = pRefCntTemp.release();
        return E_SUCCESS;
 }
diff --git a/src/base/inc/FBase_String.h b/src/base/inc/FBase_String.h
new file mode 100644 (file)
index 0000000..530968f
--- /dev/null
@@ -0,0 +1,78 @@
+//
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file               FBase_String.h
+ * @brief              This is the header file for handling atomic operations.
+ */
+
+#ifndef _FBASE_INTERNAL_STRING_H_
+#define _FBASE_INTERNAL_STRING_H_
+
+namespace Tizen { namespace Base
+{
+namespace _String
+{
+
+/**
+ * Atomically add the value to the variable that pRefCount points to.
+ *
+ * @since 2.1
+ */
+inline int AtomicAdd(volatile int* pRefCount, int value)
+{
+#if defined(__arm__)
+       register int result;
+       asm volatile (
+               "1: ldrex   %0,  [%1]   \n\t"
+               "add     r1,   %0,  %2  \n\t"
+               "strex   r2,   r1, [%1] \n\t"
+               "cmp     r2,   #0 \n\t"
+               "bne     1b"
+               : "=&r" (result)
+               : "r"(pRefCount), "r"(value)
+               : "r1","r2"
+       );
+       return result;
+#else
+       return __sync_fetch_and_add(pRefCount, value);
+#endif
+}
+
+/**
+ * Atomically increase the variable that pRefCount points to by 1
+ *
+ * @since 2.1
+ */
+inline int AtomicInc(volatile int* pRefCount)
+{
+       return AtomicAdd(pRefCount, 1);
+}
+
+/**
+ * Atomically decrease the variable that pRefCount points to by 1
+ *
+ * @since 2.1
+ */
+inline int AtomicDec(volatile int* pRefCount)
+{
+       return AtomicAdd(pRefCount, -1);
+}
+
+}// _String
+}}     // Tizen::Base
+
+#endif // _FBASE_INTERNAL_STRING_H_
\ No newline at end of file