Home | History | Annotate | Download | only in service
      1 /**
      2  * Copyright (C) 2010 Google Inc.
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  * http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.google.inject.service;
     18 
     19 import com.google.common.base.Preconditions;
     20 
     21 import java.util.concurrent.Callable;
     22 import java.util.concurrent.ExecutorService;
     23 import java.util.concurrent.Future;
     24 import java.util.concurrent.FutureTask;
     25 
     26 /**
     27  * An asynchronous implementation of {@link com.google.inject.service.Service}
     28  * that provides convenience callbacks to create your own services.
     29  *
     30  * @author dhanji (at) gmail.com (Dhanji R. Prasanna)
     31  */
     32 public abstract class AsyncService implements Service {
     33   private static final Runnable DO_NOTHING = new Runnable() {
     34     @Override public void run() {}
     35   };
     36 
     37   private final ExecutorService executor;
     38 
     39   private volatile State state;
     40 
     41   public AsyncService(ExecutorService executor) {
     42     this.executor = executor;
     43   }
     44 
     45   public synchronized final Future<State> start() {
     46     Preconditions.checkState(state != State.STOPPED,
     47         "Cannot restart a service that has been stopped");
     48 
     49     // Starts are idempotent.
     50     if (state == State.STARTED) {
     51       return new FutureTask<State>(DO_NOTHING, State.STARTED);
     52     }
     53 
     54     return executor.submit(new Callable<State>() {
     55       public State call() {
     56         onStart();
     57         return state = State.STARTED;
     58       }
     59     });
     60   }
     61 
     62   /**
     63    * Called back when this service must do its start work. Typically occurs
     64    * in a background thread. The result of this method is returned to the
     65    * original caller of {@link Service#start()} and can thus be used to
     66    * return a status message after start completes (or fails as the case
     67    * may be).
     68    */
     69   protected abstract void onStart();
     70 
     71   public synchronized final Future<State> stop() {
     72     Preconditions.checkState(state != null, "Must start this service before you stop it!");
     73 
     74     // Likewise, stops are idempotent.
     75     if (state == State.STOPPED) {
     76       return new FutureTask<State>(DO_NOTHING, State.STOPPED);
     77     }
     78 
     79     return executor.submit(new Callable<State>() {
     80       public State call() {
     81         onStop();
     82         return state = State.STOPPED;
     83       }
     84     });
     85   }
     86 
     87   /**
     88    * Called back when this service must shutdown. Typically occurs
     89    * in a background thread. The result of this method is returned to the
     90    * original caller of {@link Service#stop()} and can thus be used to
     91    * return a status message after stop completes (or fails as the case
     92    * may be).
     93    */
     94   protected abstract void onStop();
     95 
     96   public final State state() {
     97     return state;
     98   }
     99 }
    100