Revert "[Tizen] fixed argument for debug api (related to windows backend)"
[platform/core/uifw/dali-core.git] / dali / public-api / object / ref-object.cpp
1 /*
2  * Copyright (c) 2015 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 // CLASS HEADER
19 #include <dali/public-api/object/ref-object.h>
20
21 // INTERNAL INCLUDES
22 #include <dali/public-api/common/dali-common.h>
23
24 // EXTERNAL INCLUDES
25 #include <stdint.h>
26
27 namespace Dali
28 {
29
30 RefObject::RefObject()
31 : mCount(0)
32 {
33 }
34
35 RefObject::RefObject(const RefObject&)
36 : mCount(0) // Do not copy the reference count
37 {
38 }
39
40 RefObject::~RefObject()
41 {
42 #ifdef ENABLE_DEBUG
43   if(mCount)
44   {
45     DALI_LOG_ERROR("mCount should be zero, deleting referenced object!\n");
46   }
47 #endif // ENABLE_DEBUG
48 }
49
50 RefObject& RefObject::operator=(const RefObject&)
51 {
52   // Do not copy the reference count
53   return *this;
54 }
55
56 void RefObject::Reference()
57 {
58   // The inline assembly below was tested on an ARMv8 64 bit platform on
59   // 2015-02-06 and found to run in 11.8 nanoseconds, whereas
60   // __sync_add_and_fetch( address, 1 ) required 18.8 nanoseconds.
61   // Including the assembly here produced one fewer assembly instruction than if
62   // it was wrapped in a function and inlined here by the compiler.
63 #if defined __aarch64__
64
65   asm volatile(
66   "1:\tldxr  w1, %[address] \n\t"
67       "add   w1, w1, %[one] \n\t"
68       "stxr  w2,  w1, %[address] \n\t"
69       "cbnz  w2,  1b \n\t"
70       // Outputs:
71     : // Q = A memory address with no offset
72       // ( https://gcc.gnu.org/onlinedocs/gcc/Machine-Constraints.html#Machine-Constraints )
73       [address] "+Q" (mCount)
74       // Inputs:
75     : [one] "Ir" (1)
76       // Clobbers: (explicitly clobber w1 register to hold the loaded value and
77       // register w2 to hold success/fail):
78     : "w1", "w2"
79   );
80
81   // 32 bit ARMv7 version of above:
82   // Better than the code emitted by GCC for __sync_add_and_fetch(), as that
83   // includes two dmb memory barrier instructions: one before and one after the
84   // loop.
85 #elif defined __arm__
86
87   asm volatile(
88     "1:\tldrex r1, %[address] \n\t"
89         "add   r1, r1, %[one] \n\t"
90         "strex r2,  r1, %[address] \n\t"
91         "teq   r2,  %[zero] \n\t"
92         "bne   1b \n\t"
93         // Outputs:
94       : [address] "+Q" (mCount)
95         // Inputs:
96       : [zero] "Ir" (0),
97         [one]  "Ir" (1)
98         // Clobbers: (modified registers):
99       : "r1", "r2"
100     );
101
102 #else
103
104   std::atomic_fetch_add<int>(&mCount, 1);
105
106 #endif
107 }
108
109 void RefObject::Unreference()
110 {
111   // The output register:
112   int32_t newValue;
113
114 #if defined __aarch64__
115
116   asm volatile(
117   "1:\tldxr   %w[newValue], %[address] \n\t"
118       "sub   %w[newValue], %w[newValue], %[one] \n\t"
119       "stxr  w2,  %w[newValue], %[address] \n\t"
120       "cbnz  w2,  1b \n\t"
121     // Outputs:
122   : [newValue] "=&r" (newValue),
123     // Q = A memory address with no offset
124     // ( https://gcc.gnu.org/onlinedocs/gcc/Machine-Constraints.html#Machine-Constraints )
125     [address] "+Q" (mCount)
126     // Inputs:
127   : [one]  "Ir" (1)
128     // Clobbered: I.e., stuff that is modified.
129   : "w2"
130   );
131
132 #elif defined __arm__
133
134   asm volatile(
135   "1:\tldrex %[newValue], %[address] \n\t"
136       "sub   %[newValue], %[newValue], %[one] \n\t"
137       "strex r2,  %[newValue], %[address] \n\t"
138       "teq   r2, %[zero] \n\t"
139       "bne   1b \n\t"
140     // Outputs:
141   : [newValue] "=&r" (newValue),
142     [address] "+Q" (mCount)
143     // Inputs:
144     : [zero] "Ir" (0),
145       [one]  "Ir" (1)
146     // Clobbered:
147   : "r2"
148   );
149
150 #else
151
152   newValue = ( mCount -= 1 );
153
154 #endif
155
156   if( newValue == 0 )
157   {
158     delete this;
159   }
160 }
161
162 int RefObject::ReferenceCount()
163 {
164   return mCount;
165 }
166
167 } // namespace Dali
168
169