Oracle Coherence for C++ API
Release 3.6.0.0

E15728-01

coherence/util/DualQueue.hpp

00001 /*
00002 * DualQueue.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_DUAL_QUEUE_HPP
00017 #define COH_DUAL_QUEUE_HPP
00018 
00019 #include "coherence/lang.ns"
00020 
00021 #include "coherence/util/AbstractConcurrentQueue.hpp"
00022 #include "coherence/util/Iterator.hpp"
00023 #include "coherence/util/List.hpp"
00024 
00025 COH_OPEN_NAMESPACE2(coherence,util)
00026 
00027 
00028 /**
00029 * The DualQueue is optimized for the producer consumer use case.
00030 *
00031 * Producers work on the tail of the queue, consumers operate on the head of
00032 * the queue.  The two portions of the queue are maintained as seperate lists,
00033 * and protected by seperate locks.
00034 *
00035 * When a consumer looks at the head of the queue, if it is empty, the head
00036 * and tail will be swaped.
00037 *
00038 * @author nsa 2008.02.13
00039 */
00040 class COH_EXPORT DualQueue
00041     : public class_spec<DualQueue,
00042         extends<AbstractConcurrentQueue> >
00043     {
00044     friend class factory<DualQueue>;
00045 
00046     // ----- constructors ---------------------------------------------------
00047 
00048     protected:
00049         /**
00050         * Create a new DaulQueue.
00051         *
00052         * @return a new DualQueu
00053         */
00054         DualQueue();
00055 
00056 
00057     // ----- DualQueue interface --------------------------------------------
00058 
00059     protected:
00060         /**
00061         * Swap the head and the tail, but only if the head is empty and the
00062         * tail is not. The calling thread must already hold a the head lock.
00063         *
00064         * @return true iff the head and tail were swapped
00065         */
00066         virtual bool swapNoWait();
00067 
00068         /**
00069         * Return the head element list.
00070         *
00071         * @return the head element list
00072         */
00073         virtual List::Handle getHeadElementList();
00074 
00075         /**
00076         * Set the head element list.
00077         *
00078         * @param hList  the new head list to set
00079         */
00080         virtual void setHeadElementList(List::Handle hList);
00081 
00082         /**
00083         * Return the element list (tail).
00084         *
00085         * @return the element list
00086         */
00087         virtual List::Handle getElementList();
00088 
00089         /**
00090         * Set the element list (tail)
00091         *
00092         * @param hList  the new list to set
00093         */
00094         virtual void setElementList(List::Handle hList);
00095 
00096         /**
00097         * Return the head lock.
00098         *
00099         * @return the head lock
00100         */
00101         virtual Object::Handle getHeadLock();
00102 
00103 
00104     // ----- Queue interface ------------------------------------------------
00105 
00106     public:
00107         /**
00108         * {@inheritDoc}
00109         */
00110         virtual bool add(Object::Holder oh);
00111 
00112         /**
00113         * {@inheritDoc}
00114         */
00115         virtual bool addHead(Object::Holder oh);
00116 
00117         /**
00118         * {@inheritDoc}
00119         */
00120         virtual bool isEmpty() const;
00121 
00122         /**
00123         * {@inheritDoc}
00124         */
00125         virtual Object::Holder peekNoWait();
00126 
00127         /**
00128         * {@inheritDoc}
00129         */
00130         virtual Object::Holder removeNoWait();
00131 
00132 
00133     // ----- data members ---------------------------------------------------
00134 
00135     protected:
00136         /**
00137         * Lock protecting operations on the head of the queue, and tail
00138         * swapping. We cannot simply lock on the head element list as it
00139         * gets swapped with the tail.
00140         *
00141         * To avoid deadlock issues the Queue lock should never be obtained
00142         * while holding the head lock.
00143         *
00144         * For example:
00145         * <pre>
00146         * COH_SYNCHRONIZED(getHeadLock())
00147         *     {
00148         *     COH_SYNCHRONIZED(this)
00149         *         {
00150         *         // this is NOT ok
00151         *         }
00152         *     }
00153         * COH_SYNCHRONIZED(this)
00154         *     {
00155         *     COH_SYNCHRONIZED(getHeadLock())
00156         *         {
00157         *         // this is ok
00158         *         }
00159         *     }
00160         * </pre>
00161         *
00162         * The latter approach was chosen as it allows users of the DualQueue
00163         * to perform external synchronization without risking deadlock.
00164         */
00165         FinalHandle<Object> m_hHeadLock;
00166 
00167         /**
00168         * The List that backs the queue. For a dual queue the ElementList is
00169         * the tail.
00170         */
00171         MemberHandle<List> m_hElementList;
00172 
00173         /**
00174         * The storage for the head of the queue.
00175         */
00176         MemberHandle<List> m_hHeadElementList;
00177     };
00178 
00179 COH_CLOSE_NAMESPACE2
00180 
00181 #endif // COH_DUAL_QUEUE_HPP
Copyright © 2000, 2010, Oracle and/or its affiliates. All rights reserved.