1 /* 2 * Copyright (c) 2004 X-Way Rights BV 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Lesser General Public 6 * License as published by the Free Software Foundation; either 7 * version 2.1 of the License, or (at your option) any later version. 8 * 9 * This library is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * Lesser General Public License for more details. 13 * 14 * You should have received a copy of the GNU Lesser General Public 15 * License along with this library; if not, write to the Free Software 16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 */ 18 19 /*!\file Object.h 20 * \ingroup CXX_LANG_m 21 * 22 * Credit for the technique of emulating POSIX condition variables 23 * on Win32 goes to Douglas C. Schmidt and Irfan Pyarali. 24 * 25 * \see http://www.cs.wustl.edu/~schmidt/win32-cv-1.html 26 */ 27 28 #ifndef _CLASS_BEE_LANG_OBJECT_H 29 #define _CLASS_BEE_LANG_OBJECT_H 30 31 #include "beecrypt/c++/lang/CloneNotSupportedException.h" 32 using beecrypt::lang::CloneNotSupportedException; 33 #include "beecrypt/c++/lang/InterruptedException.h" 34 using beecrypt::lang::InterruptedException; 35 #include "beecrypt/c++/lang/IllegalMonitorStateException.h" 36 using beecrypt::lang::IllegalMonitorStateException; 37 #include "beecrypt/c++/lang/RuntimeException.h" 38 using beecrypt::lang::RuntimeException; 39 40 #ifdef __cplusplus 41 42 namespace beecrypt { 43 namespace util { 44 namespace concurrent { 45 namespace locks { 46 class BEECRYPTCXXAPI ReentrantLock; 47 } 48 } 49 } 50 namespace lang { 51 /*!\ingroup CXX_LANG_m 52 */ 53 class BEECRYPTCXXAPI Object 54 { 55 friend class Thread; 56 friend class beecrypt::util::concurrent::locks::ReentrantLock; 57 58 friend BEECRYPTCXXAPI void collection_attach(Object*) throw (); 59 friend BEECRYPTCXXAPI void collection_detach(Object*) throw (); 60 friend BEECRYPTCXXAPI void collection_remove(Object*) throw (); 61 friend BEECRYPTCXXAPI void collection_rcheck(Object*) throw (); 62 63 protected: 64 /*!\brief This class is used to emulate Java's lock/wait/notify 65 * methods. 66 */ 67 class Monitor 68 { 69 friend class Object; 70 71 protected: 72 bc_threadid_t _owner; 73 bc_threadid_t _interruptee; 74 bc_mutex_t _lock; 75 volatile unsigned int _lock_count; 76 77 void internal_state_lock(); 78 void internal_state_unlock(); 79 80 Monitor(); 81 82 public: ~Monitor()83 virtual ~Monitor() {} 84 85 virtual void interrupt(bc_threadid_t) = 0; 86 virtual bool interrupted(bc_threadid_t); 87 virtual bool isInterrupted(bc_threadid_t); 88 virtual bool isLocked(); 89 virtual void lock() = 0; 90 virtual void lockInterruptibly() throw (InterruptedException) = 0; 91 virtual bool tryLock() = 0; 92 virtual void notify() = 0; 93 virtual void notifyAll() = 0; 94 virtual void unlock() = 0; 95 virtual void wait(jlong timeout) throw (InterruptedException) = 0; 96 97 static Monitor* getInstance(bool fair = false); 98 }; 99 100 private: 101 /*!\brief A Non-fair Monitor 102 */ 103 class NonfairMonitor : public Monitor 104 { 105 private: 106 #if WIN32 107 HANDLE _lock_sig; // semaphore 108 bool _lock_sig_all; 109 HANDLE _lock_sig_all_done; // event 110 unsigned int _lock_wthreads; 111 HANDLE _notify_sig; // semaphore 112 bool _notify_sig_all; 113 HANDLE _notify_sig_all_done; // event 114 unsigned int _notify_wthreads; 115 #else 116 bc_cond_t _lock_sig; 117 unsigned int _lock_wthreads; 118 bc_cond_t _notify_sig; 119 unsigned int _notify_wthreads; 120 #endif 121 122 public: 123 NonfairMonitor(); 124 virtual ~NonfairMonitor(); 125 126 virtual void interrupt(bc_threadid_t); 127 virtual void lock(); 128 virtual void lockInterruptibly() throw (InterruptedException); 129 virtual bool tryLock(); 130 virtual void unlock(); 131 virtual void notify(); 132 virtual void notifyAll(); 133 virtual void wait(jlong timeout) throw (InterruptedException); 134 }; 135 136 class FairMonitor : public Monitor 137 { 138 private: 139 struct waiter 140 { 141 bc_threadid_t owner; 142 unsigned int lock_count; 143 bc_cond_t event; 144 waiter* next; 145 waiter* prev; 146 147 waiter(bc_threadid_t owner, unsigned int lock_count); 148 ~waiter(); 149 }; 150 151 waiter* _lock_head; 152 waiter* _lock_tail; 153 waiter* _notify_head; 154 waiter* _notify_tail; 155 156 public: 157 FairMonitor(); 158 virtual ~FairMonitor(); 159 160 virtual void interrupt(bc_threadid_t); 161 virtual void lock(); 162 virtual void lockInterruptibly() throw (InterruptedException); 163 virtual bool tryLock(); 164 virtual void unlock(); 165 virtual void notify(); 166 virtual void notifyAll(); 167 virtual void wait(jlong timeout) throw (InterruptedException); 168 }; 169 170 private: 171 /*!\brief The object's reference count (for use with Collections). 172 * When this value is zero, it's safe to delete it. 173 */ 174 volatile unsigned int _ref_count; 175 176 private: 177 /*!\brief The object's monitor. 178 * Initialized to zero, and only allocated when an Object's 179 * is first synchronized. Classes which rely heavily on 180 * synchronization should initialize this member in their 181 * constructor with the Object::Monitor::getInstance() 182 * method. 183 * \see Object::Monitor::getInstance(bool fair = false) 184 */ 185 mutable Monitor* monitor; 186 187 public: 188 /*!\brief This class is used to emulate Java's 'synchronized' 189 * methods. 190 */ 191 class BEECRYPTCXXAPI Synchronizer 192 { 193 private: 194 const Object* _ref; 195 bool _once; 196 197 public: 198 Synchronizer(const Object* obj); 199 Synchronizer(const Object& obj); 200 ~Synchronizer(); 201 202 bool checkonce(); 203 }; 204 205 /*!\def synchronized 206 * \brief Macro used to emulate Java's synchronization primitive. 207 */ 208 #define synchronized(obj) for (Object::Synchronizer _s(obj); _s.checkonce(); ) 209 210 private: 211 static bc_mutex_t _init_lock; 212 static bc_mutex_t init(); 213 214 private: 215 void lock() const; 216 void unlock() const; 217 218 protected: 219 virtual Object* clone() const throw (CloneNotSupportedException); 220 221 public: 222 Object(); 223 virtual ~Object(); 224 225 virtual bool equals(const Object* obj) const throw (); 226 virtual jint hashCode() const throw (); 227 void notify() const; 228 void notifyAll() const; 229 virtual String toString() const throw (); 230 void wait(jlong millis = 0) const throw (InterruptedException); 231 }; 232 233 /*!\brief This function is used inside a collection to indicate that 234 * the object is now attached to it. 235 */ 236 BEECRYPTCXXAPI 237 void collection_attach(Object*) throw (); 238 /*!\brief This function is used inside a collection to indicate that 239 * the object has been detached to it. 240 */ 241 BEECRYPTCXXAPI 242 void collection_detach(Object*) throw (); 243 /*!\brief This function is used inside a collection to detach the 244 * object, and delete it if no longer attached to any other 245 * collections. 246 */ 247 BEECRYPTCXXAPI 248 void collection_remove(Object*) throw (); 249 /*!\brief This function checks if an object needs to be recycled: 250 * the object is deleted if no longer attached to any collection. 251 */ 252 BEECRYPTCXXAPI 253 void collection_rcheck(Object*) throw (); 254 } 255 } 256 257 #endif 258 259 #endif 260