blob: 1ebd05b50fb22a8339c0f706823f77a90ba5ee92 [file] [log] [blame]
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.debugger.impl;
import com.intellij.openapi.diagnostic.Logger;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
public class EventQueue<E> {
private static final Logger LOG = Logger.getInstance("#com.intellij.debugger.impl.EventQueue");
private final LinkedList[] myEvents;
private final ReentrantLock myLock;
private final Condition myEventsAvailable;
private volatile E myCurrentEvent;
private volatile boolean myIsClosed = false;
public EventQueue (int countPriorities) {
myLock = new ReentrantLock();
myEventsAvailable = myLock.newCondition();
myEvents = new LinkedList[countPriorities];
for (int i = 0; i < myEvents.length; i++) {
myEvents[i] = new LinkedList<E>();
}
}
public boolean pushBack(@NotNull E event, int priority) {
if(LOG.isDebugEnabled()) {
LOG.debug("pushBack event " + event);
}
myLock.lock();
try {
if (isClosed()) {
return false;
}
getEventsList(priority).addFirst(event);
myEventsAvailable.signalAll();
}
finally {
myLock.unlock();
}
return true;
}
public boolean put(@NotNull E event, int priority) {
if(LOG.isDebugEnabled()) {
LOG.debug("put event " + event);
}
myLock.lock();
try {
if (isClosed()) {
return false;
}
getEventsList(priority).offer(event);
myEventsAvailable.signalAll();
}
finally {
myLock.unlock();
}
return true;
}
private LinkedList<E> getEventsList(final int priority) {
return (LinkedList<E>)myEvents[priority];
}
public void close(){
myLock.lock();
try {
myIsClosed = true;
myEventsAvailable.signalAll();
}
finally {
myLock.unlock();
}
}
private E getEvent() throws EventQueueClosedException {
myLock.lock();
try {
while (true) {
if(myIsClosed) {
throw new EventQueueClosedException();
}
for (int i = 0; i < myEvents.length; i++) {
final E event = getEventsList(i).poll();
if (event != null) {
return event;
}
}
myEventsAvailable.awaitUninterruptibly();
}
}
finally {
myLock.unlock();
}
}
public E get() throws EventQueueClosedException {
try {
return myCurrentEvent = getEvent();
}
catch (EventQueueClosedException e) {
myCurrentEvent = null; // cleanup
throw e;
}
}
public boolean isClosed() {
return myIsClosed;
}
public E getCurrentEvent() {
return myCurrentEvent;
}
@NotNull
public List<E> clearQueue() {
final List<E> allEvents = new ArrayList<E>();
for (int i = 0; i < myEvents.length; i++) {
final LinkedList<E> eventList = getEventsList(i);
for (E event = eventList.poll(); event != null; event = eventList.poll()) {
allEvents.add(event);
}
}
return allEvents;
}
}