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