00001 /* 00002 * Object.hpp 00003 * 00004 * Copyright (c) 2000, 2013, 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 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 when the shallow size is requested. 00328 * 00329 * The deep size should be the shallow size plus the size of any 00330 * referenced objects. Unlike the shallow size the deep size may change 00331 * over time. The default implementation provided by Object will 00332 * traverse the object graph of all managed objects which it references 00333 * and include their sizes in the computed deep size. In general it 00334 * is sufficient to simply delegate to super::sizeOf(true) for deep 00335 * calculations. 00336 * 00337 * For classes implemented via class_spec, a variant of this method 00338 * will be automatically produced which will utilize sizeof(*this) 00339 * to compute the shallow size, and super::sizeOf(true) to compute 00340 * the deep size. As such it is generally not necessary to provide 00341 * custom implmenetations of this method. 00342 * 00343 * @param fDeep true if the size should include the size of referenced 00344 * objects 00345 * 00346 * @return the approximate shallow byte size of the object 00347 */ 00348 virtual size64_t sizeOf(bool fDeep = false) const; 00349 00350 00351 // ----- synchronization and notification interface --------------------- 00352 00353 public: 00354 /** 00355 * Block the calling thread while waiting for notification. 00356 * 00357 * The caller must be synchronized on the Object's monitor when calling 00358 * this method. The monitor will be automatically released while the 00359 * thread awaits notification, and re-acquired before the call returns. 00360 * This method is subject to spurious wakeups, and the caller should 00361 * externally verify that the condition being waited for has been 00362 * reached. 00363 * 00364 * To synchronize on an object, the COH_SYNCHRONIZED macro is used. 00365 * The macro defines a block of code which is a critical section, 00366 * during which no other thread may acquire synchronization on the same 00367 * object. 00368 * 00369 * @code 00370 * Object::Handle hObject = ... 00371 * COH_SYNCHRONIZED (hObject) 00372 * { 00373 * while (testSomeCondition() == false) 00374 * { 00375 * hObject->wait(); 00376 * } 00377 * } 00378 * @endcode 00379 * 00380 * @see notify 00381 * @see notifyAll 00382 */ 00383 void wait() const; 00384 00385 /** 00386 * Block the calling thread while waiting for notification. 00387 * 00388 * The caller must be synchronized on the Object's monitor when calling 00389 * this method. The monitor will be automatically released while the 00390 * thread awaits notification, and re-acquired before the call returns. 00391 * This method is subject to spurious wakeups, and the caller should 00392 * externally verify that the condition being waited for has been 00393 * reached. 00394 * 00395 * @param cMillis the duration to wait to wait, a value of zero will 00396 * wait indefinitely for notification 00397 * 00398 * @see wait 00399 * @see notify 00400 * @see notifyAll 00401 */ 00402 void wait(int64_t cMillis) const; 00403 00404 /** 00405 * Notify a waiting thread. 00406 * 00407 * The caller must be synchronized on the Object's monitor when calling 00408 * this method. 00409 * 00410 * @code 00411 * Object::Handle hObject = ... 00412 * COH_SYNCHRONIZED (hObject) 00413 * { 00414 * setSomeCondition(true); 00415 * hObject->notify(); 00416 * } 00417 * @endcode 00418 * 00419 * @see wait 00420 * @see notifyAll 00421 */ 00422 void notify() const; 00423 00424 /** 00425 * Notify all waiting threads. 00426 * 00427 * The caller must be synchronized on the Object's monitor when calling 00428 * this method. 00429 * 00430 * @see wait 00431 * @see notify 00432 */ 00433 void notifyAll() const; 00434 00435 private: 00436 /** 00437 * Enter the Object's monitor, waiting as long as necessary. 00438 * <p/> 00439 * The monitor supports recursive entry, allowing the same thread to 00440 * reenter the same monitor. The thread must exit the monitor the 00441 * same number of times, by calling the exitMonitor, for the Monitor 00442 * to be released. 00443 * 00444 * It is recommended that the COH_SYNCHRONIZED macro be used in place 00445 * of direct calls to enterMonitor/exitMonitor. The use of this macro 00446 * only requires public level view access to the Object 00447 * <pre> 00448 * // outside of synchronized block 00449 * COH_SYNCHRONIZED (vObject) // monitor entered 00450 * { 00451 * // critical section goes here 00452 * // ... 00453 * // ... 00454 * } // monitor automatically exited 00455 * // outside of synchronized block 00456 * </pre> 00457 * 00458 * @see _exitMonitor 00459 */ 00460 void _enterMonitor() const 00461 { 00462 LifeCycle nState(m_atomicLifeCycle.peek()); 00463 if (nState.value.fEscaped || 00464 nState.value.nMonitor != LifeCycle::flat) 00465 { 00466 _enterMonitorInternal(); 00467 } 00468 else 00469 { 00470 // pointer acts as a nested synchronization counter 00471 m_pCondition = reinterpret_cast<NativeCondition*>( 00472 reinterpret_cast<size_t>(m_pCondition) + 1); 00473 } 00474 } 00475 00476 /** 00477 * @internal 00478 */ 00479 void _enterMonitorInternal() const; 00480 00481 /** 00482 * Exit the Object's monitor. 00483 * 00484 * This must be called by the thread which locked the monitor. 00485 * 00486 * @see _enterMonitor 00487 */ 00488 void _exitMonitor() const 00489 { 00490 LifeCycle nState(m_atomicLifeCycle.peek()); 00491 if (nState.value.fEscaped || 00492 nState.value.nMonitor != LifeCycle::flat) 00493 { 00494 _exitMonitorInternal(); 00495 } 00496 else if (m_pCondition == NULL) 00497 { 00498 coh_throw_illegal_state("Invalid monitor state"); 00499 } 00500 else 00501 { 00502 // pointer acts as a nested synchronization counter 00503 m_pCondition = reinterpret_cast<NativeCondition*>( 00504 reinterpret_cast<size_t>(m_pCondition) - 1); 00505 } 00506 } 00507 00508 /** 00509 * @internal 00510 */ 00511 void _exitMonitorInternal() const; 00512 00513 /** 00514 * Acquire the shared read lock for the Object's data members. 00515 * 00516 * The data member read/write lock is intended for protecting small 00517 * sections of non-blocking code, such as primitive data-member access 00518 * and assignment. The read lock does support limited recursion, 00519 * and each call to acquire must be matched by a corresponding 00520 * call to release. For more advanced read/write lock support the 00521 * ThreadGate class should be utilized. 00522 * 00523 * The member read lock may be acquired using the 00524 * COH_SYNCHRONIZED_MEMBER_READ macro. 00525 * 00526 * @see SynchronizedMemberReadBlock 00527 * @see coherence::util::ThreadGate 00528 */ 00529 void _acquireMemberReadLock() const 00530 { 00531 LifeCycle nState(m_atomicLifeCycle.peek()); 00532 if (nState.value.fEscaped) 00533 { 00534 _acquireMemberReadLockInternal(); 00535 } 00536 else if (nState.value.nMemberWriteLockState == 00537 LifeCycle::gate_open && 00538 nState.value.cMemberReadLock < LifeCycle::max_read_locks) 00539 { 00540 ++nState.value.cMemberReadLock; 00541 m_atomicLifeCycle.poke(nState); 00542 } 00543 else 00544 { 00545 coh_throw_illegal_state("Invalid lock state"); 00546 } 00547 } 00548 00549 /** 00550 * Release the read lock for the Object's data members 00551 */ 00552 void _releaseMemberReadLock() const 00553 { 00554 LifeCycle nState(m_atomicLifeCycle.peek()); 00555 if (nState.value.fEscaped) 00556 { 00557 _releaseMemberReadLockInternal(); 00558 } 00559 else if (nState.value.nMemberWriteLockState == 00560 LifeCycle::gate_open && 00561 nState.value.cMemberReadLock > 0) 00562 { 00563 --nState.value.cMemberReadLock; 00564 m_atomicLifeCycle.poke(nState); 00565 } 00566 else 00567 { 00568 coh_throw_illegal_state("Invalid lock state"); 00569 } 00570 } 00571 00572 /** 00573 * Cross the read barrier associated with the object's read write lock. 00574 */ 00575 void _readBarrier() const 00576 { 00577 m_atomicLifeCycle.get(); 00578 } 00579 00580 /** 00581 * Acquire the write lock for the Object's data members. 00582 * 00583 * Unlike the member read lock, write locks do not support 00584 * recursion, nor do they support lock promotion from a read to a 00585 * write lock. Attempts to use them such a manor will result in 00586 * dead-lock. 00587 * 00588 * The member write lock may be acquired using the 00589 * COH_SYNCHRONIZED_MEMBER_WRITE macro. 00590 * 00591 * @see SynchronizedMemberWriteBlock 00592 */ 00593 void _acquireMemberWriteLock() const 00594 { 00595 LifeCycle nState(m_atomicLifeCycle.peek()); 00596 if (nState.value.fEscaped) 00597 { 00598 _acquireMemberWriteLockInternal(); 00599 } 00600 else if (nState.value.nMemberWriteLockState == 00601 LifeCycle::gate_open && 00602 nState.value.cMemberReadLock == 0) 00603 { 00604 nState.value.nMemberWriteLockState = LifeCycle::gate_closed; 00605 m_atomicLifeCycle.poke(nState); 00606 } 00607 else 00608 { 00609 coh_throw_illegal_state("Invalid lock state"); 00610 } 00611 } 00612 00613 /** 00614 * Release the write lock for the Object's data members. 00615 */ 00616 void _releaseMemberWriteLock() const 00617 { 00618 LifeCycle nState(m_atomicLifeCycle.peek()); 00619 if (nState.value.fEscaped) 00620 { 00621 _releaseMemberWriteLockInternal(); 00622 } 00623 else if (nState.value.nMemberWriteLockState == 00624 LifeCycle::gate_closed) 00625 { 00626 nState.value.nMemberWriteLockState = LifeCycle::gate_open; 00627 m_atomicLifeCycle.poke(nState); 00628 } 00629 else 00630 { 00631 coh_throw_illegal_state("Invalid lock state"); 00632 } 00633 } 00634 00635 /** 00636 * Cross the write barrier associated with the object's read write lock. 00637 */ 00638 void _writeBarrier() const 00639 { 00640 m_atomicLifeCycle.update(0, 0); 00641 } 00642 00643 // ----- reference counting interface ----------------------------------- 00644 00645 public: 00646 /** 00647 * @internal 00648 * 00649 * Increment the non-const reference count for this Object. 00650 * 00651 * NOTE: This method is intended for use by smart pointers such as 00652 * TypedHandle, and its usage should be limited. 00653 * 00654 * This operation must return <tt>NULL</tt> if the Object is 00655 * immutable. 00656 * 00657 * @param fEscaped true if the attaching reference is visible to 00658 * multiple threads 00659 * 00660 * @return a pointer to the Object or <tt>NULL</tt> if new non-const 00661 * attachments are disallowed 00662 * 00663 * @see _detach 00664 */ 00665 Object* _attach(bool fEscaped = true) 00666 { 00667 LifeCycle nState(m_atomicLifeCycle.peek()); 00668 00669 if (nState.value.fEscaped) 00670 { 00671 return _attachEscaped(fEscaped); 00672 } 00673 00674 unsigned int cHandle = nState.value.cHandle; 00675 if (fEscaped || cHandle == 0 || 00676 cHandle == LifeCycle::max_handles || (cHandle == 1 && 00677 nState.value.nWeakReference == LifeCycle::inflated)) 00678 { 00679 return _attachCaptured(fEscaped); 00680 } 00681 00682 // inlined non-escaped attach 00683 nState.value.cHandle = cHandle + 1; 00684 m_atomicLifeCycle.poke(nState); 00685 return this; 00686 } 00687 00688 /** 00689 * @internal 00690 * 00691 * Increment the const reference count for this Object. 00692 * 00693 * NOTE: This method is intended for use by smart pointers such as 00694 * TypedHandle, and its usage should be limited. 00695 * 00696 * @param fEscaped true if the attaching reference is visible to 00697 * multiple threads 00698 * 00699 * @return a constant pointer to the Object, or <tt>NULL</tt> if new 00700 * const attachments are disallowed 00701 * 00702 * @see _detach 00703 */ 00704 const Object* _attach(bool fEscaped = true) const 00705 { 00706 LifeCycle nState(m_atomicLifeCycle.peek()); 00707 00708 if (nState.value.fEscaped) 00709 { 00710 return _attachEscaped(fEscaped); 00711 } 00712 00713 unsigned int cView = nState.value.cView; 00714 unsigned int cTotal = nState.value.cHandle + cView; 00715 if (fEscaped || cView == LifeCycle::max_views || cTotal == 0 || 00716 (cTotal == 1 && 00717 nState.value.nWeakReference == LifeCycle::inflated)) 00718 { 00719 return _attachCaptured(fEscaped); 00720 } 00721 00722 // inlined non-escaped attach 00723 nState.value.cView = cView + 1; 00724 m_atomicLifeCycle.poke(nState); 00725 return this; 00726 } 00727 00728 /** 00729 * @internal 00730 * 00731 * Return a WeakReference to this Object. 00732 * 00733 * Unlike non-weak attachments, there is no corresponding _detachWeak, 00734 * as the return type is a handle. 00735 * 00736 * See the WeakHandle template class which will automatically manage 00737 * the weak attachment to the Object. 00738 * 00739 * NOTE: This method is intended for use by smart pointers such as 00740 * WeakHandle, and its usage should be limited. 00741 * 00742 * @see WeakReference 00743 * @see WeakHandle 00744 * 00745 * @return a WeakReference to this Object 00746 */ 00747 TypedHandle<WeakReference> _attachWeak(); 00748 00749 /** 00750 * @internal 00751 * 00752 * Return a WeakReference View to this Object. 00753 * 00754 * Unlike non-weak attachments, there is no corresponding _detachWeak, 00755 * as the return type is a handle. 00756 * 00757 * See the WeakView template class which will automatically manage the 00758 * weak attachment to the Object. 00759 * 00760 * NOTE: This method is intended for use by smart pointers such as 00761 * WeakHandle, and its usage should be limited. 00762 * 00763 * @see WeakReference 00764 * @see WeakView 00765 * 00766 * @return a WeakReference to this Object 00767 */ 00768 TypedHandle<const WeakReference> _attachWeak() const; 00769 00770 /** 00771 * @internal 00772 * 00773 * Decrement the non-const reference count for this Object and 00774 * automatically delete this Object if the total reference count drops 00775 * to zero. 00776 * 00777 * NOTE: This method is intended for use by smart pointers such as 00778 * TypedHandle, and its usage should be limited. 00779 * 00780 * @see _attach 00781 * 00782 * @param fEscaped true if the detaching reference had attached as 00783 * escaped 00784 */ 00785 void _detach(bool fEscaped = true) 00786 { 00787 LifeCycle nState(m_atomicLifeCycle.peek()); 00788 00789 if (fEscaped || nState.value.fEscaped) 00790 { 00791 _detachEscaped(fEscaped); 00792 return; 00793 } 00794 00795 unsigned int cHandle = nState.value.cHandle; 00796 if (cHandle <= 1 || (cHandle == 2 && 00797 nState.value.nWeakReference == LifeCycle::inflated) || 00798 cHandle == LifeCycle::max_handles) 00799 { 00800 _detachCaptured(); 00801 } 00802 else 00803 { 00804 // inlined non-escaped detach 00805 nState.value.cHandle = cHandle - 1; 00806 m_atomicLifeCycle.poke(nState); 00807 } 00808 } 00809 00810 /** 00811 * @internal 00812 * 00813 * Decrement the const reference count for this Object and 00814 * automatically delete this Object if the total reference count drops 00815 * to zero. 00816 * 00817 * NOTE: This method is intended for use by smart pointers such as 00818 * TypedHandle, and its usage should be limited. 00819 * 00820 * @see _attach 00821 * 00822 * @param fEscaped true if the detaching reference had attached as 00823 * escaped 00824 */ 00825 void _detach(bool fEscaped) const 00826 { 00827 LifeCycle nState(m_atomicLifeCycle.peek()); 00828 00829 if (fEscaped || nState.value.fEscaped) 00830 { 00831 _detachEscaped(fEscaped); 00832 return; 00833 } 00834 00835 unsigned int cView = nState.value.cView; 00836 if (cView == 0 || cView == LifeCycle::max_views || 00837 (nState.value.cHandle == 0 && (cView == 1 || (cView == 2 && 00838 nState.value.nWeakReference == LifeCycle::inflated)))) 00839 { 00840 _detachCaptured(); 00841 } 00842 else 00843 { 00844 // inline non-escaped detach 00845 nState.value.cView = cView - 1; 00846 m_atomicLifeCycle.poke(nState); 00847 } 00848 } 00849 00850 /** 00851 * Return if the Object is currently marked as escaped. 00852 * 00853 * An escaped object is one which is known to be reachable by multiple 00854 * threads. 00855 * 00856 * @param fAttemptCapture true if capture should be attempted 00857 * 00858 * @return true if the Object is currently marked as escaped 00859 */ 00860 bool _isEscaped(bool fAttemptCapture = true) const 00861 { 00862 LifeCycle nState(m_atomicLifeCycle.peek()); 00863 00864 if (fAttemptCapture && nState.value.fEscaped && 00865 nState.value.cHandle + nState.value.cView == 1) 00866 { 00867 // escaped but capture appears to be possible, attempt it 00868 return !_capture(m_atomicLifeCycle.get()); 00869 } 00870 00871 return nState.value.fEscaped; 00872 } 00873 00874 00875 // ----- life cycle events ---------------------------------------------- 00876 00877 protected: 00878 /** 00879 * Event called once the Object has finished being constructed. 00880 * Specifically when the first attachment is made. This provides a 00881 * safe point at which Handles/Views to "this" can be created. It is 00882 * not safe to create Handles/Views to an Object from within its 00883 * constructor, thus any operations which rely upon this should be 00884 * deferred until the onInit event is triggered. 00885 * 00886 * As with all event methods any derived implementation should 00887 * include a call to the super class's implementation. Specifically 00888 * delegation to Object::onInit() must eventually occur or an 00889 * IllegalStateException will result. 00890 * 00891 * The default implementation calls the onInit() method of each of the 00892 * Object's SmartMembers. 00893 */ 00894 virtual void onInit(); 00895 00896 /** 00897 * Event called when the Object becomes only referenced via const 00898 * pointers (Views). Assuming a const-correct class, once this method 00899 * returns no further visible changes can be made to the object. 00900 * 00901 * As with all event methods any derived implementation should include 00902 * a call to the super class's implementation. 00903 * 00904 * The default implementation calls the onConst() method of each of 00905 * the Object's SmartMembers. 00906 * 00907 * @see isImmutable 00908 */ 00909 virtual void onConst(); 00910 00911 /** 00912 * Event called when the guarding Object's escape state changes. 00913 * 00914 * As with all event methods any derived implementation should include 00915 * a call to the super class's implementation. Ultimately delegation 00916 * must reach Object::onEscape() which will perform the actual act of 00917 * preparing the object for multi/single-threaded access. 00918 * 00919 * Throughout the call it is guaranteed that the object remains visible 00920 * to only a single thread, and as such it is not allowable to perform 00921 * an action from within this method which would attempt to escape this 00922 * object. 00923 * 00924 * @param fEscaped true if the object is escaping, false if it is 00925 * being captured 00926 */ 00927 virtual void onEscape(bool fEscaped) const; 00928 00929 00930 // ----- helper methods ------------------------------------------------- 00931 00932 protected: 00933 /** 00934 * Return a reference to the constructed base Object. 00935 * 00936 * This reference is suitable for use in derived class constructors as 00937 * the Object class will have completed construction. 00938 * 00939 * @return the Object reference 00940 */ 00941 Object& self() 00942 { 00943 return *this; 00944 } 00945 00946 /** 00947 * Return a reference to the constructed base Object. 00948 * 00949 * @return the const Object reference 00950 */ 00951 const Object& self() const 00952 { 00953 return *this; 00954 } 00955 00956 private: 00957 /** 00958 * Destroy the object. 00959 */ 00960 void _destroy() const; 00961 00962 /** 00963 * Escape an Object 00964 */ 00965 void _escape() const; 00966 00967 /** 00968 * Attempt to capture an escaped object. 00969 * 00970 * @param nState the state of the object 00971 * 00972 * @return true if the object was captured 00973 */ 00974 bool _capture(LifeCycle nState) const; 00975 00976 /** 00977 * Increment the Object's view reference count on a non-escaped object. 00978 * 00979 * @param fEscaped true if the view will be escaped 00980 * 00981 * @return NULL on failed attach otherwise return this 00982 */ 00983 const Object* _attachCaptured(bool fEscaped) const; 00984 00985 /** 00986 * Increment the Object's handle reference count on an non-escaped object. 00987 * 00988 * @param fEscaped true if the handle will be escaped 00989 * 00990 * @return NULL on failed attach otherwise return this 00991 */ 00992 Object* _attachCaptured(bool fEscaped); 00993 00994 /** 00995 * Increment the Object's view reference count on an escaped object. 00996 * 00997 * @param fEscaped true if the view will be escaped 00998 * 00999 * @return NULL on failed attach otherwise return this 01000 */ 01001 const Object* _attachEscaped(bool fEscaped) const; 01002 01003 /** 01004 * Increment the Object's handle reference count on an escaped object. 01005 * 01006 * @param fEscaped true if the view will be escaped 01007 * 01008 * @return NULL on failed attach otherwise return this 01009 */ 01010 Object* _attachEscaped(bool fEscaped); 01011 01012 /** 01013 * Decrement the Object's view reference count on a non-escaped object. 01014 */ 01015 void _detachCaptured() const; 01016 01017 /** 01018 * Decrement the Object's handle reference count on an non-escaped object. 01019 */ 01020 void _detachCaptured(); 01021 01022 /** 01023 * Decrement the Object's view reference count on an escaped object. 01024 * 01025 * @param fEscaped true if the view is escaped 01026 */ 01027 void _detachEscaped(bool fEscaped) const; 01028 01029 /** 01030 * Decrement the Object's handle reference count on an escaped object. 01031 * 01032 * @param fEscaped true if the view is escaped 01033 */ 01034 void _detachEscaped(bool fEscaped); 01035 01036 /** 01037 * Acquire the shared read lock for the Object's data members. 01038 * 01039 * The data member read/write lock is intended for protecting small 01040 * sections of non-blocking code, such as primitive data-member access 01041 * and assignment. The read lock does support limited recursion, 01042 * and each call to acquire must be matched by a corresponding 01043 * call to release. For more advanced read/write lock support the 01044 * ThreadGate class should be utilized. 01045 * 01046 * The member read lock may be acquired using the 01047 * COH_SYNCHRONIZED_MEMBER_READ macro. 01048 * 01049 * @see SynchronizedMemberReadBlock 01050 * @see coherence::util::ThreadGate 01051 */ 01052 void _acquireMemberReadLockInternal() const; 01053 01054 /** 01055 * Release the read lock for the Object's data members 01056 */ 01057 void _releaseMemberReadLockInternal() const; 01058 01059 /** 01060 * Acquire the write lock for the Object's data members. 01061 * 01062 * Unlike the member read lock, write locks do not support 01063 * recursion, nor do they support lock promotion from a read to a 01064 * write lock. Attempts to use them such a manor will result in 01065 * dead-lock. 01066 * 01067 * The member write lock may be acquired using the 01068 * COH_SYNCHRONIZED_MEMBER_WRITE macro. 01069 * 01070 * @see SynchronizedMemberWriteBlockm 01071 */ 01072 void _acquireMemberWriteLockInternal() const; 01073 01074 /** 01075 * Release the write lock for the Object's data members. 01076 */ 01077 void _releaseMemberWriteLockInternal() const; 01078 01079 /** 01080 * Return the WeakReference associated with this Object, creating one 01081 * if necessary. 01082 * 01083 * @return the WeakReference associated with this Object 01084 */ 01085 TypedHandle<WeakReference> _ensureWeakReference() const; 01086 01087 /** 01088 * Return the NativeCondition which backs the Object's monitor, 01089 * creating one if necessary. 01090 * 01091 * The life of the returned condition is bounded to the Object. 01092 * 01093 * @return the NativeCondition which backs the Object's monitor 01094 */ 01095 NativeCondition& _ensureMonitor() const; 01096 01097 01098 // ----- static methods ------------------------------------------------- 01099 01100 public: 01101 /** 01102 * Compare two Objects for equality. 01103 * 01104 * This method implements an <i>equivalence relation</i> for two 01105 * potentially <tt>NULL</tt> handles. 01106 * 01107 * @param v1 the first Object to compare 01108 * @param v2 the second Object to compare 01109 * 01110 * @return <tt>true</tt> iff v1 and v2 are <tt>NULL</tt> or 01111 * reference Objects which are equal 01112 */ 01113 static bool equals(Object::View v1, Object::View v2); 01114 01115 /** 01116 * Output an Object to a stream. 01117 * 01118 * If the handle is NULL then the string "NULL" will be written to the 01119 * stream. 01120 * 01121 * @param out the stream used to output the Object 01122 * @param v the Object to output 01123 */ 01124 static void toStream(std::ostream& out, Object::View v); 01125 01126 /** 01127 * Return a clone of the supplied Object. 01128 * 01129 * @param v the Object to clone 01130 * 01131 * @return a clone of the Object, or NULL if NULL was supplied 01132 */ 01133 static Object::Handle clone(Object::View v); 01134 01135 /** 01136 * Return the hashCode for the specified object or 0 if the object is 01137 * NULL. 01138 * 01139 * @param v the Object to hash 01140 * 01141 * @return the object's hash. 01142 */ 01143 static size32_t hashCode(Object::View v) 01144 { 01145 return NULL == get_pointer(v) ? 0 : v->hashCode(); 01146 } 01147 01148 01149 // ----- memory management ---------------------------------------------- 01150 01151 protected: 01152 /** 01153 * @internal 01154 * 01155 * Default allocator for Objects. 01156 * 01157 * @param cb the number of bytes to allocate 01158 * 01159 * @return the allocated memory 01160 * 01161 * @throws IllegalStateException if the allocation fails 01162 */ 01163 static void* operator new(size_t cb); 01164 01165 /** 01166 * @internal 01167 * 01168 * Default deallocator for Objects. 01169 * 01170 * @param po the memory to deallocate 01171 */ 01172 static void operator delete(void* po); 01173 01174 01175 // ----- data members --------------------------------------------------- 01176 01177 private: 01178 /** 01179 * 64bit atomic Object life-cycle. 01180 */ 01181 mutable NativeAtomic64 m_atomicLifeCycle; 01182 01183 /** 01184 * Pointer to the NativeCondition which is used to implement the 01185 * Object's monitor functionality. 01186 * 01187 * The validity of this pointer is governed by the Object's 01188 * life-cycle. A non-NULL pointer is not sufficient to ensure that 01189 * the condition is ready for use. 01190 */ 01191 mutable NativeCondition* m_pCondition; 01192 01193 /** 01194 * The WeakReference to this Object. 01195 * 01196 * The validity of this handle is governed by the Object's life-cycle. 01197 * A non-NULL handle is not sufficient to ensure that the reference is 01198 * ready for use. 01199 */ 01200 mutable WeakReference* m_pWeakThis; 01201 01202 /** 01203 * Pointer to the top of the stack of SmartMembers bound to this 01204 * Object, or NULL if none exist. 01205 */ 01206 mutable SmartMember* m_pSmartMemberStack; 01207 01208 01209 // ----- friends -------------------------------------------------------- 01210 01211 template<class> friend class Volatile; 01212 friend class SmartMember; 01213 friend class SynchronizedBlock; 01214 friend class SynchronizedMemberReadBlock; 01215 friend class SynchronizedMemberWriteBlock; 01216 friend class System; 01217 }; 01218 01219 01220 // ----- non-member operators and functions --------------------------------- 01221 01222 /** 01223 * Output a human-readable description of the specified Object to the given 01224 * stream. 01225 * 01226 * @param out the stream used to output the description 01227 * @param o the Object to describe 01228 * 01229 * @return the supplied stream 01230 */ 01231 COH_EXPORT std::ostream& operator<<(std::ostream& out, const Object& o); 01232 01233 /** 01234 * Object reference equality operator. 01235 */ 01236 inline bool operator==(const Object* cpo, const Object::View &v) 01237 { 01238 return ((const Object*) get_pointer(v)) == cpo; 01239 } 01240 01241 /** 01242 * Object reference equality operator. 01243 */ 01244 inline bool operator==(const Object::View &v, const Object* cpo) 01245 { 01246 return ((const Object*) get_pointer(v)) == cpo; 01247 } 01248 01249 /** 01250 * Object reference equality operator. 01251 */ 01252 inline bool operator==(const Object::View& v1, const Object::View& v2) 01253 { 01254 return ((const Object*) get_pointer(v1)) == 01255 ((const Object*) get_pointer(v2)); 01256 } 01257 01258 /** 01259 * Object reference inequality operator. 01260 */ 01261 inline bool operator!=(const Object* cpo, const Object::View& v) 01262 { 01263 return ((const Object*) get_pointer(v)) != cpo; 01264 } 01265 01266 /** 01267 * Object reference inequality operator. 01268 */ 01269 inline bool operator!=(const Object::View& v, const Object* cpo) 01270 { 01271 return ((const Object*) get_pointer(v)) != cpo; 01272 } 01273 01274 /** 01275 * Object reference inequality operator. 01276 */ 01277 inline bool operator!=(const Object::View& v1, const Object::View& v2) 01278 { 01279 return ((const Object*) get_pointer(v1)) != 01280 ((const Object*) get_pointer(v2)); 01281 } 01282 01283 /** 01284 * @internal 01285 * 01286 * Specialized extends implementation for classes deriving directly from Object. 01287 * 01288 * This specialization bring Object in virtually (as interfaces derive from it 01289 * virtually as well. 01290 */ 01291 template<class A> class COH_EXPORT_SPEC extends<Object, A> 01292 : public virtual Object 01293 { 01294 public: 01295 typedef Void<Object> inherited; 01296 typedef A alias; 01297 typedef Object inherited_literal; 01298 }; 01299 01300 /** 01301 * @internal 01302 * 01303 * Specialized extends implementation for classes deriving directly from Object. 01304 * 01305 * This specialization bring Object in virtually (as interfaces derive from it 01306 * virtually as well. 01307 */ 01308 template<> class COH_EXPORT_SPEC extends<Object, Void<Object> > 01309 : public virtual Object 01310 { 01311 public: 01312 typedef Void<Object> inherited; 01313 typedef Void<Object> alias; 01314 typedef Object inherited_literal; 01315 }; 01316 01317 COH_CLOSE_NAMESPACE2 01318 01319 #endif // COH_OBJECT_HPP