View Javadoc

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