Oracle Coherence for C++ API
Release 3.6.1.0
E18813-01

- Main Page
- Namespaces
- Classes
- Files

# coherence/lang/Object.hpp

    00001 /*
    00002 * Object.hpp
    00003 *
    00004 * Copyright (c) 2000, 2010, 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     };
    01272
    01273 /**
    01274 * @internal
    01275 *
    01276 * Specialized extends implementation for classes deriving directly from Object.
    01277 *
    01278 * This specialization bring Object in virtually (as interfaces derive from it
    01279 * virtually as well.
    01280 */
    01281 template<> class COH_EXPORT_SPEC extends<Object, Void<Object> >
    01282     : public virtual Object
    01283     {
    01284     public:
    01285         typedef Void<Object> inherited;
    01286         typedef Void<Object> alias;
    01287     };
    01288
    01289 COH_CLOSE_NAMESPACE2
    01290
    01291 #endif // COH_OBJECT_HPP

Copyright © 2000, 2010, Oracle and/or its affiliates. All rights reserved.