X-Git-Url: https://code.wpia.club/?p=gigi.git;a=blobdiff_plain;f=lib%2Fjetty%2Forg%2Feclipse%2Fjetty%2Futil%2Fthread%2FSweeper.java;fp=lib%2Fjetty%2Forg%2Feclipse%2Fjetty%2Futil%2Fthread%2FSweeper.java;h=0ea8800e6b4fc29b58735b4d965824941c8c4ebf;hp=0000000000000000000000000000000000000000;hb=065ca60170f2471227dc25784e1a4c3b7912d367;hpb=ad7a401ad98da5a8a33e60d39789e941aa8ccfc4 diff --git a/lib/jetty/org/eclipse/jetty/util/thread/Sweeper.java b/lib/jetty/org/eclipse/jetty/util/thread/Sweeper.java new file mode 100644 index 00000000..0ea8800e --- /dev/null +++ b/lib/jetty/org/eclipse/jetty/util/thread/Sweeper.java @@ -0,0 +1,194 @@ +// +// ======================================================================== +// Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd. +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// +// The Apache License v2.0 is available at +// http://www.opensource.org/licenses/apache2.0.php +// +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +// + +package org.eclipse.jetty.util.thread; + +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicReference; + +import org.eclipse.jetty.util.component.AbstractLifeCycle; +import org.eclipse.jetty.util.log.Log; +import org.eclipse.jetty.util.log.Logger; + +/** + *

A utility class to perform periodic sweeping of resources.

+ *

{@link Sweepable} resources may be added to or removed from a + * {@link Sweeper} and the resource implementation decides whether + * it should be swept or not.

+ *

If a {@link Sweepable} resources is itself a container of + * other sweepable resources, it will forward the sweep operation + * to children resources, and so on recursively.

+ *

Typical usage is to add {@link Sweeper} as a bean to an existing + * container:

+ *
+ * Server server = new Server();
+ * server.addBean(new Sweeper(), true);
+ * server.start();
+ * 
+ * Code that knows it has sweepable resources can then lookup the + * {@link Sweeper} and offer the sweepable resources to it: + *
+ * class MyComponent implements Sweeper.Sweepable
+ * {
+ *     private final long creation;
+ *     private volatile destroyed;
+ *
+ *     MyComponent(Server server)
+ *     {
+ *         this.creation = System.nanoTime();
+ *         Sweeper sweeper = server.getBean(Sweeper.class);
+ *         sweeper.offer(this);
+ *     }
+ *
+ *     void destroy()
+ *     {
+ *         destroyed = true;
+ *     }
+ *
+ *     @Override
+ *     public boolean sweep()
+ *     {
+ *         return destroyed;
+ *     }
+ * }
+ * 
+ */ +public class Sweeper extends AbstractLifeCycle implements Runnable +{ + private static final Logger LOG = Log.getLogger(Sweeper.class); + + private final AtomicReference> items = new AtomicReference<>(); + private final AtomicReference task = new AtomicReference<>(); + private final Scheduler scheduler; + private final long period; + + public Sweeper(Scheduler scheduler, long period) + { + this.scheduler = scheduler; + this.period = period; + } + + @Override + protected void doStart() throws Exception + { + super.doStart(); + items.set(new CopyOnWriteArrayList()); + activate(); + } + + @Override + protected void doStop() throws Exception + { + deactivate(); + items.set(null); + super.doStop(); + } + + public int getSize() + { + List refs = items.get(); + return refs == null ? 0 : refs.size(); + } + + public boolean offer(Sweepable sweepable) + { + List refs = items.get(); + if (refs == null) + return false; + refs.add(sweepable); + if (LOG.isDebugEnabled()) + LOG.debug("Resource offered {}", sweepable); + return true; + } + + public boolean remove(Sweepable sweepable) + { + List refs = items.get(); + return refs != null && refs.remove(sweepable); + } + + @Override + public void run() + { + List refs = items.get(); + if (refs == null) + return; + for (Sweepable sweepable : refs) + { + try + { + if (sweepable.sweep()) + { + refs.remove(sweepable); + if (LOG.isDebugEnabled()) + LOG.debug("Resource swept {}", sweepable); + } + } + catch (Throwable x) + { + LOG.info("Exception while sweeping " + sweepable, x); + } + } + activate(); + } + + private void activate() + { + if (isRunning()) + { + Scheduler.Task t = scheduler.schedule(this, period, TimeUnit.MILLISECONDS); + if (LOG.isDebugEnabled()) + LOG.debug("Scheduled in {} ms sweep task {}", period, t); + task.set(t); + } + else + { + if (LOG.isDebugEnabled()) + LOG.debug("Skipping sweep task scheduling"); + } + } + + private void deactivate() + { + Scheduler.Task t = task.getAndSet(null); + if (t != null) + { + boolean cancelled = t.cancel(); + if (LOG.isDebugEnabled()) + LOG.debug("Cancelled ({}) sweep task {}", cancelled, t); + } + } + + /** + *

A {@link Sweepable} resource implements this interface to + * signal to a {@link Sweeper} or to a parent container if it + * needs to be swept or not.

+ *

Typical implementations will check their own internal state + * and return true or false from {@link #sweep()} to indicate + * whether they should be swept.

+ */ + public interface Sweepable + { + /** + * @return whether this resource should be swept + */ + public boolean sweep(); + } +}