00001 /* 00002 * Object.hpp 00003 * 00004 * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. 00005 * 00006 * Oracle is a registered trademarks of Oracle Corporation and/or its 00007 * affiliates. 00008 * 00009 * This software is the confidential and proprietary information of Oracle 00010 * Corporation. You shall not disclose such confidential and proprietary 00011 * information and shall use it only in accordance with the terms of the 00012 * license agreement you entered into with Oracle. 00013 * 00014 * This notice may not be removed or altered. 00015 */ 00016 #ifndef COH_OBJECT_HPP 00017 #define COH_OBJECT_HPP 00018 00019 #include "coherence/lang/compatibility.hpp" 00020 00021 #include "coherence/lang/cloneable_spec.hpp" 00022 #include "coherence/lang/LifeCycle.hpp" 00023 #include "coherence/lang/TypedHandle.hpp" 00024 #include "coherence/lang/TypedHolder.hpp" 00025 #include "coherence/native/NativeAtomic64.hpp" 00026 00027 #include <ostream> 00028 00029 COH_OPEN_NAMESPACE2(coherence,native) 00030 class NativeCondition; 00031 COH_CLOSE_NAMESPACE2 00032 00033 COH_OPEN_NAMESPACE2(coherence,lang) 00034 00035 class SmartMember; 00036 class WeakReference; 00037 00038 using coherence::native::NativeAtomic64; 00039 using coherence::native::NativeCondition; 00040 00041 00042 /** 00043 * Object is the base class for all Coherence managed objects. 00044 * 00045 * The interface for Object provides support basic operations such as equality, 00046 * hashing, printing, cloning, synchronization, and notification. 00047 * 00048 * Objects have automatically managed memory, through built-in thread-safe 00049 * reference counting. The reference count is maintained through the use of 00050 * smart-pointers, known as handles. All references to an Object should be 00051 * maintained through a handle rather then a raw pointer, or C++ reference. 00052 * 00053 * Each managed class includes inner definitions of handles which can be used 00054 * to reference instance of that class, as well as derived class instances. 00055 * These definitions provide functionality corresponding to const and non-const 00056 * pointers. The names for these handles are Handle for the non-const, View for 00057 * the const pointer equivalent, and Holder for a hybrid. The Holder type acts 00058 * like a View but allows for a safe down-cast to a Handle, which will only 00059 * succeed if the Holder was assigned from a Handle, and will fail with a 00060 * ClassCastException if it had been assigned from a View. Note that in 00061 * documentation the term "handle" is used to describe any handle type 00062 * including Handle/View/Holder, while "Handle" refers to the specific 00063 * "Handle" type. 00064 * 00065 * The handles are aware of the inheritance hierarchy, allowing direct 00066 * assignment from a handle from a derived class to a handle of a base class. 00067 * These up-casts are automatic, and an explicit cast operation is rarely 00068 * needed, except to resolve compiler type ambiguities. Assignment from a View 00069 * to a Handle is also automatic as the const-interface of a class can 00070 * naturally be considered a base-class. Assignment of a handle to a derived 00071 * type is not automatic, and requires an explicit down-cast via the coherence 00072 * cast<H>(h) function. The template parameter is the desired handle type, while 00073 * the function parameter is the handle to cast. If the supplied handle is 00074 * non-NULL and is not an instance of the class associated with H, a 00075 * ClassCastException will be thrown. There is a corresponding instanceof<H>(h) 00076 * method which can be used to perform the type-check without the risk of 00077 * triggering an exception. The use of instanceof, is optional, and is only 00078 * needed if the type is actually in question. 00079 * 00080 * @code 00081 * Object::Handle hObject = ... 00082 * Foo::Handle hFoo; 00083 * 00084 * if (instanceof<Foo::Handle>(hObject)) 00085 * { 00086 * hFoo = cast<Foo::Handle>(hObject); 00087 * } 00088 * @endcode 00089 * 00090 * These convenience handles are not thread-safe, and should not be used in a 00091 * multi-threaded context. They should only be used as local variables, though 00092 * they are free to reference objects shared by many threads. The most common 00093 * place where thread-safe handles are needed is for data members of managed 00094 * objects. For these cases the Coherence API includes a variety of thread-safe 00095 * handles/views. It is necessary that any class which extends from Object use 00096 * thread-safe handles when referencing other managed Objects. 00097 * 00098 * By convention managed objects will also block direct external access to 00099 * their constructor and destructor. Constructors are accessed via public 00100 * static "create" factory methods. The copy constructor is accessed via the 00101 * public virtual "clone" method. Destructors are protected and destruction 00102 * is triggered automatically when the internal reference count reaches zero. 00103 * 00104 * @see class_spec for defining non-cloneable classes 00105 * @see cloneable_spec for defining cloneable classes 00106 * @see abstract_spec for defining abstract classes 00107 * @see interface_spec for defining interfaces 00108 * @see throwable_spec for defining exceptions 00109 * @see MemberHandle for thread-safe data member handles 00110 * @see MemberView for thread-safe data member views 00111 * @see MemberHolder for thread-safe data member holders 00112 * @see FinalHandle for thread-safe "const" data member handles 00113 * @see FinalView for thread-safe "const" data member views 00114 * @see FinalHolder for thread-safe "const" data member holders 00115 * @see WeakHandle for thread-safe weak data member handles 00116 * @see WeakView for thread-safe weak data member views 00117 * @see WeakHolder for thread-safe weak data member holders 00118 * 00119 * @author mf 2007.07.05 00120 */ 00121 class COH_EXPORT Object 00122 : public cloneable_spec<Object, 00123 extends<> > 00124 { 00125 friend class factory<Object>; 00126 00127 // ----- constructors --------------------------------------------------- 00128 00129 protected: 00130 /** 00131 * Construct a new Object. 00132 */ 00133 Object(); 00134 00135 /** 00136 * Copy constructor. 00137 */ 00138 Object(const Object& that); 00139 00140 private: 00141 /** 00142 * Blocked assignment operator. 00143 * 00144 * @internal 00145 */ 00146 Object& operator=(const Object&); 00147 00148 00149 // ----- Object interface ----------------------------------------------- 00150 00151 public: 00152 /** 00153 * Return true iff the specified Object is "equal" to this Object. 00154 * 00155 * This method implements an <i>equivalence relation</i> on Objects: 00156 * <ul> 00157 * <li>It is <i>reflexive</i>: for any non-null handle 00158 * <code>h</code>, <code>h->equals(h)</code> must return 00159 * <code>true</code>. 00160 * <li>It is <i>symmetric</i>: for any non-null handles 00161 * <code>h1</code> and <code>h2</code>, <code>h1->equals(h2)</code> 00162 * should return <code>true</code> if and only if 00163 * <code>h2->equals(h1)</code> returns <code>true</code>. 00164 * <li>It is <i>transitive</i>: for any non-null handles 00165 * <code>h1</code>, <code>h2</code>, and <code>h3</code>, if 00166 * <code>h1->equals(h2)</code> returns <code>true</code> and 00167 * <code>h2->equals(h3)</code> returns <code>true</code>, then 00168 * <code>h1->equals(h3)</code> should return <code>true</code>. 00169 * <li>It is <i>consistent</i>: for any non-null handles 00170 * <code>h1</code> and <code>h2</code>, multiple invocations of 00171 * <tt>h1->equals(h2)</tt> consistently return <code>true</code> 00172 * or consistently return <tt>false</tt>, provided no 00173 * information used in comparisons on the objects is modified. 00174 * <li>If the supplied handle is <tt>NULL</tt> then <tt>false</tt> 00175 * must be returned. 00176 * </ul> 00177 * 00178 * The default implementation is a reference equality comparison. 00179 * 00180 * @param v the Object::View to compare against, may be <tt>NULL</tt> 00181 * 00182 * @return <tt>true</tt> iff the given handle references an Object 00183 * that is "equal" to this Object 00184 * 00185 * @see #equals(Object::View v1, Object::View v2) 00186 */ 00187 virtual bool equals(Object::View v) const; 00188 00189 /** 00190 * Return a hash code value for the Object. This method is supported 00191 * for the benefit of hash-based containers. 00192 * 00193 * The general contract of <code>hashCode</code> is: 00194 * <ul> 00195 * <li>Whenever it is invoked on the same Object more than once 00196 * during an execution of an application, the <tt>hashCode</tt> 00197 * method must consistently return the same value, provided no 00198 * information used in <tt>equals</tt> comparisons on the object 00199 * is modified. This value need not remain consistent from one 00200 * execution of an application to another execution of the same 00201 * application. 00202 * <li>If two Objects are equal according to the <tt>equals</tt> 00203 * method, then calling the <code>hashCode</code> method on each 00204 * of the two Objects must produce the same value. 00205 * <li>It is <em>not</em> required that if two Objects are unequal 00206 * according to the <tt>equals</tt> method, then calling the 00207 * <tt>hashCode</tt> method on each of the two objects must 00208 * produce distinct results. However, the programmer should be 00209 * aware that producing distinct results for unequal objects may 00210 * improve the performance of hash-based containers. 00211 * </ul> 00212 * 00213 * The default implementation is identity based. 00214 * 00215 * @return a hash code value for this Object 00216 */ 00217 virtual size32_t hashCode() const; 00218 00219 /** 00220 * Return a handle to a deep copy of the original Object. 00221 * 00222 * The returned clone should be sufficient decoupled from the original 00223 * such that further modifications to the original Object will not be 00224 * visible within the cloned object. More specifically, the following 00225 * is expected to hold true. 00226 * 00227 * @code 00228 * h->clone() != h && 00229 * h->clone()->equals(h) && 00230 * typeid(*h) == typeid(*(h->clone())) 00231 * @endcode 00232 * 00233 * Note that this suggests that data members of a cloned object are 00234 * expected to cloned if they are tested for equality (via a call to 00235 * equals) within the cloned object's equals method. If a data member 00236 * is compared via reference equality, or not even considered within 00237 * equals, then it does not necessarily need to be deeply cloned. 00238 * 00239 * Object is cloneable, but it's derived classes are not automatically 00240 * cloneable, and CloneNotSupportedExceptions are thrown. To be made 00241 * cloneable the derived class should use the cloneable_spec<> helper 00242 * template in its declaration, and define a protected copy constructor. 00243 * The derived class does not need to override this method, as that is 00244 * done by the cloneable_spec<> template. 00245 * 00246 * @return a copy of the original Object 00247 * 00248 * @throws CloneNotSupportedException if the object cannot be deep 00249 * cloned 00250 * 00251 * @see isImmutable() 00252 */ 00253 virtual Object::Handle clone() const; 00254 00255 /** 00256 * Return <tt>true</tt> iff no further changes can be made to the 00257 * Object, that would effect the outcome of a call to its equals method. 00258 * Except for Objects which are naturally immutable (such as String), 00259 * being immutable generally implies that the Object is only referenced 00260 * via const pointers or views. Objects which hold references to child 00261 * Objects, may need to take the immutability of their children into 00262 * account when determining their own immutability. 00263 * 00264 * This extended check is not performed by the default implementation, 00265 * but can be integrated into the immutability checks by overriding 00266 * this method, as well as making use of MemberHandles to reference 00267 * child Objects. 00268 * 00269 * A typical derived implementation may look as follows: 00270 * 00271 * <pre> 00272 * bool isImmutable() const 00273 * { 00274 * if (m_fImmutable) // check recorded state 00275 * { 00276 * return true; // already marked as immutable, avoid calculation 00277 * } 00278 * else if (Object::isImmutable()) // ensure shallow immutability 00279 * { 00280 * // ensure deep immutability 00281 * if (m_child1->isImmutable() && m_child2->isImmutable() ... 00282 * && m_childN->isImmutable()) 00283 * { 00284 * // record and return immutability 00285 * return m_fImmutable = true; 00286 * } 00287 * // some Objects which comprise this Object are still mutable 00288 * } 00289 * return false; 00290 * } 00291 * </pre> 00292 * 00293 * The default implementation return true iff the Object is only 00294 * referenced via const pointers and or views. 00295 * 00296 * @return true iff the Object is immutable 00297 */ 00298 virtual bool isImmutable() const; 00299 00300 /** 00301 * Output a human-readable description of this Object to the given 00302 * stream. 00303 * 00304 * coherence::lang::operator<<(std::ostream, Object::View) is defined 00305 * and will call into the toStream method, to output Objects. If a 00306 * managed String object is desired, the COH_TO_STRING macro can be used 00307 * to build up a String from streamable contents. 00308 * 00309 * @code 00310 * Object::View vKey = ... 00311 * Object::View vValue = ... 00312 * std::cout << vKey << " = " << vValue << std::endl; 00313 * 00314 * String::Handle hs = COH_TO_STRING(vKey << " = " << vValue); 00315 * @endcode 00316 * 00317 * @param out the stream used to output the description 00318 */ 00319 virtual void toStream(std::ostream& out) const; 00320 00321 /** 00322 * Return an estimate as to the shallow byte size of the object. 00323 * 00324 * The shallow size should not include the cost of referenced managed 00325 * objects, or non-fixed dynamically allocated memory. That for a 00326 * given object it is assumed that a call to this method will always 00327 * return the same value. 00328 * 00329 * For classes defined via the class_spec template an auto-generated 00330 * implementation is provided which utilizes the standard C sizeof() 00331 * operator to compute the size. User defined implementations are 00332 * only needed to account for dynamic memory allocated during 00333 * construction. 00334 * 00335 * @return the approximate shallow byte size of the object 00336 */ 00337 virtual size32_t sizeOf() const; 00338 00339 00340 // ----- synchronization and notification interface --------------------- 00341 00342 public: 00343 /** 00344 * Block the calling thread while waiting for notification. 00345 * 00346 * The caller must be synchronized on the Object's monitor when calling 00347 * this method. The monitor will be automatically released while the 00348 * thread awaits notification, and re-acquired before the call returns. 00349 * This method is subject to spurious wakeups, and the caller should 00350 * externally verify that the condition being waited for has been 00351 * reached. 00352 * 00353 * To synchronize on an object, the COH_SYNCHRONIZED macro is used. 00354 * The macro defines a block of code which is a critical section, 00355 * during which no other thread may acquire synchronization on the same 00356 * object. 00357 * 00358 * @code 00359 * Object::Handle hObject = ... 00360 * COH_SYNCHRONIZED (hObject) 00361 * { 00362 * while (testSomeCondition() == false) 00363 * { 00364 * hObject->wait(); 00365 * } 00366 * } 00367 * @endcode 00368 * 00369 * @see notify 00370 * @see notifyAll 00371 */ 00372 void wait() const; 00373 00374 /** 00375 * Block the calling thread while waiting for notification. 00376 * 00377 * The caller must be synchronized on the Object's monitor when calling 00378 * this method. The monitor will be automatically released while the 00379 * thread awaits notification, and re-acquired before the call returns. 00380 * This method is subject to spurious wakeups, and the caller should 00381 * externally verify that the condition being waited for has been 00382 * reached. 00383 * 00384 * @param cMillis the duration to wait to wait, a value of zero will 00385 * wait indefinitely for notification 00386 * 00387 * @see wait 00388 * @see notify 00389 * @see notifyAll 00390 */ 00391 void wait(int64_t cMillis) const; 00392 00393 /** 00394 * Notify a waiting thread. 00395 * 00396 * The caller must be synchronized on the Object's monitor when calling 00397 * this method. 00398 * 00399 * @code 00400 * Object::Handle hObject = ... 00401 * COH_SYNCHRONIZED (hObject) 00402 * { 00403 * setSomeCondition(true); 00404 * hObject->notify(); 00405 * } 00406 * @endcode 00407 * 00408 * @see wait 00409 * @see notifyAll 00410 */ 00411 void notify() const; 00412 00413 /** 00414 * Notify all waiting threads. 00415 * 00416 * The caller must be synchronized on the Object's monitor when calling 00417 * this method. 00418 * 00419 * @see wait 00420 * @see notify 00421 */ 00422 void notifyAll() const; 00423 00424 private: 00425 /** 00426 * Enter the Object's monitor, waiting as long as necessary. 00427 * <p/> 00428 * The monitor supports recursive entry, allowing the same thread to 00429 * reenter the same monitor. The thread must exit the monitor the 00430 * same number of times, by calling the exitMonitor, for the Monitor 00431 * to be released. 00432 * 00433 * It is recommended that the COH_SYNCHRONIZED macro be used in place 00434 * of direct calls to enterMonitor/exitMonitor. The use of this macro 00435 * only requires public level view access to the Object 00436 * <pre> 00437 * // outside of synchronized block 00438 * COH_SYNCHRONIZED (vObject) // monitor entered 00439 * { 00440 * // critical section goes here 00441 * // ... 00442 * // ... 00443 * } // monitor automatically exited 00444 * // outside of synchronized block 00445 * </pre> 00446 * 00447 * @see _exitMonitor 00448 */ 00449 void _enterMonitor() const 00450 { 00451 LifeCycle nState(m_atomicLifeCycle.peek()); 00452 if (nState.value.fEscaped || 00453 nState.value.nMonitor != LifeCycle::flat) 00454 { 00455 _enterMonitorInternal(); 00456 } 00457 else 00458 { 00459 // pointer acts as a nested synchronization counter 00460 m_pCondition = reinterpret_cast<NativeCondition*>( 00461 reinterpret_cast<size_t>(m_pCondition) + 1); 00462 } 00463 } 00464 00465 /** 00466 * @internal 00467 */ 00468 void _enterMonitorInternal() const; 00469 00470 /** 00471 * Exit the Object's monitor. 00472 * 00473 * This must be called by the thread which locked the monitor. 00474 * 00475 * @see _enterMonitor 00476 */ 00477 void _exitMonitor() const 00478 { 00479 LifeCycle nState(m_atomicLifeCycle.peek()); 00480 if (nState.value.fEscaped || 00481 nState.value.nMonitor != LifeCycle::flat) 00482 { 00483 _exitMonitorInternal(); 00484 } 00485 else if (m_pCondition == NULL) 00486 { 00487 coh_throw_illegal_state("Invalid monitor state"); 00488 } 00489 else 00490 { 00491 // pointer acts as a nested synchronization counter 00492 m_pCondition = reinterpret_cast<NativeCondition*>( 00493 reinterpret_cast<size_t>(m_pCondition) - 1); 00494 } 00495 } 00496 00497 /** 00498 * @internal 00499 */ 00500 void _exitMonitorInternal() const; 00501 00502 /** 00503 * Acquire the shared read lock for the Object's data members. 00504 * 00505 * The data member read/write lock is intended for protecting small 00506 * sections of non-blocking code, such as primitive data-member access 00507 * and assignment. The read lock does support limited recursion, 00508 * and each call to acquire must be matched by a corresponding 00509 * call to release. For more advanced read/write lock support the 00510 * ThreadGate class should be utilized. 00511 * 00512 * The member read lock may be acquired using the 00513 * COH_SYNCHRONIZED_MEMBER_READ macro. 00514 * 00515 * @see SynchronizedMemberReadBlock 00516 * @see coherence::util::ThreadGate 00517 */ 00518 void _acquireMemberReadLock() const 00519 { 00520 LifeCycle nState(m_atomicLifeCycle.peek()); 00521 if (nState.value.fEscaped) 00522 { 00523 _acquireMemberReadLockInternal(); 00524 } 00525 else if (nState.value.nMemberWriteLockState == 00526 LifeCycle::gate_open && 00527 nState.value.cMemberReadLock < LifeCycle::max_read_locks) 00528 { 00529 ++nState.value.cMemberReadLock; 00530 m_atomicLifeCycle.poke(nState); 00531 } 00532 else 00533 { 00534 coh_throw_illegal_state("Invalid lock state"); 00535 } 00536 } 00537 00538 /** 00539 * Release the read lock for the Object's data members 00540 */ 00541 void _releaseMemberReadLock() const 00542 { 00543 LifeCycle nState(m_atomicLifeCycle.peek()); 00544 if (nState.value.fEscaped) 00545 { 00546 _releaseMemberReadLockInternal(); 00547 } 00548 else if (nState.value.nMemberWriteLockState == 00549 LifeCycle::gate_open && 00550 nState.value.cMemberReadLock > 0) 00551 { 00552 --nState.value.cMemberReadLock; 00553 m_atomicLifeCycle.poke(nState); 00554 } 00555 else 00556 { 00557 coh_throw_illegal_state("Invalid lock state"); 00558 } 00559 } 00560 00561 /** 00562 * Acquire the write lock for the Object's data members. 00563 * 00564 * Unlike the member read lock, write locks do not support 00565 * recursion, nor do they support lock promotion from a read to a 00566 * write lock. Attempts to use them such a manor will result in 00567 * dead-lock. 00568 * 00569 * The member write lock may be acquired using the 00570 * COH_SYNCHRONIZED_MEMBER_WRITE macro. 00571 * 00572 * @see SynchronizedMemberWriteBlock 00573 */ 00574 void _acquireMemberWriteLock() const 00575 { 00576 LifeCycle nState(m_atomicLifeCycle.peek()); 00577 if (nState.value.fEscaped) 00578 { 00579 _acquireMemberWriteLockInternal(); 00580 } 00581 else if (nState.value.nMemberWriteLockState == 00582 LifeCycle::gate_open && 00583 nState.value.cMemberReadLock == 0) 00584 { 00585 nState.value.nMemberWriteLockState = LifeCycle::gate_closed; 00586 m_atomicLifeCycle.poke(nState); 00587 } 00588 else 00589 { 00590 coh_throw_illegal_state("Invalid lock state"); 00591 } 00592 } 00593 00594 /** 00595 * Release the write lock for the Object's data members. 00596 */ 00597 void _releaseMemberWriteLock() const 00598 { 00599 LifeCycle nState(m_atomicLifeCycle.peek()); 00600 if (nState.value.fEscaped) 00601 { 00602 _releaseMemberWriteLockInternal(); 00603 } 00604 else if (nState.value.nMemberWriteLockState == 00605 LifeCycle::gate_closed) 00606 { 00607 nState.value.nMemberWriteLockState = LifeCycle::gate_open; 00608 m_atomicLifeCycle.poke(nState); 00609 } 00610 else 00611 { 00612 coh_throw_illegal_state("Invalid lock state"); 00613 } 00614 } 00615 00616 00617 // ----- reference counting interface ----------------------------------- 00618 00619 public: 00620 /** 00621 * @internal 00622 * 00623 * Increment the non-const reference count for this Object. 00624 * 00625 * NOTE: This method is intended for use by smart pointers such as 00626 * TypedHandle, and its usage should be limited. 00627 * 00628 * This operation must return <tt>NULL</tt> if the Object is 00629 * immutable. 00630 * 00631 * @param fEscaped true if the attaching reference is visible to 00632 * multiple threads 00633 * 00634 * @return a pointer to the Object or <tt>NULL</tt> if new non-const 00635 * attachments are disallowed 00636 * 00637 * @see _detach 00638 */ 00639 Object* _attach(bool fEscaped = true) 00640 { 00641 LifeCycle nState(m_atomicLifeCycle.peek()); 00642 00643 if (nState.value.fEscaped) 00644 { 00645 return _attachEscaped(fEscaped); 00646 } 00647 00648 unsigned int cHandle = nState.value.cHandle; 00649 if (fEscaped || cHandle == 0 || 00650 cHandle == LifeCycle::max_handles || (cHandle == 1 && 00651 nState.value.nWeakReference == LifeCycle::inflated)) 00652 { 00653 return _attachCaptured(fEscaped); 00654 } 00655 00656 // inlined non-escaped attach 00657 nState.value.cHandle = cHandle + 1; 00658 m_atomicLifeCycle.poke(nState); 00659 return this; 00660 } 00661 00662 /** 00663 * @internal 00664 * 00665 * Increment the const reference count for this Object. 00666 * 00667 * NOTE: This method is intended for use by smart pointers such as 00668 * TypedHandle, and its usage should be limited. 00669 * 00670 * @param fEscaped true if the attaching reference is visible to 00671 * multiple threads 00672 * 00673 * @return a constant pointer to the Object, or <tt>NULL</tt> if new 00674 * const attachments are disallowed 00675 * 00676 * @see _detach 00677 */ 00678 const Object* _attach(bool fEscaped = true) const 00679 { 00680 LifeCycle nState(m_atomicLifeCycle.peek()); 00681 00682 if (nState.value.fEscaped) 00683 { 00684 return _attachEscaped(fEscaped); 00685 } 00686 00687 unsigned int cView = nState.value.cView; 00688 unsigned int cTotal = nState.value.cHandle + cView; 00689 if (fEscaped || cView == LifeCycle::max_views || cTotal == 0 || 00690 (cTotal == 1 && 00691 nState.value.nWeakReference == LifeCycle::inflated)) 00692 { 00693 return _attachCaptured(fEscaped); 00694 } 00695 00696 // inlined non-escaped attach 00697 nState.value.cView = cView + 1; 00698 m_atomicLifeCycle.poke(nState); 00699 return this; 00700 } 00701 00702 /** 00703 * @internal 00704 * 00705 * Return a WeakReference to this Object. 00706 * 00707 * Unlike non-weak attachments, there is no corresponding _detachWeak, 00708 * as the return type is a handle. 00709 * 00710 * See the WeakHandle template class which will automatically manage 00711 * the weak attachment to the Object. 00712 * 00713 * NOTE: This method is intended for use by smart pointers such as 00714 * WeakHandle, and its usage should be limited. 00715 * 00716 * @see WeakReference 00717 * @see WeakHandle 00718 * 00719 * @return a WeakReference to this Object 00720 */ 00721 TypedHandle<WeakReference> _attachWeak(); 00722 00723 /** 00724 * @internal 00725 * 00726 * Return a WeakReference View to this Object. 00727 * 00728 * Unlike non-weak attachments, there is no corresponding _detachWeak, 00729 * as the return type is a handle. 00730 * 00731 * See the WeakView template class which will automatically manage the 00732 * weak attachment to the Object. 00733 * 00734 * NOTE: This method is intended for use by smart pointers such as 00735 * WeakHandle, and its usage should be limited. 00736 * 00737 * @see WeakReference 00738 * @see WeakView 00739 * 00740 * @return a WeakReference to this Object 00741 */ 00742 TypedHandle<const WeakReference> _attachWeak() const; 00743 00744 /** 00745 * @internal 00746 * 00747 * Decrement the non-const reference count for this Object and 00748 * automatically delete this Object if the total reference count drops 00749 * to zero. 00750 * 00751 * NOTE: This method is intended for use by smart pointers such as 00752 * TypedHandle, and its usage should be limited. 00753 * 00754 * @see _attach 00755 * 00756 * @param fEscaped true if the detaching reference had attached as 00757 * escaped 00758 */ 00759 void _detach(bool fEscaped = true) 00760 { 00761 LifeCycle nState(m_atomicLifeCycle.peek()); 00762 00763 if (fEscaped || nState.value.fEscaped) 00764 { 00765 _detachEscaped(fEscaped); 00766 return; 00767 } 00768 00769 unsigned int cHandle = nState.value.cHandle; 00770 if (cHandle <= 1 || (cHandle == 2 && 00771 nState.value.nWeakReference == LifeCycle::inflated) || 00772 cHandle == LifeCycle::max_handles) 00773 { 00774 _detachCaptured(); 00775 } 00776 else 00777 { 00778 // inlined non-escaped detach 00779 nState.value.cHandle = cHandle - 1; 00780 m_atomicLifeCycle.poke(nState); 00781 } 00782 } 00783 00784 /** 00785 * @internal 00786 * 00787 * Decrement the const reference count for this Object and 00788 * automatically delete this Object if the total reference count drops 00789 * to zero. 00790 * 00791 * NOTE: This method is intended for use by smart pointers such as 00792 * TypedHandle, and its usage should be limited. 00793 * 00794 * @see _attach 00795 * 00796 * @param fEscaped true if the detaching reference had attached as 00797 * escaped 00798 */ 00799 void _detach(bool fEscaped) const 00800 { 00801 LifeCycle nState(m_atomicLifeCycle.peek()); 00802 00803 if (fEscaped || nState.value.fEscaped) 00804 { 00805 _detachEscaped(fEscaped); 00806 return; 00807 } 00808 00809 unsigned int cView = nState.value.cView; 00810 if (cView == 0 || cView == LifeCycle::max_views || 00811 (nState.value.cHandle == 0 && (cView == 1 || (cView == 2 && 00812 nState.value.nWeakReference == LifeCycle::inflated)))) 00813 { 00814 _detachCaptured(); 00815 } 00816 else 00817 { 00818 // inline non-escaped detach 00819 nState.value.cView = cView - 1; 00820 m_atomicLifeCycle.poke(nState); 00821 } 00822 } 00823 00824 /** 00825 * Return if the Object is currently marked as escaped. 00826 * 00827 * An escaped object is one which is known to be reachable by multiple 00828 * threads. 00829 * 00830 * @param fAttemptCapture true if capture should be attempted 00831 * 00832 * @return true if the Object is currently marked as escaped 00833 */ 00834 bool _isEscaped(bool fAttemptCapture = true) const 00835 { 00836 LifeCycle nState(m_atomicLifeCycle.peek()); 00837 00838 if (fAttemptCapture && nState.value.fEscaped && 00839 nState.value.cHandle + nState.value.cView == 1) 00840 { 00841 // escaped but capture appears to be possible, attempt it 00842 return !_capture(m_atomicLifeCycle.get()); 00843 } 00844 00845 return nState.value.fEscaped; 00846 } 00847 00848 00849 // ----- life cycle events ---------------------------------------------- 00850 00851 protected: 00852 /** 00853 * Event called once the Object has finished being constructed. 00854 * Specifically when the first attachment is made. This provides a 00855 * safe point at which Handles/Views to "this" can be created. It is 00856 * not safe to create Handles/Views to an Object from within its 00857 * constructor, thus any operations which rely upon this should be 00858 * deferred until the onInit event is triggered. 00859 * 00860 * As with all event methods any derived implementation should 00861 * include a call to the super class's implementation. Specifically 00862 * delegation to Object::onInit() must eventually occur or an 00863 * IllegalStateException will result. 00864 * 00865 * The default implementation calls the onInit() method of each of the 00866 * Object's SmartMembers. 00867 */ 00868 virtual void onInit(); 00869 00870 /** 00871 * Event called when the Object becomes only referenced via const 00872 * pointers (Views). Assuming a const-correct class, once this method 00873 * returns no further visible changes can be made to the object. 00874 * 00875 * As with all event methods any derived implementation should include 00876 * a call to the super class's implementation. 00877 * 00878 * The default implementation calls the onConst() method of each of 00879 * the Object's SmartMembers. 00880 * 00881 * @see isImmutable 00882 */ 00883 virtual void onConst(); 00884 00885 /** 00886 * Event called when the guarding Object's escape state changes. 00887 * 00888 * As with all event methods any derived implementation should include 00889 * a call to the super class's implementation. Ultimately delegation 00890 * must reach Object::onEscape() which will perform the actual act of 00891 * preparing the object for multi/single-threaded access. 00892 * 00893 * Throughout the call it is guaranteed that the object remains visible 00894 * to only a single thread, and as such it is not allowable to perform 00895 * an action from within this method which would attempt to escape this 00896 * object. 00897 * 00898 * @param fEscaped true if the object is escaping, false if it is 00899 * being captured 00900 */ 00901 virtual void onEscape(bool fEscaped) const; 00902 00903 00904 // ----- helper methods ------------------------------------------------- 00905 00906 protected: 00907 /** 00908 * Return a reference to the constructed base Object. 00909 * 00910 * This reference is suitable for use in derived class constructors as 00911 * the Object class will have completed construction. 00912 * 00913 * @return the Object reference 00914 */ 00915 Object& self() 00916 { 00917 return *this; 00918 } 00919 00920 /** 00921 * Return a reference to the constructed base Object. 00922 * 00923 * @return the const Object reference 00924 */ 00925 const Object& self() const 00926 { 00927 return *this; 00928 } 00929 00930 private: 00931 /** 00932 * Destroy the object. 00933 */ 00934 void _destroy() const; 00935 00936 /** 00937 * Escape an Object 00938 */ 00939 void _escape() const; 00940 00941 /** 00942 * Attempt to capture an escaped object. 00943 * 00944 * @param nState the state of the object 00945 * 00946 * @return true if the object was captured 00947 */ 00948 bool _capture(LifeCycle nState) const; 00949 00950 /** 00951 * Increment the Object's view reference count on a non-escaped object. 00952 * 00953 * @param fEscaped true if the view will be escaped 00954 * 00955 * @return NULL on failed attach otherwise return this 00956 */ 00957 const Object* _attachCaptured(bool fEscaped) const; 00958 00959 /** 00960 * Increment the Object's handle reference count on an non-escaped object. 00961 * 00962 * @param fEscaped true if the handle will be escaped 00963 * 00964 * @return NULL on failed attach otherwise return this 00965 */ 00966 Object* _attachCaptured(bool fEscaped); 00967 00968 /** 00969 * Increment the Object's view reference count on an escaped object. 00970 * 00971 * @param fEscaped true if the view will be escaped 00972 * 00973 * @return NULL on failed attach otherwise return this 00974 */ 00975 const Object* _attachEscaped(bool fEscaped) const; 00976 00977 /** 00978 * Increment the Object's handle reference count on an escaped object. 00979 * 00980 * @param fEscaped true if the view will be escaped 00981 * 00982 * @return NULL on failed attach otherwise return this 00983 */ 00984 Object* _attachEscaped(bool fEscaped); 00985 00986 /** 00987 * Decrement the Object's view reference count on a non-escaped object. 00988 */ 00989 void _detachCaptured() const; 00990 00991 /** 00992 * Decrement the Object's handle reference count on an non-escaped object. 00993 */ 00994 void _detachCaptured(); 00995 00996 /** 00997 * Decrement the Object's view reference count on an escaped object. 00998 * 00999 * @param fEscaped true if the view is escaped 01000 */ 01001 void _detachEscaped(bool fEscaped) const; 01002 01003 /** 01004 * Decrement the Object's handle reference count on an escaped object. 01005 * 01006 * @param fEscaped true if the view is escaped 01007 */ 01008 void _detachEscaped(bool fEscaped); 01009 01010 /** 01011 * Acquire the shared read lock for the Object's data members. 01012 * 01013 * The data member read/write lock is intended for protecting small 01014 * sections of non-blocking code, such as primitive data-member access 01015 * and assignment. The read lock does support limited recursion, 01016 * and each call to acquire must be matched by a corresponding 01017 * call to release. For more advanced read/write lock support the 01018 * ThreadGate class should be utilized. 01019 * 01020 * The member read lock may be acquired using the 01021 * COH_SYNCHRONIZED_MEMBER_READ macro. 01022 * 01023 * @see SynchronizedMemberReadBlock 01024 * @see coherence::util::ThreadGate 01025 */ 01026 void _acquireMemberReadLockInternal() const; 01027 01028 /** 01029 * Release the read lock for the Object's data members 01030 */ 01031 void _releaseMemberReadLockInternal() const; 01032 01033 /** 01034 * Acquire the write lock for the Object's data members. 01035 * 01036 * Unlike the member read lock, write locks do not support 01037 * recursion, nor do they support lock promotion from a read to a 01038 * write lock. Attempts to use them such a manor will result in 01039 * dead-lock. 01040 * 01041 * The member write lock may be acquired using the 01042 * COH_SYNCHRONIZED_MEMBER_WRITE macro. 01043 * 01044 * @see SynchronizedMemberWriteBlockm 01045 */ 01046 void _acquireMemberWriteLockInternal() const; 01047 01048 /** 01049 * Release the write lock for the Object's data members. 01050 */ 01051 void _releaseMemberWriteLockInternal() const; 01052 01053 /** 01054 * Return the WeakReference associated with this Object, creating one 01055 * if necessary. 01056 * 01057 * @return the WeakReference associated with this Object 01058 */ 01059 TypedHandle<WeakReference> _ensureWeakReference() const; 01060 01061 /** 01062 * Return the NativeCondition which backs the Object's monitor, 01063 * creating one if necessary. 01064 * 01065 * The life of the returned condition is bounded to the Object. 01066 * 01067 * @return the NativeCondition which backs the Object's monitor 01068 */ 01069 NativeCondition& _ensureMonitor() const; 01070 01071 01072 // ----- static methods ------------------------------------------------- 01073 01074 public: 01075 /** 01076 * Compare two Objects for equality. 01077 * 01078 * This method implements an <i>equivalence relation</i> for two 01079 * potentially <tt>NULL</tt> handles. 01080 * 01081 * @param v1 the first Object to compare 01082 * @param v2 the second Object to compare 01083 * 01084 * @return <tt>true</tt> iff v1 and v2 are <tt>NULL</tt> or 01085 * reference Objects which are equal 01086 */ 01087 static bool equals(Object::View v1, Object::View v2); 01088 01089 /** 01090 * Output an Object to a stream. 01091 * 01092 * If the handle is NULL then the string "NULL" will be written to the 01093 * stream. 01094 * 01095 * @param out the stream used to output the Object 01096 * @param v the Object to output 01097 */ 01098 static void toStream(std::ostream& out, Object::View v); 01099 01100 /** 01101 * Return a clone of the supplied Object. 01102 * 01103 * @param v the Object to clone 01104 * 01105 * @return a clone of the Object, or NULL if NULL was supplied 01106 */ 01107 static Object::Handle clone(Object::View v); 01108 01109 /** 01110 * Return the hashCode for the specified object or 0 if the object is 01111 * NULL. 01112 * 01113 * @param v the Object to hash 01114 * 01115 * @return the object's hash. 01116 */ 01117 static size32_t hashCode(Object::View v) 01118 { 01119 return NULL == get_pointer(v) ? 0 : v->hashCode(); 01120 } 01121 01122 01123 // ----- memory management ---------------------------------------------- 01124 01125 protected: 01126 /** 01127 * @internal 01128 * 01129 * Default allocator for Objects. 01130 * 01131 * @param cb the number of bytes to allocate 01132 * 01133 * @return the allocated memory 01134 * 01135 * @throws IllegalStateException if the allocation fails 01136 */ 01137 static void* operator new(size_t cb); 01138 01139 /** 01140 * @internal 01141 * 01142 * Default deallocator for Objects. 01143 * 01144 * @param po the memory to deallocate 01145 */ 01146 static void operator delete(void* po); 01147 01148 01149 // ----- data members --------------------------------------------------- 01150 01151 private: 01152 /** 01153 * 64bit atomic Object life-cycle. 01154 */ 01155 mutable NativeAtomic64 m_atomicLifeCycle; 01156 01157 /** 01158 * Pointer to the NativeCondition which is used to implement the 01159 * Object's monitor functionality. 01160 * 01161 * The validity of this pointer is governed by the Object's 01162 * life-cycle. A non-NULL pointer is not sufficient to ensure that 01163 * the condition is ready for use. 01164 */ 01165 mutable NativeCondition* m_pCondition; 01166 01167 /** 01168 * The WeakReference to this Object. 01169 * 01170 * The validity of this handle is governed by the Object's life-cycle. 01171 * A non-NULL handle is not sufficient to ensure that the reference is 01172 * ready for use. 01173 */ 01174 mutable WeakReference* m_pWeakThis; 01175 01176 /** 01177 * Pointer to the top of the stack of SmartMembers bound to this 01178 * Object, or NULL if none exist. 01179 */ 01180 mutable SmartMember* m_pSmartMemberStack; 01181 01182 01183 // ----- friends -------------------------------------------------------- 01184 01185 template<class> friend class Volatile; 01186 friend class SmartMember; 01187 friend class SynchronizedBlock; 01188 friend class SynchronizedMemberReadBlock; 01189 friend class SynchronizedMemberWriteBlock; 01190 friend class System; 01191 }; 01192 01193 01194 // ----- non-member operators and functions --------------------------------- 01195 01196 /** 01197 * Output a human-readable description of the specified Object to the given 01198 * stream. 01199 * 01200 * @param out the stream used to output the description 01201 * @param o the Object to describe 01202 * 01203 * @return the supplied stream 01204 */ 01205 COH_EXPORT std::ostream& operator<<(std::ostream& out, const Object& o); 01206 01207 /** 01208 * Object reference equality operator. 01209 */ 01210 inline bool operator==(const Object* cpo, const Object::View &v) 01211 { 01212 return ((const Object*) get_pointer(v)) == cpo; 01213 } 01214 01215 /** 01216 * Object reference equality operator. 01217 */ 01218 inline bool operator==(const Object::View &v, const Object* cpo) 01219 { 01220 return ((const Object*) get_pointer(v)) == cpo; 01221 } 01222 01223 /** 01224 * Object reference equality operator. 01225 */ 01226 inline bool operator==(const Object::View& v1, const Object::View& v2) 01227 { 01228 return ((const Object*) get_pointer(v1)) == 01229 ((const Object*) get_pointer(v2)); 01230 } 01231 01232 /** 01233 * Object reference inequality operator. 01234 */ 01235 inline bool operator!=(const Object* cpo, const Object::View& v) 01236 { 01237 return ((const Object*) get_pointer(v)) != cpo; 01238 } 01239 01240 /** 01241 * Object reference inequality operator. 01242 */ 01243 inline bool operator!=(const Object::View& v, const Object* cpo) 01244 { 01245 return ((const Object*) get_pointer(v)) != cpo; 01246 } 01247 01248 /** 01249 * Object reference inequality operator. 01250 */ 01251 inline bool operator!=(const Object::View& v1, const Object::View& v2) 01252 { 01253 return ((const Object*) get_pointer(v1)) != 01254 ((const Object*) get_pointer(v2)); 01255 } 01256 01257 /** 01258 * @internal 01259 * 01260 * Specialized extends implementation for classes deriving directly from Object. 01261 * 01262 * This specialization bring Object in virtually (as interfaces derive from it 01263 * virtually as well. 01264 */ 01265 template<class A> class COH_EXPORT_SPEC extends<Object, A> 01266 : public virtual Object 01267 { 01268 public: 01269 typedef Void<Object> inherited; 01270 typedef A alias; 01271 typedef Object inherited_literal; 01272 }; 01273 01274 /** 01275 * @internal 01276 * 01277 * Specialized extends implementation for classes deriving directly from Object. 01278 * 01279 * This specialization bring Object in virtually (as interfaces derive from it 01280 * virtually as well. 01281 */ 01282 template<> class COH_EXPORT_SPEC extends<Object, Void<Object> > 01283 : public virtual Object 01284 { 01285 public: 01286 typedef Void<Object> inherited; 01287 typedef Void<Object> alias; 01288 typedef Object inherited_literal; 01289 }; 01290 01291 COH_CLOSE_NAMESPACE2 01292 01293 #endif // COH_OBJECT_HPP