    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
    015    package org.apache.tapestry5.ioc.internal.services;
    016
    017    import java.util.concurrent.Callable;
    018    import java.util.concurrent.ExecutorService;
    019    import java.util.concurrent.Future;
    020
    021    import org.apache.tapestry5.ioc.Invokable;
    022    import org.apache.tapestry5.ioc.ObjectCreator;
    023    import org.apache.tapestry5.ioc.services.ParallelExecutor;
    024    import org.apache.tapestry5.ioc.services.PerthreadManager;
    025    import org.apache.tapestry5.ioc.services.ThunkCreator;
    026
    027    public 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    }