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