Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/objectstyle/cayenne/util/RequestQueue.java


1   /* ====================================================================
2    * 
3    * The ObjectStyle Group Software License, Version 1.0 
4    *
5    * Copyright (c) 2002-2003 The ObjectStyle Group 
6    * and individual authors of the software.  All rights reserved.
7    *
8    * Redistribution and use in source and binary forms, with or without
9    * modification, are permitted provided that the following conditions
10   * are met:
11   *
12   * 1. Redistributions of source code must retain the above copyright
13   *    notice, this list of conditions and the following disclaimer. 
14   *
15   * 2. Redistributions in binary form must reproduce the above copyright
16   *    notice, this list of conditions and the following disclaimer in
17   *    the documentation and/or other materials provided with the
18   *    distribution.
19   *
20   * 3. The end-user documentation included with the redistribution, if
21   *    any, must include the following acknowlegement:  
22   *       "This product includes software developed by the 
23   *        ObjectStyle Group (http://objectstyle.org/)."
24   *    Alternately, this acknowlegement may appear in the software itself,
25   *    if and wherever such third-party acknowlegements normally appear.
26   *
27   * 4. The names "ObjectStyle Group" and "Cayenne" 
28   *    must not be used to endorse or promote products derived
29   *    from this software without prior written permission. For written 
30   *    permission, please contact andrus@objectstyle.org.
31   *
32   * 5. Products derived from this software may not be called "ObjectStyle"
33   *    nor may "ObjectStyle" appear in their names without prior written
34   *    permission of the ObjectStyle Group.
35   *
36   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39   * DISCLAIMED.  IN NO EVENT SHALL THE OBJECTSTYLE GROUP OR
40   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
42   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
43   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
44   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
45   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
46   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47   * SUCH DAMAGE.
48   * ====================================================================
49   *
50   * This software consists of voluntary contributions made by many
51   * individuals on behalf of the ObjectStyle Group.  For more
52   * information on the ObjectStyle Group, please see
53   * <http://objectstyle.org/>.
54   *
55   */
56  package org.objectstyle.cayenne.util;
57  
58  import java.util.ArrayList;
59  import java.util.Collections;
60  import java.util.List;
61  
62  import org.apache.log4j.Logger;
63  
64  /**
65   * RequestQueue implements a FIFO queue for threads waiting for a 
66   * particular event, resource, etc. Each thread will wait 
67   * in the queue until either of the following events happen:
68   * 
69   * <ul>
70   *    <li>Thread is already #1 in the queue and an awaited event occurrs.</li>
71   *     <li>Thread timeout interval expired.</li>
72   *    <li>Thread was interrupted (this is a quick way to remove thread from the queue).</li>
73   * </ul>
74   * 
75   * If any of the conditions above ocurrs, thread will be removed from the queue. 
76   * 
77   * @author Andrei Adamchik
78   */
79  public class RequestQueue {
80      private static Logger logObj = Logger.getLogger(RequestQueue.class);
81  
82      protected List queue;
83      protected int maxSize;
84      protected int timeout;
85  
86      /**
87       * Constructor for RequestQueue.
88       * 
89       * @param maxSize - maximum allowed number of threads in the queue.
90       * @param timeout - timeout in milliseconds that determines maximum possible 
91       * wait time in the queue.
92       */
93      public RequestQueue(int maxSize, int timeout) {
94          this.maxSize = maxSize;
95          this.timeout = timeout;
96          this.queue = Collections.synchronizedList(new ArrayList());
97      }
98  
99      public int getSize() {
100         synchronized (queue) {
101             return queue.size();
102         }
103     }
104 
105     /**
106      * Queues current thread. This will block 
107      * the caller till the thread is dequeued as a result
108      * of another thread calling <code>dequeueFirst</code>
109      * or as a result of a timeout. 
110      * 
111      * @return an object that represents an event or resource that
112      * caused 
113      */
114     public RequestDequeue queueThread() {
115         RequestDequeue result = new RequestDequeue(Thread.currentThread().getName());
116 
117         // queue up request
118         synchronized (queue) {
119             if (maxSize > 0 && queue.size() >= maxSize) {
120                 result.setDequeueEventCode(RequestDequeue.QUEUE_FULL);
121                 return result;
122             }
123 
124             queue.add(result);
125         }
126 
127         // wait
128         synchronized (result) {
129             boolean interrupted = false;
130             try {
131 
132                 if (logObj.isDebugEnabled()) {
133                     logObj.debug(
134                         "thread [" + result.getName() + "] queued for " + timeout);
135                 }
136 
137                 // release lock and wait
138                 result.wait(timeout);
139             } catch (InterruptedException e) {
140                 interrupted = true;
141             }
142 
143             // wait is over, remove itself from the queue
144             if (result.getDequeueEventCode() != RequestDequeue.DEQUEUE_SUCCESS) {
145 
146                 // timeout or interrupted
147                 synchronized (queue) {
148                     queue.remove(result);
149                     int code =
150                         (interrupted)
151                             ? RequestDequeue.INTERRUPTED
152                             : RequestDequeue.TIMED_OUT;
153                     result.setDequeueEventCode(code);
154                 }
155             }
156 
157             return result;
158         }
159     }
160 
161     /**
162      * Releases the first thread in the queue. 
163      */
164     public boolean dequeueFirst(Object dequeuedObj) {
165         RequestDequeue first = null;
166         // Make sure we avoid nested locks - locking both queue & result object
167         // at the same time - this is a potential deadlock.
168 
169         synchronized (queue) {
170             if (queue.size() > 0) {
171                 first = (RequestDequeue) queue.get(0);
172                 queue.remove(0);
173             }
174         }
175 
176         // this is true when the queue contained at least one object
177         if (first != null) {
178             synchronized (first) {
179                 first.setDequeueEventObject(dequeuedObj);
180                 first.setDequeueEventCode(RequestDequeue.DEQUEUE_SUCCESS);
181                 first.notifyAll();
182                 if (logObj.isDebugEnabled()) {
183                     logObj.debug("Dequeued thread: " + first.getName());
184                 }
185             }
186 
187             return true;
188         } else {
189             return false;
190         }
191     }
192 }