View Javadoc

1   //
2   //  ========================================================================
3   //  Copyright (c) 1995-2013 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;
20  
21  import java.util.concurrent.Executor;
22  
23  public abstract class ExecutorCallback implements Callback
24  {
25      private final ForkInvoker<Void> _invoker;
26      private final Executor _executor;
27      private final Runnable _onComplete=new Runnable()
28      {
29          @Override
30          public void run()
31          {
32              onCompleted();
33          }
34      };
35  
36      public ExecutorCallback(Executor executor)
37      {
38          this(executor, 4);
39      }
40  
41      public ExecutorCallback(Executor executor, int maxRecursion)
42      {
43          _executor = executor;
44          _invoker = maxRecursion>0?new ExecutorCallbackInvoker(maxRecursion):null;
45          if (_executor==null)
46              throw new IllegalArgumentException();
47      }
48  
49      @Override
50      public void succeeded()
51      {
52          // Should we execute?
53          if (_invoker==null)
54          {
55              _executor.execute(_onComplete);
56          } 
57          else if (alwaysDispatchCompletion())
58          {
59              _invoker.fork(null);
60          }
61          else
62          {
63              _invoker.invoke(null);
64          }
65      }
66  
67      protected abstract void onCompleted();
68  
69      @Override
70      public void failed(final Throwable x)
71      {
72          // Always execute failure
73          Runnable runnable = new Runnable()
74          {
75              @Override
76              public void run()
77              {
78                  onFailed(x);
79              }
80  
81              @Override
82              public String toString()
83              {
84                  return String.format("ExecutorCallback@%x{%s}", hashCode(), x);
85              }
86          };
87  
88          if (_executor == null)
89              new Thread(runnable).start();
90          else
91              _executor.execute(runnable);
92      }
93  
94      protected void onFailed(Throwable x)
95      {
96      }
97  
98      protected boolean alwaysDispatchCompletion()
99      {
100         return _executor != null;
101     }
102 
103     @Override
104     public String toString()
105     {
106         return String.format("%s@%x", getClass(), hashCode());
107     }
108 
109     private class ExecutorCallbackInvoker extends ForkInvoker<Void> implements Runnable
110     {
111         private ExecutorCallbackInvoker(int maxInvocations)
112         {
113             super(maxInvocations);
114         }
115 
116         @Override
117         public void fork(Void arg)
118         {
119             _executor.execute(this);
120         }
121 
122         @Override
123         public void call(Void arg)
124         {
125             onCompleted();
126         }
127 
128         @Override
129         public void run()
130         {
131             onCompleted();
132         }
133     }
134 }