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