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