001 /*
002 * Java Genetic Algorithm Library (jenetics-1.6.0).
003 * Copyright (c) 2007-2014 Franz Wilhelmstötter
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License");
006 * you may not use this file except in compliance with the License.
007 * You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 *
017 * Author:
018 * Franz Wilhelmstötter (franz.wilhelmstoetter@gmx.at)
019 */
020 package org.jenetics.util;
021
022 import static java.util.Objects.requireNonNull;
023
024 import java.util.concurrent.CancellationException;
025 import java.util.concurrent.ExecutionException;
026 import java.util.concurrent.ForkJoinPool;
027 import java.util.concurrent.Future;
028 import java.util.concurrent.atomic.AtomicReference;
029
030 import javolution.context.ConcurrentContext;
031 import javolution.context.ObjectFactory;
032 import javolution.util.FastList;
033
034 /**
035 * Since the parallelization of the library is build on the {@link ConcurrentContext}
036 * of the <a href="http://javolution.org/">Javolution</a> project, this class
037 * allows you to share a common {@link ForkJoinPool} for the GA and the rest of
038 * your application.
039 * <p/>
040 * The following example shows how to use the {@code ForkJoinContext} directly:
041 * [code]
042 * public class Main {
043 * public static void main(final String[] args) {
044 * final int nthreads = 10;
045 *
046 * // Create a java ForkJoinPool and initialize the ForkJoinContext.
047 * final ForkJoinPool pool = new ForkJoinPool(nthreads);
048 * ForkJoinContext.setForkJoinPool(pool);
049 *
050 * // Set the concurrence context to use by the javolution context.
051 * ConcurentContext.setContext(ForkJoinContext.class);
052 *
053 * // Execute some task concurrently.
054 * ConcurentContext.enter()
055 * try {
056 * ConcurrentContext.execute(...);
057 * ConcurrentContext.execute(...);
058 * } finally {
059 * ConcurrentContext.exit();
060 * }
061 * }
062 * }
063 * [/code]
064 *
065 * A more convenient way for using the {@code ForkJoinContext} allows the
066 * {@link Concurrency} class.
067 *
068 * @see Concurrency
069 *
070 * @author <a href="mailto:franz.wilhelmstoetter@gmx.at">Franz Wilhelmstötter</a>
071 * @since 1.0
072 * @version 1.0 — <em>$Date: 2014-02-15 $</em>
073 */
074 public final class ForkJoinContext extends ConcurrentContext {
075
076 private static final long serialVersionUID = 1L;
077
078 private final static AtomicReference<ForkJoinPool> _POOL = new AtomicReference<>();
079
080 private final FastList<Future<?>> _futures = new FastList<>(10);
081
082 ForkJoinContext() {
083 }
084
085 /**
086 * Deprecated for fixing typo in method name.
087 *
088 * @see #setForkJoinPool(ForkJoinPool)
089 *
090 * @deprecated Fixing typo, use {@link #setForkJoinPool(ForkJoinPool)}
091 * instead.
092 */
093 @Deprecated
094 public static boolean setForkkJoinPool(final ForkJoinPool pool) {
095 return setForkJoinPool(pool);
096 }
097
098 /**
099 * Set the fork-join-pool used by this context. This method doesn't replace
100 * an already set {@link ForkJoinPool}. Before the <i>context</i> can be
101 * used a {@link ForkJoinPool} must be set.
102 *
103 * @param pool the fork-join-pool to use.
104 * @return {@code true} if the given pool has been set, {@code false}
105 * otherwise.
106 * @throws NullPointerException if the pool is {@code null}.
107 */
108 public static boolean setForkJoinPool(final ForkJoinPool pool) {
109 return _POOL.compareAndSet(null, requireNonNull(pool, "ForkJoinPool"));
110 }
111
112 /**
113 * Return the current fork-join-pool used by this context.
114 *
115 * @return the current fork-join-pool used by this context. Can be
116 * {@code null} if not set jet.
117 */
118 public static ForkJoinPool getForkJoinPool() {
119 return _POOL.get();
120 }
121
122 @Override
123 protected void enterAction() {
124 if (_POOL.get() == null) {
125 throw new IllegalStateException("No ForkJoinPool set.");
126 }
127 _futures.clear();
128 }
129
130 @Override
131 protected void executeAction(final Runnable logic) {
132 _futures.add(_POOL.get().submit(logic));
133 }
134
135
136
137 @Override
138 protected void exitAction() {
139 try {
140 for (FastList.Node<Future<?>> n = _futures.head(),
141 end = _futures.tail(); (n = n.getNext()) != end;)
142 {
143 n.getValue().get();
144 }
145 } catch (InterruptedException | ExecutionException e) {
146 throw (CancellationException)new CancellationException().initCause(e);
147 }
148 }
149
150 static {
151 ObjectFactory.setInstance(
152 new ObjectFactory<ForkJoinContext>() {
153 @Override protected ForkJoinContext create() {
154 return new ForkJoinContext();
155 }
156 },
157 ForkJoinContext.class
158 );
159 }
160
161 }
|