Oracle Fusion Middleware C++ API Reference for Oracle Coherence
12c (12.1.2)

E26041-01

coherence/lang/Object.hpp

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
Copyright © 2000, 2013, Oracle and/or its affiliates. All rights reserved.