| /* |
| * Copyright (c) 2011-2013, 2015 Eike Stepper (Berlin, Germany) and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * Eike Stepper - initial API and implementation |
| * Simon McDuff - bug 201266 |
| * Simon McDuff - bug 230832 |
| */ |
| package org.eclipse.net4j.util.ref; |
| |
| import java.lang.ref.Reference; |
| import java.lang.ref.ReferenceQueue; |
| import java.util.concurrent.atomic.AtomicBoolean; |
| |
| /** |
| * @author Eike Stepper |
| * @since 3.6 |
| */ |
| public abstract class CleanableReferenceQueue<T> extends ReferenceQueue<T> |
| { |
| public static final int ALL_WORK_PER_POLL = ReferenceQueueWorker.ALL_WORK_PER_POLL; |
| |
| public static final int DEFAULT_MAX_WORK_PER_POLL = ReferenceQueueWorker.DEFAULT_MAX_WORK_PER_POLL; |
| |
| public static final int DEFAULT_POLL_MILLIS = ReferenceQueueWorker.DEFAULT_POLL_MILLIS; |
| |
| private final AtomicBoolean cleaning = new AtomicBoolean(); |
| |
| private int maxWorkPerPoll; |
| |
| private long pollMillis; |
| |
| private long lastPoll = System.currentTimeMillis(); |
| |
| public CleanableReferenceQueue() |
| { |
| setPollMillis(DEFAULT_POLL_MILLIS); |
| setMaxWorkPerPoll(DEFAULT_MAX_WORK_PER_POLL); |
| } |
| |
| public final long getPollMillis() |
| { |
| return pollMillis; |
| } |
| |
| public final void setPollMillis(long pollMillis) |
| { |
| this.pollMillis = pollMillis; |
| } |
| |
| public final int getMaxWorkPerPoll() |
| { |
| return maxWorkPerPoll; |
| } |
| |
| public final void setMaxWorkPerPoll(int maxWorkPerPoll) |
| { |
| this.maxWorkPerPoll = maxWorkPerPoll; |
| } |
| |
| public final void register(T object) |
| { |
| clean(); |
| createReference(object); |
| } |
| |
| public final void clean() |
| { |
| if (cleaning.compareAndSet(false, true)) |
| { |
| long now = System.currentTimeMillis(); |
| if (lastPoll + pollMillis > now) |
| { |
| int count = maxWorkPerPoll; |
| if (count == ALL_WORK_PER_POLL) |
| { |
| count = Integer.MAX_VALUE; |
| } |
| |
| for (int i = 0; i < count; i++) |
| { |
| Reference<? extends T> reference = poll(); |
| if (reference == null) |
| { |
| break; |
| } |
| |
| cleanReference(reference); |
| } |
| |
| lastPoll = now; |
| } |
| |
| cleaning.set(false); |
| } |
| } |
| |
| protected abstract void cleanReference(Reference<? extends T> reference); |
| |
| protected abstract Reference<T> createReference(T object); |
| } |