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.commons.ObjectCreator;
022import org.apache.tapestry5.ioc.Invokable;
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}