    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    @Override
    044    public <T> Future<T> invoke(Invokable<T> invocable)
    045    {
    046        assert invocable != null;
    047
    048        return executorService.submit(toCallable(invocable));
    049    }
    050
    051    private <T> Callable<T> toCallable(final Invokable<T> invocable)
    052    {
    053        return new Callable<T>()
    054        {
    055            @Override
    056            public T call() throws Exception
    057            {
    058                try
    059                {
    060                    return invocable.invoke();
    061                }
    062                finally
    063                {
    064                    perthreadManager.cleanup();
    065                }
    066            }
    067        };
    068    }
    069
    070    @Override
    071    public <T> T invoke(Class<T> proxyType, Invokable<T> invocable)
    072    {
    073        final Future<T> future = invoke(invocable);
    074
    075        ObjectCreator<T> creator = new ObjectCreator<T>()
    076        {
    077            @Override
    078            public T createObject()
    079            {
    080                try
    081                {
    082                    return future.get();
    083                }
    084                catch (Exception ex)
    085                {
    086                    throw new RuntimeException(ex);
    087                }
    088            }
    089        };
    090
    091        String description = String.format("FutureThunk[%s]", proxyType.getName());
    092
    093        return thunkCreator.createThunk(proxyType, new CachingObjectCreator(creator), description);
    094    }
    095}