Merge "BUG-1275: Expose XmlStreamUtils.writeValue()"
[yangtools.git] / common / util / src / main / java / org / opendaylight / yangtools / util / concurrent / AsyncNotifyingListeningExecutorService.java
1 /*
2  * Copyright (c) 2014 Brocade Communications Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8
9 package org.opendaylight.yangtools.util.concurrent;
10
11 import java.util.List;
12 import java.util.concurrent.Callable;
13 import java.util.concurrent.Executor;
14 import java.util.concurrent.ExecutorService;
15 import java.util.concurrent.TimeUnit;
16
17 import javax.annotation.Nullable;
18
19 import com.google.common.base.Objects;
20 import com.google.common.base.Objects.ToStringHelper;
21 import com.google.common.base.Preconditions;
22 import com.google.common.util.concurrent.AbstractListeningExecutorService;
23 import com.google.common.util.concurrent.ListenableFuture;
24
25 /**
26  * An {@link ListeningExecutorService} implementation that also allows for an {@link Executor} to be
27  * specified on construction that is used to execute {@link ListenableFuture} callback Runnables,
28  * registered via {@link Futures#addCallback} or {@link ListenableFuture#addListener} directly,
29  * asynchronously when a task that is run on this executor completes. This is useful when you want
30  * to guarantee listener callback executions are off-loaded onto another thread to avoid blocking
31  * the thread that completed the task, as a common use case is to pass an executor that runs tasks
32  * in the same thread as the caller (ie <code>MoreExecutors#sameThreadExecutor</code>}) to
33  * {@link ListenableFuture#addListener}.
34  * <p>
35  * Most commonly, this class would be used in lieu of <code>MoreExecutors#listeningDecorator<code>
36  * when the underlying delegate Executor is single-threaded, in which case, you may not want
37  * ListenableFuture callbacks to block the single thread.
38  * <p>
39  * Note: the Executor specified on construction does not replace the Executor specified in
40  * {@link ListenableFuture#addListener}. The latter Executor is still used however, if it is
41  * detected that the listener Runnable would execute in the thread that completed the task, the
42  * listener is executed on Executor specified on construction.
43  *
44  * @author Thomas Pantelis
45  * @see AsyncNotifyingListenableFutureTask
46  */
47 public class AsyncNotifyingListeningExecutorService extends AbstractListeningExecutorService {
48
49     private final ExecutorService delegate;
50     private final Executor listenableFutureExecutor;
51
52     /**
53      * Constructor.
54      *
55      * @param delegate the back-end ExecutorService.
56      * @param listenableFutureExecutor the executor used to run listener callbacks asynchronously.
57      *     If null, no executor is used.
58      */
59     public AsyncNotifyingListeningExecutorService( ExecutorService delegate,
60             @Nullable Executor listenableFutureExecutor ) {
61         this.delegate = Preconditions.checkNotNull( delegate );
62         this.listenableFutureExecutor = listenableFutureExecutor;
63     }
64
65     /**
66      * Creates an {@link AsyncNotifyingListenableFutureTask} instance with the listener Executor.
67      *
68      * @param task the Callable to execute
69      */
70     private <T> AsyncNotifyingListenableFutureTask<T> newFutureTask( Callable<T> task ) {
71         return AsyncNotifyingListenableFutureTask.create( task, listenableFutureExecutor );
72     }
73
74     /**
75      * Creates an {@link AsyncNotifyingListenableFutureTask} instance with the listener Executor.
76      *
77      * @param task the Runnable to execute
78      */
79     private <T> AsyncNotifyingListenableFutureTask<T> newFutureTask( Runnable task, T result ) {
80         return AsyncNotifyingListenableFutureTask.create( task, result, listenableFutureExecutor );
81     }
82
83     /**
84      * Returns the delegate ExecutorService.
85      */
86     protected ExecutorService getDelegate() {
87         return delegate;
88     }
89
90     @Override
91     public boolean awaitTermination( long timeout, TimeUnit unit ) throws InterruptedException {
92         return delegate.awaitTermination( timeout, unit );
93     }
94
95     @Override
96     public boolean isShutdown() {
97         return delegate.isShutdown();
98     }
99
100     @Override
101     public boolean isTerminated() {
102         return delegate.isTerminated();
103     }
104
105     @Override
106     public void shutdown() {
107         delegate.shutdown();
108     }
109
110     @Override
111     public List<Runnable> shutdownNow() {
112         return delegate.shutdownNow();
113     }
114
115     @Override
116     public void execute( Runnable command ) {
117         delegate.execute( command );
118     }
119
120     @Override
121     public <T> ListenableFuture<T> submit( Callable<T> task ) {
122         AsyncNotifyingListenableFutureTask<T> futureTask = newFutureTask( task );
123         delegate.execute( futureTask );
124         return futureTask;
125     }
126
127     @Override
128     public ListenableFuture<?> submit( Runnable task ) {
129         AsyncNotifyingListenableFutureTask<Void> futureTask = newFutureTask( task, null );
130         delegate.execute( futureTask );
131         return futureTask;
132     }
133
134     @Override
135     public <T> ListenableFuture<T> submit( Runnable task, T result ) {
136         AsyncNotifyingListenableFutureTask<T> futureTask = newFutureTask( task, result );
137         delegate.execute( futureTask );
138         return futureTask;
139     }
140
141     protected ToStringHelper addToStringAttributes( ToStringHelper toStringHelper ) {
142         return toStringHelper;
143     }
144
145     @Override
146     public final String toString(){
147         return addToStringAttributes( Objects.toStringHelper( this )
148                 .add( "delegate", delegate ) ).toString();
149     }
150 }