001/* 002 * ModeShape (http://www.modeshape.org) 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.modeshape.common.collection.ring; 018 019import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; 020 021/** 022 * A {@link Pointer} that will always stay behind a number of other {@link Pointer} instances, which can be safely and dynamically 023 * added or removed. 024 * 025 * @author Randall Hauch (rhauch@redhat.com) 026 */ 027public class TrailingPointer extends Pointer implements DependentOnPointers { 028 029 private static final Pointer[] EMPTY_ARRAY = new Pointer[0]; 030 031 private static final AtomicReferenceFieldUpdater<TrailingPointer, Pointer[]> STAY_BEHIND_UPDATER = AtomicReferenceFieldUpdater.newUpdater(TrailingPointer.class, 032 Pointer[].class, 033 "stayBehinds"); 034 035 private volatile Pointer[] stayBehinds; 036 037 public TrailingPointer( Pointer... stayBehinds ) { 038 this(INITIAL_VALUE, stayBehinds); 039 } 040 041 public TrailingPointer( long initialValue, 042 Pointer... stayBehinds ) { 043 super(initialValue); 044 this.stayBehinds = stayBehinds == null ? EMPTY_ARRAY : stayBehinds; 045 } 046 047 @Override 048 public long get() { 049 return Math.max(INITIAL_VALUE, Pointers.getMinimum(stayBehinds, Long.MAX_VALUE) - 1L); 050 } 051 052 @Override 053 public void stayBehind( Pointer... pointers ) { 054 Pointers.add(this, STAY_BEHIND_UPDATER, null, pointers); 055 } 056 057 @Override 058 public boolean ignore( Pointer pointer ) { 059 return Pointers.remove(this, STAY_BEHIND_UPDATER, pointer); 060 } 061 062 @Override 063 public String toString() { 064 StringBuilder sb = new StringBuilder(); 065 sb.append('['); 066 for (Pointer pointer : stayBehinds) { 067 sb.append(pointer).append(","); 068 } 069 sb.append(']'); 070 return sb.toString(); 071 } 072}