001// Copyright 2009, 2010, 2011 The Apache Software Foundation
002//
003// Licensed under the Apache License, Version 2.0 (the "License");
004// you may not use this file except in compliance with the License.
005// You may obtain a copy of the License at
006//
007// http://www.apache.org/licenses/LICENSE-2.0
008//
009// Unless required by applicable law or agreed to in writing, software
010// distributed under the License is distributed on an "AS IS" BASIS,
011// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012// See the License for the specific language governing permissions and
013// limitations under the License.
014
015package org.apache.tapestry5.ioc.internal.services;
016
017import java.util.concurrent.Callable;
018import java.util.concurrent.ExecutorService;
019import java.util.concurrent.Future;
020
021import org.apache.tapestry5.ioc.Invokable;
022import org.apache.tapestry5.ioc.ObjectCreator;
023import org.apache.tapestry5.ioc.services.ParallelExecutor;
024import org.apache.tapestry5.ioc.services.PerthreadManager;
025import org.apache.tapestry5.ioc.services.ThunkCreator;
026
027public class ParallelExecutorImpl implements ParallelExecutor
028{
029    private final ThunkCreator thunkCreator;
030
031    private final ExecutorService executorService;
032
033    private final PerthreadManager perthreadManager;
034
035    public ParallelExecutorImpl(ExecutorService executorService, ThunkCreator thunkCreator,
036            PerthreadManager perthreadManager)
037    {
038        this.executorService = executorService;
039        this.thunkCreator = thunkCreator;
040        this.perthreadManager = perthreadManager;
041    }
042
043    public <T> Future<T> invoke(Invokable<T> invocable)
044    {
045        assert invocable != null;
046
047        return executorService.submit(toCallable(invocable));
048    }
049
050    private <T> Callable<T> toCallable(final Invokable<T> invocable)
051    {
052        return new Callable<T>()
053        {
054            public T call() throws Exception
055            {
056                try
057                {
058                    return invocable.invoke();
059                }
060                finally
061                {
062                    perthreadManager.cleanup();
063                }
064            }
065        };
066    }
067
068    public <T> T invoke(Class<T> proxyType, Invokable<T> invocable)
069    {
070        final Future<T> future = invoke(invocable);
071
072        ObjectCreator<T> creator = new ObjectCreator<T>()
073        {
074            public T createObject()
075            {
076                try
077                {
078                    return future.get();
079                }
080                catch (Exception ex)
081                {
082                    throw new RuntimeException(ex);
083                }
084            }
085        };
086
087        String description = String.format("FutureThunk[%s]", proxyType.getName());
088
089        return thunkCreator.createThunk(proxyType, new CachingObjectCreator(creator), description);
090    }
091}