adb5d67cbb0304a8bb85b3d0efc81fe9c14eec6d
[enigma2.git] / lib / base / object.h
1 #ifndef __base_object_h
2 #define __base_object_h
3
4 #include <assert.h>
5
6 // #define OBJECT_DEBUG
7
8 #include <lib/base/smartptr.h>
9 #ifdef OBJECT_DEBUG
10 #include <lib/base/eerror.h>
11 #endif
12 #include <lib/base/elock.h>
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 struct oRefCount
29 {
30         volatile int count;
31         oRefCount(): count(0) { }
32         operator volatile int&() { return count; }
33         ~oRefCount() { 
34 #ifdef OBJECT_DEBUG
35                 if (count) eDebug("OBJECT_DEBUG FATAL: %p has %d references!", this, ref); else eDebug("OBJECT_DEBUG refcount ok! (%p)", this); 
36 #endif
37         }
38 };
39
40 #ifndef SWIG
41         #if defined(__mips__)
42                 #define DECLARE_REF(x)                  \
43                         private: oRefCount ref;         \
44                         public: void AddRef();          \
45                                         void Release();
46                 #define DEFINE_REF(c) \
47                         void c::AddRef() \
48                         { \
49                                 unsigned long temp; \
50                                 __asm__ __volatile__( \
51                                 "               .set    mips3                                                                                   \n" \
52                                 "1:             ll              %0, %1  # load counter                                                  \n" \
53                                 "               .set    mips0                                                                                   \n" \
54                                 "               addu    %0, 1   # increment                                                             \n" \
55                                 "               .set    mips3                                                                                   \n" \
56                                 "               sc              %0, %1  # try to store, checking for atomicity  \n" \
57                                 "               .set    mips0                                                                                   \n" \
58                                 "               beqz    %0, 1b  # if not atomic (0), try again                  \n" \
59                                 : "=&r" (temp), "=m" (ref.count) \
60                                 : "m" (ref.count) \
61                                 : ); \
62                         } \
63                         void c::Release() \
64                         { \
65                                 unsigned long temp; \
66                                 __asm__ __volatile__( \
67                                 "               .set    mips3                           \n" \
68                                 "1:             ll              %0, %1                          \n" \
69                                 "               .set    mips0                           \n" \
70                                 "               subu    %0, 1   # decrement     \n" \
71                                 "               .set    mips3                           \n" \
72                                 "               sc              %0, %1                          \n" \
73                                 "               .set    mips0                           \n" \
74                                 "               beqz    %0, 1b                          \n" \
75                                 : "=&r" (temp), "=m" (ref.count) \
76                                 : "m" (ref.count) \
77                                 : ); \
78                                 if (!ref) \
79                                         delete this; \
80                         }
81         #elif defined(__ppc__)
82                 #define DECLARE_REF(x)                  \
83                         private: oRefCount ref;         \
84                         public: void AddRef();          \
85                                         void Release();
86                 #define DEFINE_REF(c) \
87                         void c::AddRef() \
88                         { \
89                                 int temp; \
90                                 __asm__ __volatile__( \
91                                 "1:             lwarx   %0, 0, %3       \n" \
92                                 "               add             %0, %2, %0      \n" \
93                                 "               dcbt    0, %3           # workaround for PPC405CR Errata\n" \
94                                 "               stwcx.  %0, 0, %3       \n" \
95                                 "               bne-    1b                      \n" \
96                                 : "=&r" (temp), "=m" (ref.count) \
97                                 : "r" (1), "r" (&ref.count), "m" (ref.count) \
98                                 : "cc"); \
99                         } \
100                         void c::Release() \
101                         { \
102                                 int temp; \
103                                 __asm__ __volatile__( \
104                                 "1:             lwarx   %0, 0, %3       \n" \
105                                 "               subf    %0, %2, %0      \n" \
106                                 "               dcbt    0, %3           # workaround for PPC405CR Errata\n" \
107                                 "               stwcx.  %0, 0, %3       \n" \
108                                 "               bne-    1b                      \n" \
109                                 : "=&r" (temp), "=m" (ref.count) \
110                                 : "r" (1), "r" (&ref.count), "m" (ref.count) \
111                                 : "cc"); \
112                                 if (!ref) \
113                                         delete this; \
114                         }
115         #else
116                 #define DECLARE_REF(x)                  \
117                         private:oRefCount ref;  \
118                                         eSingleLock ref_lock; \
119                         public: void AddRef();          \
120                                         void Release();
121                 #ifdef OBJECT_DEBUG
122                         extern int object_total_remaining;
123                         #define DEFINE_REF(c) \
124                                 void c::AddRef() \
125                                 { \
126                                         eSingleLocker l(ref_lock); \
127                                         ++object_total_remaining; \
128                                         ++ref; \
129                                         eDebug("OBJECT_DEBUG " #c "+%p now %d", this, ref.count); \
130                                 } \
131                                 void c::Release() \
132                                 { \
133                                         { \
134                                                 eSingleLocker l(ref_lock); \
135                                                 --object_total_remaining; \
136                                                 --ref; \
137                                                 eDebug("OBJECT_DEBUG " #c "-%p now %d", this, ref); \
138                                         } \
139                                         if (!ref) \
140                                                 delete this; \
141                                 }
142                                 #error fix locking for debug
143                 #else
144                         #define DEFINE_REF(c) \
145                                 void c::AddRef() \
146                                 { \
147                                         eSingleLocker l(ref_lock); \
148                                         ++ref; \
149                                 } \
150                                 void c::Release() \
151                                 { \
152                                         { \
153                                                 eSingleLocker l(ref_lock); \
154                                                 --ref; \
155                                         } \
156                                         if (!ref) \
157                                                 delete this; \
158                                 }
159                 #endif
160         #endif
161 #else
162         #define DECLARE_REF(x) \
163                 private: \
164                         void AddRef(); \
165                         void Release();
166 #endif
167
168 #ifdef SWIG
169 class Object
170 {
171 };
172 #endif
173
174 #endif