com.liferay.portal.kernel.concurrent.BatchablePipe Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of portal-service Show documentation
Show all versions of portal-service Show documentation
Contains interfaces for the portal services. Interfaces are only loaded by the global class loader and are shared by all plugins.
/**
* Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or (at your option)
* any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*/
package com.liferay.portal.kernel.concurrent;
import java.util.concurrent.atomic.AtomicMarkableReference;
import java.util.concurrent.atomic.AtomicReference;
/**
* @author Shuyang Zhou
*/
public class BatchablePipe {
public BatchablePipe() {
_headEntry = new Entry(null);
_lastEntryReference = new AtomicReference>(_headEntry);
}
public boolean put(IncreasableEntry increasableEntry) {
Entry newEntry = new Entry(increasableEntry);
while (true) {
if (_doIncrease(increasableEntry)) {
return false;
}
Entry lastEntryLink = _lastEntryReference.get();
Entry nextEntryLink = lastEntryLink._nextEntry.getReference();
if (nextEntryLink == null) {
if (lastEntryLink._nextEntry.compareAndSet(
null, newEntry, false, false)) {
_lastEntryReference.set(newEntry);
return true;
}
}
else {
_lastEntryReference.compareAndSet(lastEntryLink, nextEntryLink);
}
}
}
public IncreasableEntry take() {
boolean[] marked = {false};
take:
while (true) {
Entry predecessorEntry = _headEntry;
Entry currentEntry =
predecessorEntry._nextEntry.getReference();
while (currentEntry != null) {
Entry successorEntry = currentEntry._nextEntry.get(
marked);
if (marked[0]) {
if (!predecessorEntry._nextEntry.compareAndSet(
currentEntry, successorEntry, false, false)) {
continue take;
}
currentEntry = predecessorEntry._nextEntry.getReference();
continue;
}
if (currentEntry._nextEntry.compareAndSet(
successorEntry, successorEntry, false, true)) {
return currentEntry._increasableEntry;
}
continue take;
}
return null;
}
}
private boolean _doIncrease(IncreasableEntry increasableEntry) {
boolean[] marked = {false};
retry:
while (true) {
Entry predecessorEntry = _headEntry;
Entry currentEntry =
predecessorEntry._nextEntry.getReference();
while (currentEntry != null) {
Entry successorEntry = currentEntry._nextEntry.get(
marked);
if (marked[0]) {
if (!predecessorEntry._nextEntry.compareAndSet(
currentEntry, successorEntry, false, false)) {
continue retry;
}
currentEntry = predecessorEntry._nextEntry.getReference();
continue;
}
if (currentEntry._increasableEntry.getKey().equals(
increasableEntry.getKey())) {
return currentEntry._increasableEntry.increase(
increasableEntry.getValue());
}
predecessorEntry = currentEntry;
currentEntry = successorEntry;
}
_lastEntryReference.set(predecessorEntry);
return false;
}
}
private final Entry _headEntry;
private final AtomicReference> _lastEntryReference;
private static class Entry {
private Entry(IncreasableEntry increasableEntry) {
_increasableEntry = increasableEntry;
_nextEntry = new AtomicMarkableReference>(null, false);
}
private IncreasableEntry _increasableEntry;
private AtomicMarkableReference> _nextEntry;
}
}