]> WPIA git - gigi.git/blob - lib/jetty/org/eclipse/jetty/util/thread/Sweeper.java
updating jetty to jetty-9.2.16.v2016040
[gigi.git] / lib / jetty / org / eclipse / jetty / util / thread / Sweeper.java
1 //
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.
8 //
9 //      The Eclipse Public License is available at
10 //      http://www.eclipse.org/legal/epl-v10.html
11 //
12 //      The Apache License v2.0 is available at
13 //      http://www.opensource.org/licenses/apache2.0.php
14 //
15 //  You may elect to redistribute this code under either of these licenses.
16 //  ========================================================================
17 //
18
19 package org.eclipse.jetty.util.thread;
20
21 import java.util.List;
22 import java.util.concurrent.CopyOnWriteArrayList;
23 import java.util.concurrent.TimeUnit;
24 import java.util.concurrent.atomic.AtomicReference;
25
26 import org.eclipse.jetty.util.component.AbstractLifeCycle;
27 import org.eclipse.jetty.util.log.Log;
28 import org.eclipse.jetty.util.log.Logger;
29
30 /**
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
39  * container:</p>
40  * <pre>
41  * Server server = new Server();
42  * server.addBean(new Sweeper(), true);
43  * server.start();
44  * </pre>
45  * Code that knows it has sweepable resources can then lookup the
46  * {@link Sweeper} and offer the sweepable resources to it:
47  * <pre>
48  * class MyComponent implements Sweeper.Sweepable
49  * {
50  *     private final long creation;
51  *     private volatile destroyed;
52  *
53  *     MyComponent(Server server)
54  *     {
55  *         this.creation = System.nanoTime();
56  *         Sweeper sweeper = server.getBean(Sweeper.class);
57  *         sweeper.offer(this);
58  *     }
59  *
60  *     void destroy()
61  *     {
62  *         destroyed = true;
63  *     }
64  *
65  *     &#64;Override
66  *     public boolean sweep()
67  *     {
68  *         return destroyed;
69  *     }
70  * }
71  * </pre>
72  */
73 public class Sweeper extends AbstractLifeCycle implements Runnable
74 {
75     private static final Logger LOG = Log.getLogger(Sweeper.class);
76
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;
81
82     public Sweeper(Scheduler scheduler, long period)
83     {
84         this.scheduler = scheduler;
85         this.period = period;
86     }
87
88     @Override
89     protected void doStart() throws Exception
90     {
91         super.doStart();
92         items.set(new CopyOnWriteArrayList<Sweepable>());
93         activate();
94     }
95
96     @Override
97     protected void doStop() throws Exception
98     {
99         deactivate();
100         items.set(null);
101         super.doStop();
102     }
103
104     public int getSize()
105     {
106         List<Sweepable> refs = items.get();
107         return refs == null ? 0 : refs.size();
108     }
109
110     public boolean offer(Sweepable sweepable)
111     {
112         List<Sweepable> refs = items.get();
113         if (refs == null)
114             return false;
115         refs.add(sweepable);
116         if (LOG.isDebugEnabled())
117             LOG.debug("Resource offered {}", sweepable);
118         return true;
119     }
120
121     public boolean remove(Sweepable sweepable)
122     {
123         List<Sweepable> refs = items.get();
124         return refs != null && refs.remove(sweepable);
125     }
126
127     @Override
128     public void run()
129     {
130         List<Sweepable> refs = items.get();
131         if (refs == null)
132             return;
133         for (Sweepable sweepable : refs)
134         {
135             try
136             {
137                 if (sweepable.sweep())
138                 {
139                     refs.remove(sweepable);
140                     if (LOG.isDebugEnabled())
141                         LOG.debug("Resource swept {}", sweepable);
142                 }
143             }
144             catch (Throwable x)
145             {
146                 LOG.info("Exception while sweeping " + sweepable, x);
147             }
148         }
149         activate();
150     }
151
152     private void activate()
153     {
154         if (isRunning())
155         {
156             Scheduler.Task t = scheduler.schedule(this, period, TimeUnit.MILLISECONDS);
157             if (LOG.isDebugEnabled())
158                 LOG.debug("Scheduled in {} ms sweep task {}", period, t);
159             task.set(t);
160         }
161         else
162         {
163             if (LOG.isDebugEnabled())
164                 LOG.debug("Skipping sweep task scheduling");
165         }
166     }
167
168     private void deactivate()
169     {
170         Scheduler.Task t = task.getAndSet(null);
171         if (t != null)
172         {
173             boolean cancelled = t.cancel();
174             if (LOG.isDebugEnabled())
175                 LOG.debug("Cancelled ({}) sweep task {}", cancelled, t);
176         }
177     }
178
179     /**
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>
186      */
187     public interface Sweepable
188     {
189         /**
190          * @return whether this resource should be swept
191          */
192         public boolean sweep();
193     }
194 }