00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 package ros.roscpp;
00039
00040 import java.util.Map;
00041 import java.util.concurrent.Callable;
00042 import java.util.concurrent.ExecutionException;
00043 import java.util.concurrent.ExecutorService;
00044 import java.util.concurrent.Executors;
00045 import java.util.concurrent.FutureTask;
00046
00047 import ros.RosException;
00048 import ros.ServiceClient;
00049 import ros.communication.Message;
00050 import ros.communication.Service;
00051
00052 public class CppServiceClient<Q extends Message, A extends Message, S extends Service<Q, A> > implements ServiceClient<Q, A, S> {
00053 private CppNodeHandle handle;
00054 private String name;
00055 private S serviceTemplate;
00056 private long cppServiceClient;
00057 private ExecutorService threadPool;
00058
00059 private CppServiceClient() { }
00060
00061 protected static <Q extends Message, A extends Message, S extends Service<Q, A> > CppServiceClient<Q,A,S>
00062 create(CppNodeHandle handle, long cppHandle, String name, S serviceTemplate, boolean isPersistant, Map<String, String> headerValues) {
00063 CppServiceClient<Q, A, S> that = new CppServiceClient<Q, A, S>();
00064 that.handle = handle;
00065 that.name = name;
00066 that.serviceTemplate = serviceTemplate;
00067 that.cppServiceClient = JNI.serviceClient(cppHandle, name, serviceTemplate.getMD5Sum(), isPersistant, Util.mapToArray(headerValues));
00068 if (that.cppServiceClient == 0) throw new RuntimeException("Could not create service client " + name + "(should not happen)");
00069 return that;
00070 }
00071
00072 public String getService() {return name; }
00073
00074 public A call(Q request) throws RosException {
00075 A response = serviceTemplate.createResponse();
00076 if (!JNI.callService(cppServiceClient, request, response, serviceTemplate.getMD5Sum())) throw new RosException("Service call failed!");
00077 return response;
00078 }
00079
00080 public FutureTask<A> callAsync(final Q request) throws RosException {
00081 if (threadPool == null) threadPool = Executors.newCachedThreadPool();
00082 final CppServiceClient<Q, A, S> that = this;
00083 FutureTask<A> f = new FutureTask<A>(new Callable<A>() {
00084 public A call() throws Exception {
00085 return (A) that.call(request);
00086 }
00087 });
00088 handle.submitFuture(f);
00089 return f;
00090 }
00091
00092 public A callLocal(Q request) throws RosException {
00093 FutureTask<A> f = callAsync(request);
00094 while(!f.isDone()) {
00095 handle.spinOnce();
00096 }
00097 try {
00098 return f.get();
00099 } catch (InterruptedException e) {
00100 throw new RosException("InterruptedException in callLocal", e);
00101 } catch (ExecutionException e) {
00102 throw new RosException("ExecutionException in callLocal", e);
00103 }
00104 }
00105
00106 public boolean isValid() { return (cppServiceClient != 0); }
00107
00108 public void shutdown() {
00109 if (!isValid()) return;
00110 JNI.shutdownServiceClient(cppServiceClient);
00111 cppServiceClient = 0;
00112 }
00113 }
00114