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