2 // ========================================================================
3 // Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
4 // ------------------------------------------------------------------------
5 // All rights reserved. This program and the accompanying materials
6 // are made available under the terms of the Eclipse Public License v1.0
7 // and Apache License v2.0 which accompanies this distribution.
9 // The Eclipse Public License is available at
10 // http://www.eclipse.org/legal/epl-v10.html
12 // The Apache License v2.0 is available at
13 // http://www.opensource.org/licenses/apache2.0.php
15 // You may elect to redistribute this code under either of these licenses.
16 // ========================================================================
19 package org.eclipse.jetty.util.thread;
21 import java.util.List;
22 import java.util.concurrent.CopyOnWriteArrayList;
23 import java.util.concurrent.TimeUnit;
24 import java.util.concurrent.atomic.AtomicReference;
26 import org.eclipse.jetty.util.component.AbstractLifeCycle;
27 import org.eclipse.jetty.util.log.Log;
28 import org.eclipse.jetty.util.log.Logger;
31 * <p>A utility class to perform periodic sweeping of resources.</p>
32 * <p>{@link Sweepable} resources may be added to or removed from a
33 * {@link Sweeper} and the resource implementation decides whether
34 * it should be swept or not.</p>
35 * <p>If a {@link Sweepable} resources is itself a container of
36 * other sweepable resources, it will forward the sweep operation
37 * to children resources, and so on recursively.</p>
38 * <p>Typical usage is to add {@link Sweeper} as a bean to an existing
41 * Server server = new Server();
42 * server.addBean(new Sweeper(), true);
45 * Code that knows it has sweepable resources can then lookup the
46 * {@link Sweeper} and offer the sweepable resources to it:
48 * class MyComponent implements Sweeper.Sweepable
50 * private final long creation;
51 * private volatile destroyed;
53 * MyComponent(Server server)
55 * this.creation = System.nanoTime();
56 * Sweeper sweeper = server.getBean(Sweeper.class);
57 * sweeper.offer(this);
66 * public boolean sweep()
73 public class Sweeper extends AbstractLifeCycle implements Runnable
75 private static final Logger LOG = Log.getLogger(Sweeper.class);
77 private final AtomicReference<List<Sweepable>> items = new AtomicReference<>();
78 private final AtomicReference<Scheduler.Task> task = new AtomicReference<>();
79 private final Scheduler scheduler;
80 private final long period;
82 public Sweeper(Scheduler scheduler, long period)
84 this.scheduler = scheduler;
89 protected void doStart() throws Exception
92 items.set(new CopyOnWriteArrayList<Sweepable>());
97 protected void doStop() throws Exception
106 List<Sweepable> refs = items.get();
107 return refs == null ? 0 : refs.size();
110 public boolean offer(Sweepable sweepable)
112 List<Sweepable> refs = items.get();
116 if (LOG.isDebugEnabled())
117 LOG.debug("Resource offered {}", sweepable);
121 public boolean remove(Sweepable sweepable)
123 List<Sweepable> refs = items.get();
124 return refs != null && refs.remove(sweepable);
130 List<Sweepable> refs = items.get();
133 for (Sweepable sweepable : refs)
137 if (sweepable.sweep())
139 refs.remove(sweepable);
140 if (LOG.isDebugEnabled())
141 LOG.debug("Resource swept {}", sweepable);
146 LOG.info("Exception while sweeping " + sweepable, x);
152 private void activate()
156 Scheduler.Task t = scheduler.schedule(this, period, TimeUnit.MILLISECONDS);
157 if (LOG.isDebugEnabled())
158 LOG.debug("Scheduled in {} ms sweep task {}", period, t);
163 if (LOG.isDebugEnabled())
164 LOG.debug("Skipping sweep task scheduling");
168 private void deactivate()
170 Scheduler.Task t = task.getAndSet(null);
173 boolean cancelled = t.cancel();
174 if (LOG.isDebugEnabled())
175 LOG.debug("Cancelled ({}) sweep task {}", cancelled, t);
180 * <p>A {@link Sweepable} resource implements this interface to
181 * signal to a {@link Sweeper} or to a parent container if it
182 * needs to be swept or not.</p>
183 * <p>Typical implementations will check their own internal state
184 * and return true or false from {@link #sweep()} to indicate
185 * whether they should be swept.</p>
187 public interface Sweepable
190 * @return whether this resource should be swept
192 public boolean sweep();