Merge branch 'master' of git.opendreambox.org:/git/enigma2
[enigma2.git] / lib / base / object.h
1 #ifndef __base_object_h
2 #define __base_object_h
3
4 #include <assert.h>
5 #include <lib/base/smartptr.h>
6 #include <lib/base/elock.h>
7
8 //#define OBJECT_DEBUG
9
10 #include <lib/base/eerror.h>
11
12 typedef int RESULT;
13
14 class iObject
15 {
16 private:
17                 /* we don't allow the default operator here, as it would break the refcount. */
18         void operator=(const iObject &);
19 protected:
20         void operator delete(void *p) { ::operator delete(p); }
21         virtual ~iObject() { }
22 #ifdef SWIG
23         virtual void AddRef()=0;
24         virtual void Release()=0;
25 #endif
26 public:
27 #ifndef SWIG
28         virtual void AddRef()=0;
29         virtual void Release()=0;
30 #endif
31 };
32
33 #ifndef SWIG
34         struct oRefCount
35         {
36                 volatile int count;
37                 oRefCount(): count(0) { }
38                 operator volatile int&() { return count; }
39                 ~oRefCount()
40                 { 
41         #ifdef OBJECT_DEBUG
42                         if (count)
43                                 eDebug("OBJECT_DEBUG FATAL: %p has %d references!", this, count);
44                         else
45                                 eDebug("OBJECT_DEBUG refcount ok! (%p)", this); 
46         #endif
47                 }
48         };
49
50         #if defined(OBJECT_DEBUG)
51                 extern int object_total_remaining;
52                 #define DECLARE_REF(x)                  \
53                         public: void AddRef();          \
54                                         void Release();         \
55                         private:oRefCount ref;          \
56                                         eSingleLock ref_lock;
57                 #define DEFINE_REF(c) \
58                         void c::AddRef() \
59                         { \
60                                 eSingleLocker l(ref_lock); \
61                                 ++object_total_remaining; \
62                                 ++ref; \
63                                 eDebug("OBJECT_DEBUG " #c "+%p now %d", this, (int)ref); \
64                         } \
65                         void c::Release() \
66                         { \
67                                 { \
68                                         eSingleLocker l(ref_lock); \
69                                         --object_total_remaining; \
70                                         --ref; \
71                                         eDebug("OBJECT_DEBUG " #c "-%p now %d", this, (int)ref); \
72                                 } \
73                                 if (!ref) \
74                                         delete this; \
75                         }
76         #elif defined(__mips__)
77                 #define DECLARE_REF(x)                  \
78                         public: void AddRef();          \
79                                         void Release();         \
80                         private: oRefCount ref; 
81                 #define DEFINE_REF(c) \
82                         void c::AddRef() \
83                         { \
84                                 unsigned long temp; \
85                                 __asm__ __volatile__( \
86                                 "               .set    mips3                                                                                   \n" \
87                                 "1:             ll              %0, %1  # load counter                                                  \n" \
88                                 "               .set    mips0                                                                                   \n" \
89                                 "               addu    %0, 1   # increment                                                             \n" \
90                                 "               .set    mips3                                                                                   \n" \
91                                 "               sc              %0, %1  # try to store, checking for atomicity  \n" \
92                                 "               .set    mips0                                                                                   \n" \
93                                 "               beqz    %0, 1b  # if not atomic (0), try again                  \n" \
94                                 : "=&r" (temp), "=m" (ref.count) \
95                                 : "m" (ref.count) \
96                                 : ); \
97                         } \
98                         void c::Release() \
99                         { \
100                                 unsigned long temp; \
101                                 __asm__ __volatile__( \
102                                 "               .set    mips3                           \n" \
103                                 "1:             ll              %0, %1                          \n" \
104                                 "               .set    mips0                           \n" \
105                                 "               subu    %0, 1   # decrement     \n" \
106                                 "               .set    mips3                           \n" \
107                                 "               sc              %0, %1                          \n" \
108                                 "               .set    mips0                           \n" \
109                                 "               beqz    %0, 1b                          \n" \
110                                 : "=&r" (temp), "=m" (ref.count) \
111                                 : "m" (ref.count) \
112                                 : ); \
113                                 if (!ref) \
114                                         delete this; \
115                         }
116         #elif defined(__ppc__) || defined(__powerpc__)
117                 #define DECLARE_REF(x)                  \
118                         public: void AddRef();          \
119                                         void Release();         \
120                         private: oRefCount ref;
121                 #define DEFINE_REF(c) \
122                         void c::AddRef() \
123                         { \
124                                 int temp; \
125                                 __asm__ __volatile__( \
126                                 "1:             lwarx   %0, 0, %3       \n" \
127                                 "               add             %0, %2, %0      \n" \
128                                 "               dcbt    0, %3           # workaround for PPC405CR Errata\n" \
129                                 "               stwcx.  %0, 0, %3       \n" \
130                                 "               bne-    1b                      \n" \
131                                 : "=&r" (temp), "=m" (ref.count) \
132                                 : "r" (1), "r" (&ref.count), "m" (ref.count) \
133                                 : "cc"); \
134                         } \
135                         void c::Release() \
136                         { \
137                                 int temp; \
138                                 __asm__ __volatile__( \
139                                 "1:             lwarx   %0, 0, %3       \n" \
140                                 "               subf    %0, %2, %0      \n" \
141                                 "               dcbt    0, %3           # workaround for PPC405CR Errata\n" \
142                                 "               stwcx.  %0, 0, %3       \n" \
143                                 "               bne-    1b                      \n" \
144                                 : "=&r" (temp), "=m" (ref.count) \
145                                 : "r" (1), "r" (&ref.count), "m" (ref.count) \
146                                 : "cc"); \
147                                 if (!ref) \
148                                         delete this; \
149                         }
150         #elif defined(__i386__) || defined(__x86_64__)
151                 #define DECLARE_REF(x)                  \
152                         public: void AddRef();          \
153                                         void Release();         \
154                         private: oRefCount ref;
155                 #define DEFINE_REF(c) \
156                         void c::AddRef() \
157                         { \
158                                 __asm__ __volatile__( \
159                                 "               lock ; incl     %0      \n" \
160                                 : "=m" (ref.count) \
161                                 : "m" (ref.count)); \
162                         } \
163                         void c::Release() \
164                         { \
165                                 __asm__ __volatile__( \
166                                 "               lock ; decl     %0      \n" \
167                                 : "=m" (ref.count) \
168                                 : "m" (ref.count)); \
169                                 if (!ref) \
170                                         delete this; \
171                         }
172         #else
173                 #warning use non optimized implementation of refcounting.
174                 #define DECLARE_REF(x)                  \
175                         public: void AddRef();          \
176                                         void Release();         \
177                         private:oRefCount ref;  \
178                                         eSingleLock ref_lock;
179                 #define DEFINE_REF(c) \
180                         void c::AddRef() \
181                         { \
182                                 eSingleLocker l(ref_lock); \
183                                 ++ref; \
184                         } \
185                         void c::Release() \
186                         { \
187                                 { \
188                                         eSingleLocker l(ref_lock); \
189                                         --ref; \
190                                 } \
191                                 if (!ref) \
192                                         delete this; \
193                         }
194         #endif
195 #else  // SWIG
196         #define DECLARE_REF(x) \
197                 private: \
198                         void AddRef(); \
199                         void Release();
200 #endif  // SWIG
201
202 #endif  // __base_object_h