Revert "[Tizen] Add codes for Dali 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   // gcc > 4.1 builtin atomic add and fetch:
105   __sync_add_and_fetch( &mCount, 1 );
106
107 #endif
108 }
109
110 void RefObject::Unreference()
111 {
112   // The output register:
113   int32_t newValue;
114
115 #if defined __aarch64__
116
117   asm volatile(
118   "1:\tldxr   %w[newValue], %[address] \n\t"
119       "sub   %w[newValue], %w[newValue], %[one] \n\t"
120       "stxr  w2,  %w[newValue], %[address] \n\t"
121       "cbnz  w2,  1b \n\t"
122     // Outputs:
123   : [newValue] "=&r" (newValue),
124     // Q = A memory address with no offset
125     // ( https://gcc.gnu.org/onlinedocs/gcc/Machine-Constraints.html#Machine-Constraints )
126     [address] "+Q" (mCount)
127     // Inputs:
128   : [one]  "Ir" (1)
129     // Clobbered: I.e., stuff that is modified.
130   : "w2"
131   );
132
133 #elif defined __arm__
134
135   asm volatile(
136   "1:\tldrex %[newValue], %[address] \n\t"
137       "sub   %[newValue], %[newValue], %[one] \n\t"
138       "strex r2,  %[newValue], %[address] \n\t"
139       "teq   r2, %[zero] \n\t"
140       "bne   1b \n\t"
141     // Outputs:
142   : [newValue] "=&r" (newValue),
143     [address] "+Q" (mCount)
144     // Inputs:
145     : [zero] "Ir" (0),
146       [one]  "Ir" (1)
147     // Clobbered:
148   : "r2"
149   );
150
151 #else
152
153   // gcc > 4.1 builtin atomic subtract and fetch (--mCount; return mCount)
154   newValue = __sync_sub_and_fetch( &mCount, 1 );
155
156 #endif
157
158   if( newValue == 0 )
159   {
160     delete this;
161   }
162 }
163
164 int RefObject::ReferenceCount()
165 {
166   return mCount;
167 }
168
169 } // namespace Dali
170
171