libgpars-groovy-java-0.10.orig/0000755000000000000000000000000011416416664013335 5ustar libgpars-groovy-java-0.10.orig/groovyx/0000755000000000000000000000000011347765306015055 5ustar libgpars-groovy-java-0.10.orig/groovyx/gpars/0000755000000000000000000000000011374454000016153 5ustar libgpars-groovy-java-0.10.orig/groovyx/gpars/GParsExecutorsPool.groovy0000644000000000000000000003000411373715074023201 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-10 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars import groovyx.gpars.util.PoolUtils import java.util.concurrent.Callable import java.util.concurrent.ExecutorService import java.util.concurrent.Executors import java.util.concurrent.Future import java.util.concurrent.ThreadFactory import java.util.concurrent.TimeUnit /** * Enables a ExecutorService-based DSL on closures, objects and collections. * E.g. * GParsExecutorsPool.withPool(5) {ExecutorService service -> * Collection result = [1, 2, 3, 4, 5].collectParallel({it * 10}.async()) * assertEquals(new HashSet([10, 20, 30, 40, 50]), new HashSet((Collection)result*.get())) *}* * GParsExecutorsPool.withPool(5) {ExecutorService service -> * def result = [1, 2, 3, 4, 5].findParallel{Number number -> number > 2}* assert result in [3, 4, 5] *}* * @author Vaclav Pech * Date: Oct 23, 2008 */ class GParsExecutorsPool { /** * Maps threads to their appropriate thread pools */ private static final ThreadLocalPools currentPoolStack = new ThreadLocalPools() /** * Caches the default pool size. */ private static final int defaultPoolSize = PoolUtils.retrieveDefaultPoolSize() /** * Retrieves the pool assigned to the current thread. */ protected static ExecutorService retrieveCurrentPool() { currentPoolStack.current } /** * Creates a new pool with the default size() */ private static createPool() { return createPool(PoolUtils.retrieveDefaultPoolSize()) } /** * Creates a new pool with the given size() */ private static createPool(int poolSize) { return createPool(poolSize, createDefaultThreadFactory()) } private static createPool(int poolSize, ThreadFactory threadFactory) { if (!(poolSize in 1..Integer.MAX_VALUE)) throw new IllegalArgumentException("Invalid value $poolSize for the pool size has been specified. Please supply a positive int number.") if (!threadFactory) throw new IllegalArgumentException("No value specified for threadFactory.") return Executors.newFixedThreadPool(poolSize, threadFactory) } private static ThreadFactory createDefaultThreadFactory() { return {Runnable runnable -> final Thread thread = new Thread(runnable) thread.daemon = false thread } as ThreadFactory } /** * Creates a new instance of ExecutorService, binds it to the current thread, enables the ExecutorService DSL * and runs the supplied closure. * It is an identical alternative for withPool() with a shorter name. * Within the supplied code block the ExecutorService is available as the only parameter, objects have been * enhanced with the eachParallel(), collectParallel() and other methods from the GParsExecutorsPoolUtil * category class as well as closures can be turned into asynchronous ones by calling the async() method on them. * E.g. closure,async returns a new closure, which, when run will schedule the original closure * for processing in the pool. * Calling images.eachParallel{processImage(it}} will call the potentially long-lasting processImage() * operation on each image in the images collection in parallel. *
     * def result = new ConcurrentSkipListSet()
     * GParsExecutorsPool.withPool {ExecutorService service ->
     *     [1, 2, 3, 4, 5].eachParallel{Number number -> result.add(number * 10)}*     assertEquals(new HashSet([10, 20, 30, 40, 50]), result)
     *}* 
* @param cl The block of code to invoke with the DSL enabled */ public static withPool(Closure cl) { return withPool(defaultPoolSize, cl) } /** * Creates a new instance of ExecutorService, binds it to the current thread, enables the ExecutorService DSL * and runs the supplied closure. * It is an identical alternative for withPool() with a shorter name. * Within the supplied code block the ExecutorService is available as the only parameter, objects have been * enhanced with the eachParallel(), collectParallel() and other methods from the GParsExecutorsPoolUtil * category class as well as closures can be turned into asynchronous ones by calling the async() method on them. * E.g. closure,async returns a new closure, which, when run will schedule the original closure * for processing in the pool. * Calling images.eachParallel{processImage(it}} will call the potentially long-lasting processImage() * operation on each image in the images collection in parallel. *
     * def result = new ConcurrentSkipListSet()
     * GParsExecutorsPool.withPool(5) {ExecutorService service ->
     *     [1, 2, 3, 4, 5].eachParallel{Number number -> result.add(number * 10)}*     assertEquals(new HashSet([10, 20, 30, 40, 50]), result)
     *}* 
* @param numberOfThreads Number of threads in the newly created thread pool * @param cl The block of code to invoke with the DSL enabled */ public static withPool(int numberOfThreads, Closure cl) { return withPool(numberOfThreads, createDefaultThreadFactory(), cl) } /** * Creates a new instance of ExecutorService, binds it to the current thread, enables the ExecutorService DSL * and runs the supplied closure. * It is an identical alternative for withPool() with a shorter name. * Within the supplied code block the ExecutorService is available as the only parameter, objects have been * enhanced with the eachParallel(), collectParallel() and other methods from the GParsExecutorsPoolUtil * category class as well as closures can be turned into asynchronous ones by calling the async() method on them. * E.g. closure,async returns a new closure, which, when run will schedule the original closure * for processing in the pool. * Calling images.eachParallel{processImage(it}} will call the potentially long-lasting processImage() * operation on each image in the images collection in parallel. *
     * def result = new ConcurrentSkipListSet()
     * GParsExecutorsPool.withPool(5) {ExecutorService service ->
     *     [1, 2, 3, 4, 5].eachParallel{Number number -> result.add(number * 10)}*     assertEquals(new HashSet([10, 20, 30, 40, 50]), result)
     *}* 
* @param numberOfThreads Number of threads in the newly created thread pool * @param threadFactory Factory for threads in the pool * @param cl The block of code to invoke with the DSL enabled */ public static withPool(int numberOfThreads, ThreadFactory threadFactory, Closure cl) { final ExecutorService pool = createPool(numberOfThreads, threadFactory) try { return withExistingPool(pool, cl) } finally { pool.shutdown() pool.awaitTermination(Long.MAX_VALUE, TimeUnit.MILLISECONDS) } } /** * Creates a new instance of ExecutorService, binds it to the current thread, enables the ExecutorService DSL * and runs the supplied closure. * Within the supplied code block the ExecutorService is available as the only parameter, objects have been * enhanced with the eachParallel(), collectParallel() and other methods from the GParsExecutorsPoolUtil * category class as well as closures can be turned into asynchronous ones by calling the async() method on them. * E.g. closure,async returns a new closure, which, when run will schedule the original closure * for processing in the pool. * Calling images.eachParallel{processImage(it}} will call the potentially long-lasting processImage() * operation on each image in the images collection in parallel. *
     * def result = new ConcurrentSkipListSet()
     * GParsExecutorsPool.withPool(5) {ExecutorService service ->
     *     [1, 2, 3, 4, 5].eachParallel{Number number -> result.add(number * 10)}*     assertEquals(new HashSet([10, 20, 30, 40, 50]), result)
     *}* 
* @param pool The ExecutorService to use, the service will not be shutdown after this method returns */ public static withExistingPool(ExecutorService pool, Closure cl) { currentPoolStack << pool def result = null try { use(GParsExecutorsPoolUtil) { result = cl(pool) } } finally { currentPoolStack.pop() } return result } /** * Starts multiple closures in separate threads, collecting their return values * If an exception is thrown from the closure when called on any of the collection's elements, * it will be re-thrown in the calling thread when it calls the Future.get() method. * @return The result values of all closures * @throws AsyncException If any of the collection's elements causes the closure to throw an exception. The original exceptions will be stored in the AsyncException's concurrentExceptions field. */ public static List executeAsyncAndWait(Closure... closures) { return GParsExecutorsPoolUtil.processResult(executeAsync(closures)) } /** * Starts multiple closures in separate threads, collecting their return values * If an exception is thrown from the closure when called on any of the collection's elements, * it will be re-thrown in the calling thread when it calls the Future.get() method. * @return The result values of all closures * @throws AsyncException If any of the collection's elements causes the closure to throw an exception. The original exceptions will be stored in the AsyncException's concurrentExceptions field. */ public static List executeAsyncAndWait(List closures) { return executeAsyncAndWait(* closures) } /** * Starts multiple closures in separate threads, collecting Futures for their return values * If an exception is thrown from the closure when called on any of the collection's elements, * it will be re-thrown in the calling thread when it calls the Future.get() method. * @return Futures for the result values or exceptions of all closures */ public static List> executeAsync(Closure... closures) { GParsExecutorsPool.withPool(closures.size()) {ExecutorService executorService -> List> result = closures.collect {cl -> executorService.submit({ cl.call() } as Callable) } result } } /** * Starts multiple closures in separate threads, collecting Futures for their return values * If an exception is thrown from the closure when called on any of the collection's elements, * it will be re-thrown in the calling thread when it calls the Future.get() method. * @return Futures for the result values or exceptions of all closures */ public static List> executeAsync(List closures) { return executeAsync(* closures) } } libgpars-groovy-java-0.10.orig/groovyx/gpars/csp/0000755000000000000000000000000011352326072016743 5ustar libgpars-groovy-java-0.10.orig/groovyx/gpars/csp/PAR.groovy0000644000000000000000000000250711352326072020640 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-9 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.csp import org.jcsp.lang.Parallel /** * PAR is used to create a Parallel object * *

Company: Napier University

* * @author Jon Kerridge, Ken Barclay, John Savage * @version 1.0 * @version 1.1 modified to compile under groovy jsr03 */ class PAR extends Parallel { /** * PAR extends the Parallel class of JCSP * PAR takes a list of processes as its constructor parameter * and converts them to an array of CSProcess * as required by Parallel * */ PAR(processList) { super() processList.each {p -> this.addProcess(p) } } PAR() { super() } } libgpars-groovy-java-0.10.orig/groovyx/gpars/csp/JCSPCopy.groovy0000644000000000000000000000414411352326072021607 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-9 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.csp public interface JCSPCopy { /** * The interface JCSPCopy is used to define a copy method * that is used to make a deep copy of an object. In parallel systems an object * is used to encapsulate data only. When an object is communicated from one process * to another then an object reference is passed from the outputting process to the inputting one, * if the processes are on the same processor. This would mean that two processes could modify the * same object in parallel, which of course is very dangerous. One of the processes has to make * a copy of the object if they are both to work on the same object at the same time. This can be * achieved by always declaring new objects for each iteration of a process, which is wasteful of * memory, or by copying the object. The interface JCSPCopy gives the basic * definition of such a copy method. * * If an object is communicated over a network channel there is no need to make * a copy as the object has to implement Serializable and a copy * is made by the underlying system. A processor cannot access the memory space of * another processor. *

Company: Napier University

* * @author Jon Kerridge, Ken Barclay, John Savage * @version 1.0 * */ public abstract copy() } libgpars-groovy-java-0.10.orig/groovyx/gpars/csp/GroovyMobileProcess.groovy0000644000000000000000000000153011352326072024165 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-9 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.csp //import org.jcsp.net.mobile.* abstract class GroovyMobileProcess {//todo extends MobileProcess implements Serializable{ abstract connect(x) abstract disconnect() }libgpars-groovy-java-0.10.orig/groovyx/gpars/csp/MobileAgent.groovy0000644000000000000000000000147211352326072022404 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-9 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.csp import org.jcsp.lang.CSProcess interface MobileAgent extends CSProcess, Serializable { abstract connect(List x) abstract disconnect() }libgpars-groovy-java-0.10.orig/groovyx/gpars/csp/plugAndPlay/0000755000000000000000000000000011365257450021172 5ustar libgpars-groovy-java-0.10.orig/groovyx/gpars/csp/plugAndPlay/GSuccessor.groovy0000644000000000000000000000175011352326072024515 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-9 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.csp.plugAndPlay import org.jcsp.lang.CSProcess import org.jcsp.lang.ChannelInput import org.jcsp.lang.ChannelOutput class GSuccessor implements CSProcess { ChannelInput inChannel ChannelOutput outChannel void run() { while (true) { outChannel.write(inChannel.read() + 1) } } } libgpars-groovy-java-0.10.orig/groovyx/gpars/csp/plugAndPlay/GPrint.groovy0000644000000000000000000000221711352326072023637 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-9 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.csp.plugAndPlay import org.jcsp.lang.CSProcess import org.jcsp.lang.CSTimer import org.jcsp.lang.ChannelInput class GPrint implements CSProcess { ChannelInput inChannel String heading = "No Heading Provided" long delay = 200 def void run() { def timer = new CSTimer() println "${heading}" while (true) { println inChannel.read().toString() if (delay != 0) { timer.sleep(delay) } } } }libgpars-groovy-java-0.10.orig/groovyx/gpars/csp/plugAndPlay/GPrefix.groovy0000644000000000000000000000203711352326072024000 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-9 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.csp.plugAndPlay import org.jcsp.lang.CSProcess import org.jcsp.lang.ChannelInput import org.jcsp.lang.ChannelOutput class GPrefix implements CSProcess { int prefixValue = 0 ChannelInput inChannel ChannelOutput outChannel void run() { outChannel.write(prefixValue) while (true) { outChannel.write(inChannel.read()) } } } libgpars-groovy-java-0.10.orig/groovyx/gpars/csp/plugAndPlay/GObjectToConsoleString.groovy0000644000000000000000000000203411352326072026763 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-9 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.csp.plugAndPlay import org.jcsp.lang.CSProcess import org.jcsp.lang.ChannelInput import org.jcsp.lang.ChannelOutput class GObjectToConsoleString implements CSProcess { ChannelInput inChannel ChannelOutput outChannel def void run() { while (true) { def o = inChannel.read() outChannel.write(o.toString() + "\n") } } }libgpars-groovy-java-0.10.orig/groovyx/gpars/csp/plugAndPlay/GPCopy.groovy0000644000000000000000000000244711352326072023602 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-9 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.csp.plugAndPlay import groovyx.gpars.csp.PAR import org.jcsp.lang.CSProcess import org.jcsp.lang.ChannelInput import org.jcsp.lang.ChannelOutput import org.jcsp.plugNplay.ProcessWrite class GPCopy implements CSProcess { ChannelInput inChannel ChannelOutput outChannel0 ChannelOutput outChannel1 void run() { def write0 = new ProcessWrite(outChannel0) def write1 = new ProcessWrite(outChannel1) def parWrite2 = new PAR([write0, write1]) while (true) { def i = inChannel.read() write0.value = i write1.value = i parWrite2.run() } } } libgpars-groovy-java-0.10.orig/groovyx/gpars/csp/plugAndPlay/GConsole.groovy0000644000000000000000000000422011352326072024141 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-9 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.csp.plugAndPlay import groovyx.gpars.csp.PAR import java.awt.BorderLayout import java.awt.Container import java.awt.Font import java.awt.GridLayout import java.awt.Label import org.jcsp.awt.ActiveClosingFrame import org.jcsp.awt.ActiveTextArea import org.jcsp.awt.ActiveTextEnterField import org.jcsp.lang.CSProcess import org.jcsp.lang.ChannelInput import org.jcsp.lang.ChannelOutput class GConsole implements CSProcess { ChannelInput toConsole ChannelOutput fromConsole ChannelInput clearInputArea String frameLabel = "Groovy Eclipse Console" def void run() { def main = new ActiveClosingFrame(frameLabel) def root = main.activeFrame root.layout = new BorderLayout() def outLabel = new Label("Output Area", Label.CENTER) outLabel.font = new Font("sans-serif", Font.BOLD, 20) def inLabel = new Label("Input Area", Label.CENTER) inLabel.font = new Font("sans-serif", Font.BOLD, 20) def outText = new ActiveTextArea(toConsole, null) def inText = new ActiveTextEnterField(clearInputArea, fromConsole) def console = new Container() console.layout = new GridLayout(4, 1) console.add(outLabel) console.add(outText) console.add(inLabel) console.add(inText.activeTextField) root.add(console, BorderLayout.CENTER) root.pack() root.visible = true def interfaceProcessList = [main, outText, inText] new PAR(interfaceProcessList).run() } }libgpars-groovy-java-0.10.orig/groovyx/gpars/csp/plugAndPlay/GConsoleStringToInteger.groovy0000644000000000000000000000210011352326072027144 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-9 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.csp.plugAndPlay import org.jcsp.lang.CSProcess import org.jcsp.lang.ChannelInput import org.jcsp.lang.ChannelOutput class GConsoleStringToInteger implements CSProcess { ChannelInput inChannel ChannelOutput outChannel def void run() { while (true) { def String s = inChannel.read().trim() def i = Integer.valueOf(s) outChannel.write(i) } } }libgpars-groovy-java-0.10.orig/groovyx/gpars/csp/plugAndPlay/GDelta2.groovy0000644000000000000000000000245411352326072023661 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-9 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.csp.plugAndPlay import groovyx.gpars.csp.PAR import org.jcsp.lang.CSProcess import org.jcsp.lang.ChannelInput import org.jcsp.lang.ChannelOutput import org.jcsp.plugNplay.ProcessWrite class GDelta2 implements CSProcess { ChannelInput inChannel ChannelOutput outChannel0 ChannelOutput outChannel1 def void run() { def write0 = new ProcessWrite(outChannel0) def write1 = new ProcessWrite(outChannel1) def parWrite2 = new PAR([write0, write1]) while (true) { def i = inChannel.read() write0.value = i write1.value = i parWrite2.run() } } } libgpars-groovy-java-0.10.orig/groovyx/gpars/csp/plugAndPlay/GPairs.groovy0000644000000000000000000000304011352326072023614 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-9 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.csp.plugAndPlay import groovyx.gpars.csp.PAR import org.jcsp.lang.CSProcess import org.jcsp.lang.Channel import org.jcsp.lang.ChannelInput import org.jcsp.lang.ChannelOutput import org.jcsp.lang.One2OneChannel class GPairs implements CSProcess { ChannelOutput outChannel ChannelInput inChannel void run() { One2OneChannel a = Channel.createOne2One() One2OneChannel b = Channel.createOne2One() One2OneChannel c = Channel.createOne2One() def pairsList = [new GPlus(outChannel: outChannel, inChannel0: a.in(), inChannel1: c.in()), new GPCopy(inChannel: inChannel, outChannel0: a.out(), outChannel1: b.out()), new GTail(inChannel: b.in(), outChannel: c.out()) ] new PAR(pairsList).run() } } libgpars-groovy-java-0.10.orig/groovyx/gpars/csp/plugAndPlay/GFixedDelay.groovy0000644000000000000000000000215311352326072024560 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-9 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.csp.plugAndPlay import org.jcsp.lang.CSProcess import org.jcsp.lang.CSTimer import org.jcsp.lang.ChannelInput import org.jcsp.lang.ChannelOutput class GFixedDelay implements CSProcess { ChannelInput inChannel ChannelOutput outChannel long delay = 0 void run() { def timer = new CSTimer() while (true) { def v = inChannel.read() timer.sleep(delay) outChannel.write(v) } } }libgpars-groovy-java-0.10.orig/groovyx/gpars/csp/plugAndPlay/GIntegrate.groovy0000644000000000000000000000312711352326072024466 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-9 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.csp.plugAndPlay import groovyx.gpars.csp.PAR import org.jcsp.lang.CSProcess import org.jcsp.lang.Channel import org.jcsp.lang.ChannelInput import org.jcsp.lang.ChannelOutput import org.jcsp.lang.One2OneChannel class GIntegrate implements CSProcess { ChannelOutput outChannel ChannelInput inChannel void run() { One2OneChannel a = Channel.createOne2One() One2OneChannel b = Channel.createOne2One() One2OneChannel c = Channel.createOne2One() def integrateList = [new GPrefix(prefixValue: 0, outChannel: c.out(), inChannel: b.in()), new GPCopy(inChannel: a.in(), outChannel0: outChannel, outChannel1: b.out()), new GPlus(inChannel0: inChannel, inChannel1: c.in(), outChannel: a.out()) ] new PAR(integrateList).run() } } libgpars-groovy-java-0.10.orig/groovyx/gpars/csp/plugAndPlay/GTail.groovy0000644000000000000000000000177011352326072023437 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-9 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.csp.plugAndPlay import org.jcsp.lang.CSProcess import org.jcsp.lang.ChannelInput import org.jcsp.lang.ChannelOutput class GTail implements CSProcess { ChannelOutput outChannel ChannelInput inChannel void run() { inChannel.read() while (true) { outChannel.write(inChannel.read()) } } } libgpars-groovy-java-0.10.orig/groovyx/gpars/csp/plugAndPlay/GSquares.groovy0000644000000000000000000000255111352326072024167 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-9 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.csp.plugAndPlay import groovyx.gpars.csp.PAR import org.jcsp.lang.CSProcess import org.jcsp.lang.Channel import org.jcsp.lang.ChannelOutput import org.jcsp.lang.One2OneChannel class GSquares implements CSProcess { ChannelOutput outChannel void run() { One2OneChannel N2I = Channel.createOne2One() One2OneChannel I2P = Channel.createOne2One() def testList = [new GNumbers(outChannel: N2I.out()), new GIntegrate(inChannel: N2I.in(), outChannel: I2P.out()), new GPairs(inChannel: I2P.in(), outChannel: outChannel), ] new PAR(testList).run() } } libgpars-groovy-java-0.10.orig/groovyx/gpars/csp/plugAndPlay/GPlus.groovy0000644000000000000000000000242011352326072023462 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-9 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.csp.plugAndPlay import groovyx.gpars.csp.PAR import org.jcsp.lang.CSProcess import org.jcsp.lang.ChannelInput import org.jcsp.lang.ChannelOutput import org.jcsp.plugNplay.ProcessRead class GPlus implements CSProcess { ChannelOutput outChannel ChannelInput inChannel0 ChannelInput inChannel1 void run() { ProcessRead read0 = new ProcessRead(inChannel0) ProcessRead read1 = new ProcessRead(inChannel1) def parRead2 = new PAR([read0, read1]) while (true) { parRead2.run() outChannel.write(read0.value + read1.value) } } } libgpars-groovy-java-0.10.orig/groovyx/gpars/csp/plugAndPlay/GNumbers.groovy0000644000000000000000000000303311352326072024153 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-9 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.csp.plugAndPlay import groovyx.gpars.csp.PAR import org.jcsp.lang.CSProcess import org.jcsp.lang.Channel import org.jcsp.lang.ChannelOutput import org.jcsp.lang.One2OneChannel class GNumbers implements CSProcess { ChannelOutput outChannel void run() { One2OneChannel a = Channel.createOne2One() One2OneChannel b = Channel.createOne2One() One2OneChannel c = Channel.createOne2One() def numbersList = [new GPrefix(prefixValue: 0, inChannel: c.in(), outChannel: a.out()), new GPCopy(inChannel: a.in(), outChannel0: outChannel, outChannel1: b.out()), new GSuccessor(inChannel: b.in(), outChannel: c.out()) ] new PAR(numbersList).run() } } libgpars-groovy-java-0.10.orig/groovyx/gpars/csp/plugAndPlay/GParPrint.groovy0000644000000000000000000000331211352326072024277 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-9 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.csp.plugAndPlay import groovyx.gpars.csp.ChannelInputList import groovyx.gpars.csp.PAR import org.jcsp.lang.CSProcess import org.jcsp.lang.CSTimer import org.jcsp.plugNplay.ProcessRead class GParPrint implements CSProcess { ChannelInputList inChannels List headings long delay = 200 void run() { def inSize = inChannels.size() def readerList = [] (0.. readerList[i] = new ProcessRead(inChannels[i]) } def parRead = new PAR(readerList) if (headings == null) { println "No headings provided" } else { headings.each { print "\t${it}" } println() } def timer = new CSTimer() while (true) { parRead.run() // print "\t" // readerList.each { pr -> print "${pr.value}\t" } readerList.each {pr -> print "\t" + pr.value.toString() } println() if (delay > 0) { timer.sleep(delay) } } } }libgpars-groovy-java-0.10.orig/groovyx/gpars/csp/plugAndPlay/GIdentity.groovy0000644000000000000000000000174311352326072024337 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-9 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.csp.plugAndPlay import org.jcsp.lang.CSProcess import org.jcsp.lang.ChannelInput import org.jcsp.lang.ChannelOutput class GIdentity implements CSProcess { ChannelOutput outChannel ChannelInput inChannel void run() { while (true) { outChannel.write(inChannel.read()) } } } libgpars-groovy-java-0.10.orig/groovyx/gpars/csp/plugAndPlay/GStatePairs.groovy0000644000000000000000000000212711352326072024622 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-9 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.csp.plugAndPlay import org.jcsp.lang.CSProcess import org.jcsp.lang.ChannelInput import org.jcsp.lang.ChannelOutput class GStatePairs implements CSProcess { ChannelOutput outChannel ChannelInput inChannel void run() { def n1 = inChannel.read() def n2 = inChannel.read() while (true) { outChannel.write(n1 + n2) n1 = n2 n2 = inChannel.read() } } } libgpars-groovy-java-0.10.orig/groovyx/gpars/csp/util/0000755000000000000000000000000011365257450017727 5ustar libgpars-groovy-java-0.10.orig/groovyx/gpars/csp/util/PriMultiplex.groovy0000644000000000000000000000214311352326072023625 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-9 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.csp.util import groovyx.gpars.csp.ALT import groovyx.gpars.csp.ChannelInputList import org.jcsp.lang.CSProcess import org.jcsp.lang.ChannelOutput class PriMultiplex implements CSProcess { ChannelInputList inChannels ChannelOutput outChannel def void run() { def alt = new ALT(inChannels) while (true) { def index = alt.priSelect() outChannel.write(inChannels[index].read()) } } } libgpars-groovy-java-0.10.orig/groovyx/gpars/csp/util/TimedMultiplex.groovy0000644000000000000000000000306711365257450024152 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-9 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.csp.util import groovyx.gpars.csp.ALT import groovyx.gpars.csp.ChannelInputList import org.jcsp.lang.CSProcess import org.jcsp.lang.CSTimer import org.jcsp.lang.ChannelOutput class TimedMultiplex implements CSProcess { ChannelInputList inChannels ChannelOutput outChannel long timeout // period during which process will run def void run() { def timer = new CSTimer() def timerIndex = inChannels.size() def alt = new ALT((List)(inChannels + timer)) timer.alarm = timer.read() + timeout def running = true while (running) { def index = alt.select() if (index == timerIndex) { running = false println "TimedMultiplex has stopped" } else { outChannel.write(inChannels[index].read()) } } } } libgpars-groovy-java-0.10.orig/groovyx/gpars/csp/util/FairMultiplex.groovy0000644000000000000000000000214511352326072023756 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-9 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.csp.util import groovyx.gpars.csp.ALT import groovyx.gpars.csp.ChannelInputList import org.jcsp.lang.CSProcess import org.jcsp.lang.ChannelOutput class FairMultiplex implements CSProcess { ChannelInputList inChannels ChannelOutput outChannel def void run() { def alt = new ALT(inChannels) while (true) { def index = alt.fairSelect() outChannel.write(inChannels[index].read()) } } } libgpars-groovy-java-0.10.orig/groovyx/gpars/csp/util/Multiplexer.groovy0000644000000000000000000000213311352326072023500 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-9 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.csp.util import groovyx.gpars.csp.ALT import groovyx.gpars.csp.ChannelInputList import org.jcsp.lang.CSProcess import org.jcsp.lang.ChannelOutput class Multiplexer implements CSProcess { ChannelInputList inChannels ChannelOutput outChannel void run() { def alt = new ALT(inChannels) while (true) { def index = alt.select() outChannel.write(inChannels[index].read()) } } } libgpars-groovy-java-0.10.orig/groovyx/gpars/csp/util/TestUtilities.groovy0000644000000000000000000000273411365257450024017 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-9 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.csp.util @SuppressWarnings("GroovyMultipleReturnPointsPerMethod") abstract class TestUtilities { public static boolean listContains(firstList, secondList) { if (firstList.size != secondList.size) { return false } else { firstList.sort() secondList.sort() return (firstList == secondList) } } // end listContains public static boolean list1GEList2(firstList, secondList) { if (firstList.size != secondList.size) { return false } else { for (i in 0..Alternative object * *

Company: Napier University

* @author Jon Kerridge, Ken Barclay, John Savage * @version 1.0 * @version 1.1 takes account of jsr03 requirements */ class ALT extends Alternative { /** * ALT extends the Alternative class of JCSP * ALT takes a list of Guards as its constructor parameter * and converts them to an array of Guards * as required by Alternative */ ALT(ChannelInputList channelList) { super((Guard[]) channelList.toArray()) } ALT(List guardList) { super((Guard[]) guardList.toArray()) } } libgpars-groovy-java-0.10.orig/groovyx/gpars/csp/ChannelOutputList.groovy0000644000000000000000000000513011352326072023636 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-9 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.csp import org.jcsp.lang.Channel import org.jcsp.plugNplay.ProcessWrite /** * ChannelOutputList is used to create a list of * ChannelOUTPUTEnds *

Company: Napier University

* * @author Jon Kerridge, Ken Barclay, John Savage * @version 1.0 * * @version 1.1 included the empty constructor to enable * easier NetChannelOUTPUT list creation (Jon Kerridge) * and changes to comply with Groovy-jsr03 */ class ChannelOutputList { def cList = [] /** * ChannelOutputList uses the ArrayList class of java * This ChannelOutputList takes an array of One2OneChannels as its * constructor parameter and converts them to a list of ChannelOUTPUTEnds * */ ChannelOutputList(channelArray) { cList = (Arrays.asList(Channel.getOutputArray(channelArray))) } /** * ChannelOutputList uses the ArrayList class of java * This constructor creates an empty ArrayList to be populated with * NetChannelOUTPUTs * */ ChannelOutputList() { // nothing required it is just an empty list } def append(value) { cList << value } def size() { return cList.size() } def contains(value) { return cList.contains(value) } def remove(value) { return cList.remove(value) } def minus(list) { return cList - list } def plus(list) { return cList + list } def putAt(index, value) { cList[index] = value } def getAt(index) { return cList[index] } def Object[] toArray() { return cList.toArray() } def write(value) { def channels = cList.size() def writerList = [] (0.. writerList[i] = new ProcessWrite(cList[i]) writerList[i].value = value } def parWrite = new PAR(writerList) parWrite.run() } }libgpars-groovy-java-0.10.orig/groovyx/gpars/csp/ChannelInputList.groovy0000644000000000000000000000521011352326072023434 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-9 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.csp import org.jcsp.lang.Channel import org.jcsp.plugNplay.ProcessRead /** * ChannelInputList is used to create a list of * ChannelInputEnds * */ class ChannelInputList { def cList = [] /** * ChannelInputList uses the ArrayList class of java * This ChannelInputList takes an array of One2OneChannels as its * constructor parameter and converts them to a list of ChannelInputEnds * *

Company: Napier University

* @author Jon Kerridge, Ken Barclay, John Savage * @version 1.0 * * @version 1.1 included the empty constructor to enable * easier NetChannelOUTPUT list creation (Jon Kerridge) * and changes to comply with Groovy-jsr03 */ ChannelInputList(channelArray) { cList = (Arrays.asList(Channel.getInputArray(channelArray))) } /** * ChannelInputList uses the ArrayList class of java * This constructor creates an empty ArrayList to be populated with * NetChannelInputs * */ ChannelInputList() { // nothing required it is just an empty list } def append(value) { cList << value } def size() { return cList.size() } def contains(value) { return cList.contains(value) } def remove(value) { return cList.remove(value) } def minus(list) { return cList - list } def plus(list) { return cList + list } def putAt(index, value) { cList[index] = value } def getAt(index) { return cList[index] } def Object[] toArray() { return cList.toArray() } def List read() { def values = [] def channels = cList.size() def readerList = [] (0.. readerList[i] = new ProcessRead(cList[i]) } def parRead = new PAR(readerList) parRead.run() (0.. values[i] = readerList[i].value } return values } } libgpars-groovy-java-0.10.orig/groovyx/gpars/AbstractForkJoinWorker.java0000644000000000000000000000516011347765306023435 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-10 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars; import jsr166y.forkjoin.RecursiveTask; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; /** * Implements the ForkJoin worker contract. * Subclasses need to implement the compute() to perform the actual Fork/Join algorithm leveraging the options * provided by the AbstractForkJoinWorker class. The AbstractForJoinWorker class takes care of the child sub-processes. *

* Author: Vaclav Pech * Date: Nov 1, 2009 */ @SuppressWarnings({"AbstractClassWithOnlyOneDirectInheritor", "CollectionWithoutInitialCapacity"}) public abstract class AbstractForkJoinWorker extends RecursiveTask { /** * Stores the child workers */ private Collection> children = null; protected AbstractForkJoinWorker() { } @Override protected final T compute() { try { return computeTask(); } finally { children = null; } } protected abstract T computeTask(); /** * Forks a child task. Makes sure it has a means to indicate back completion. * The worker is stored in the internal list of workers for evidence and easy result retrieval through getChildrenResults(). * * @param child The child task */ protected final void forkOffChild(final AbstractForkJoinWorker child) { if (children == null) children = new ArrayList>(); children.add(child); child.fork(); } /** * Waits for and returns the results of the child tasks. * * @return A list of results returned from the child tasks */ protected final List getChildrenResults() { if (children == null) return Collections.emptyList(); final List results = new ArrayList(children.size()); for (final AbstractForkJoinWorker worker : children) { results.add(worker.join()); } return results; } } libgpars-groovy-java-0.10.orig/groovyx/gpars/dataflow/0000755000000000000000000000000011374454000017754 5ustar libgpars-groovy-java-0.10.orig/groovyx/gpars/dataflow/DataFlowExpression.java0000644000000000000000000005535611374457552024435 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-10 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.dataflow; import groovy.lang.Closure; import groovy.lang.GroovyObject; import groovy.lang.MetaClass; import groovy.lang.MetaProperty; import groovyx.gpars.actor.Actors; import groovyx.gpars.actor.impl.MessageStream; import groovyx.gpars.remote.RemoteConnection; import groovyx.gpars.remote.RemoteHost; import groovyx.gpars.serial.SerialContext; import groovyx.gpars.serial.SerialMsg; import groovyx.gpars.serial.WithSerialId; import org.codehaus.groovy.runtime.InvokerHelper; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.UUID; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; import java.util.concurrent.locks.LockSupport; /** * The base class for all dataflow elements. * * @author Alex Tkachman, Vaclav Pech */ @SuppressWarnings({"UnqualifiedStaticUsage", "CallToSimpleGetterFromWithinClass"}) public abstract class DataFlowExpression extends WithSerialId implements GroovyObject { /** * Updater for the state field */ protected static final AtomicIntegerFieldUpdater stateUpdater = AtomicIntegerFieldUpdater.newUpdater(DataFlowExpression.class, "state"); /** * Updater for the waiting field */ protected static final AtomicReferenceFieldUpdater waitingUpdater = AtomicReferenceFieldUpdater.newUpdater(DataFlowExpression.class, WaitingThread.class, "waiting"); /** * The current metaclass */ private MetaClass metaClass = InvokerHelper.getMetaClass(getClass()); /** * Holds the actual value. Is null before a concrete value is bound to it. */ @SuppressWarnings({"InstanceVariableMayNotBeInitialized"}) protected volatile T value; /** * Holds the current state of the variable */ protected volatile int state; /** * Points to the head of the chain of requests waiting for a value to be bound */ private volatile WaitingThread waiting; /** * Possible states */ protected static final int S_NOT_INITIALIZED = 0; protected static final int S_INITIALIZING = 1; protected static final int S_INITIALIZED = 2; /** * A logical representation of a synchronous or asynchronous request to read the value once it is bound. */ private static class WaitingThread extends AtomicBoolean { private static final long serialVersionUID = 8909974768784947460L; private final Thread thread; private volatile WaitingThread previous; private final MessageStream callback; private final Object attachment; /** * Creates a representation of the request to read the value once it is bound * * @param thread The physical thread of the request, which will be suspended * @param previous The previous request in the chain of requests * @param attachment An arbitrary object closely identifying the request for the caller * @param callback An actor or operator to send a message to once a value is bound */ private WaitingThread(final Thread thread, final WaitingThread previous, final Object attachment, final MessageStream callback) { this.callback = callback; this.attachment = attachment; this.thread = thread; this.previous = previous; } } /** * A request chain terminator */ private static final WaitingThread dummyWaitingThread = new WaitingThread(null, null, null, null); /** * Creates a new unbound Dataflow Expression */ protected DataFlowExpression() { state = S_NOT_INITIALIZED; } /** * Check if value has been set already for this expression * * @return true if bound already */ public boolean isBound() { return state == S_INITIALIZED; } /** * Asynchronously retrieves the value of the variable. Sends the actual value of the variable as a message * back the the supplied actor once the value has been bound. * The actor can perform other activities or release a thread back to the pool by calling react() waiting for the message * with the value of the Dataflow Variable. * * @param callback An actor to send the bound value to. */ public void getValAsync(final MessageStream callback) { getValAsync(null, callback); } /** * Used by Dataflow operators. * Asynchronously retrieves the value of the variable. Sends a message back the the supplied MessageStream * with a map holding the supplied attachment under the 'attachment' key and the actual value of the variable under * the 'result' key once the value has been bound. * Attachment is an arbitrary value helping the actor.operator match its request with the reply. * The actor/operator can perform other activities or release a thread back to the pool by calling react() waiting for the message * with the value of the Dataflow Variable. * * @param attachment arbitrary non-null attachment if reader needs better identification of result * @param callback An actor to send the bound value plus the supplied index to. */ void getValAsync(final Object attachment, final MessageStream callback) { if (callback == null) { throw new NullPointerException(); } WaitingThread newWaiting = null; while (state != S_INITIALIZED) { if (newWaiting == null) { newWaiting = new WaitingThread(null, null, attachment, callback); } final WaitingThread previous = waiting; // it means that writer already started processing queue, so value is already in place if (previous == dummyWaitingThread) { break; } newWaiting.previous = previous; if (waitingUpdater.compareAndSet(this, previous, newWaiting)) { // ok, we are in the queue, so writer is responsible to process us return; } } scheduleCallback(attachment, callback); } /** * Reads the value of the variable. Blocks, if the value has not been assigned yet. * * @return The actual value * @throws InterruptedException If the current thread gets interrupted while waiting for the variable to be bound */ public T getVal() throws InterruptedException { WaitingThread newWaiting = null; while (state != S_INITIALIZED) { if (newWaiting == null) { newWaiting = new WaitingThread(Thread.currentThread(), null, null, null); } final WaitingThread previous = waiting; // it means that writer already started processing queue, so value is already in place if (previous == dummyWaitingThread) { break; } newWaiting.previous = previous; if (waitingUpdater.compareAndSet(this, previous, newWaiting)) { // ok, we are in the queue, so writer is responsible to process us while (state != S_INITIALIZED) { LockSupport.park(); if (Thread.currentThread().isInterrupted()) handleInterruption(newWaiting); } break; } } return value; } /** * Reads the value of the variable. Blocks up to given timeout, if the value has not been assigned yet. * * @param timeout The timeout value * @param units Units for the timeout * @return The actual value * @throws InterruptedException If the current thread gets interrupted while waiting for the variable to be bound */ public T getVal(final long timeout, final TimeUnit units) throws InterruptedException { final long endNano = System.nanoTime() + units.toNanos(timeout); WaitingThread newWaiting = null; while (state != S_INITIALIZED) { if (newWaiting == null) { newWaiting = new WaitingThread(Thread.currentThread(), null, null, null); } final WaitingThread previous = waiting; // it means that writer already started processing queue, so value is already in place if (previous == dummyWaitingThread) { break; } newWaiting.previous = previous; if (waitingUpdater.compareAndSet(this, previous, newWaiting)) { // ok, we are in the queue, so writer is responsible to process us while (state != S_INITIALIZED) { final long toWait = endNano - System.nanoTime(); if (toWait <= 0) { newWaiting.set(true); // don't unpark please return null; } LockSupport.parkNanos(toWait); if (Thread.currentThread().isInterrupted()) handleInterruption(newWaiting); } break; } } return value; } private static void handleInterruption(final AtomicBoolean newWaiting) throws InterruptedException { newWaiting.set(true); // don't unpark please throw new InterruptedException(); } /** * Assigns a value to the variable. Returns silently if invoked on an already bound variable. * * @param value The value to assign */ public void bindSafely(final T value) { if (!stateUpdater.compareAndSet(this, S_NOT_INITIALIZED, S_INITIALIZING)) { return; } doBind(value); } /** * Assigns a value to the variable. Can only be invoked once on each instance of DataFlowVariable * Throws exception if invoked on an already bound variable. * * @param value The value to assign */ public void bind(final T value) { if (!stateUpdater.compareAndSet(this, S_NOT_INITIALIZED, S_INITIALIZING)) { throw new IllegalStateException("A DataFlowVariable can only be assigned once."); } doBind(value); } /** * Performs the actual bind operation, unblocks all blocked threads and informs all asynchronously waiting actors. * * @param value The value to assign */ private void doBind(final T value) { doBindImpl(value); notifyRemote(null); } private void doBindImpl(final T value) { this.value = value; state = S_INITIALIZED; @SuppressWarnings({"unchecked"}) final WaitingThread waitingQueue = waitingUpdater.getAndSet(this, dummyWaitingThread); // no more new waiting threads since that point for (WaitingThread currentWaiting = waitingQueue; currentWaiting != null; currentWaiting = currentWaiting.previous) { // maybe currentWaiting thread canceled or was interrupted if (currentWaiting.compareAndSet(false, true)) { if (currentWaiting.thread != null) { // can be potentially called on a non-parked thread, // which is OK as in this case next park () will be ignored LockSupport.unpark(currentWaiting.thread); } else { if (currentWaiting.callback != null) { scheduleCallback(currentWaiting.attachment, currentWaiting.callback); } } } } } /** * Binds the value after receiving a bing message over the wire * * @param hostId Id of the bind originator host * @param message The value to bind */ public void doBindRemote(final UUID hostId, final T message) { doBindImpl(message); notifyRemote(hostId); } /** * Sends notifications to all subscribers * * @param hostId The local host id */ private void notifyRemote(final UUID hostId) { if (serialHandle != null) { Actors.defaultActorPGroup.getThreadPool().execute(new Runnable() { public void run() { final Object sub = serialHandle.getSubscribers(); if (sub instanceof RemoteHost) { final RemoteHost host = (RemoteHost) sub; if (hostId == null || !host.getHostId().equals(hostId)) { host.write(new BindDataFlow(DataFlowExpression.this, value, host.getLocalHost().getId())); } } if (sub instanceof List) { //noinspection SynchronizeOnNonFinalField synchronized (serialHandle) { //noinspection unchecked for (final SerialContext host : (List) sub) { if (hostId == null || !host.getHostId().equals(hostId)) { host.write(new BindDataFlow(DataFlowExpression.this, value, host.getLocalHostId())); } } } } } }); } } /** * Sends the result back to the actor, which is waiting asynchronously for the value to be bound. * The message will either be a map holding the attachment under the 'attachment' key and the actual bound value under the 'result' key, * or it will be the result itself if the callback doesn't care about the index. * * @param attachment An arbitrary object identifying the request * @param callback The actor to send the message to */ @SuppressWarnings({"TypeMayBeWeakened"}) private void scheduleCallback(final Object attachment, final MessageStream callback) { if (attachment == null) { callback.send(value); } else { final Map message = new HashMap(2); message.put("attachment", attachment); message.put("result", value); callback.send(message); } } /** * Schedule closure to be executed by pooled actor after data became available * It is important to notice that even if data already available the execution of closure * will not happen immediately but will be scheduled * * @param closure closure to execute when data available */ public void rightShift(final Closure closure) { whenBound(closure); } /** * Schedule closure to be executed by pooled actor after data becomes available * It is important to notice that even if data already available the execution of closure * will not happen immediately but will be scheduled. * * @param closure closure to execute when data available */ public void whenBound(final Closure closure) { getValAsync(new DataCallback(closure)); } /** * Send the bound data to provided stream when it becomes available * * @param stream stream where to send result */ public void whenBound(final MessageStream stream) { getValAsync(stream); } @SuppressWarnings("unchecked") public static DataFlowExpression transform(final Object another, final Closure closure) { final int pnum = closure.getMaximumNumberOfParameters(); if (pnum == 0) { throw new IllegalArgumentException("Closure should have parameters"); } if (pnum == 1) { return new TransformOne(another, closure); } else { if (another instanceof Collection) { final Collection collection = (Collection) another; if (collection.size() != pnum) { throw new IllegalArgumentException("Closure parameters don't match #of arguments"); } return new TransformMany(collection, closure); } throw new IllegalArgumentException("Collection expected"); } } /** * Utility method to call at the very end of constructor of derived expressions. * Create and subscribe listener */ protected final void subscribe() { final DataFlowExpressionsCollector listener = new DataFlowExpressionsCollector(); subscribe(listener); listener.start(); } /** * Evaluate expression after the ones we depend on are ready * * @return value to bind */ protected T evaluate() { return value; } protected void subscribe(final DataFlowExpressionsCollector listener) { listener.subscribe(this); } public Object invokeMethod(final String name, final Object args) { if (getMetaClass().respondsTo(this, name).isEmpty()) { return new DataFlowInvocationExpression(this, name, (Object[]) args); } return InvokerHelper.invokeMethod(this, name, args); } /** * Returns either standard property of expression or * creates expression, which will request given property when receiver became available * * @param propertyName The name of the property to retrieve * @return The property value, instance of DataFlowGetPropertyExpression */ public Object getProperty(final String propertyName) { final MetaProperty metaProperty = getMetaClass().hasProperty(this, propertyName); if (metaProperty != null) { return metaProperty.getProperty(this); } return new DataFlowGetPropertyExpression(this, propertyName); } public void setMetaClass(final MetaClass metaClass) { this.metaClass = metaClass; } public void setProperty(final String propertyName, final Object newValue) { metaClass.setProperty(this, propertyName, newValue); } public MetaClass getMetaClass() { return metaClass; } /** * Listener for availability of data flow expressions we depend from */ final class DataFlowExpressionsCollector extends MessageStream { private static final long serialVersionUID = 3414942165521113575L; private final AtomicInteger count = new AtomicInteger(1); @Override public MessageStream send(final Object message) { if (count.decrementAndGet() == 0) { bind(evaluate()); } return this; } Object subscribe(final Object element) { if (!(element instanceof DataFlowExpression)) { return element; } final DataFlowExpression dataFlowExpression = (DataFlowExpression) element; if (dataFlowExpression.state == S_INITIALIZED) { return dataFlowExpression.value; } count.incrementAndGet(); dataFlowExpression.getValAsync(this); return element; } void start() { if (count.decrementAndGet() == 0) { doBind(evaluate()); } } } @SuppressWarnings({"ArithmeticOnVolatileField"}) @Override public String toString() { return getClass().getSimpleName() + "(value=" + value + ')'; } private static class TransformOne extends DataFlowExpression { private static final long serialVersionUID = 6701886501249351047L; Object arg; private final Closure closure; private TransformOne(final Object another, final Closure closure) { this.closure = closure; arg = another; } @Override protected V evaluate() { //noinspection unchecked return (V) closure.call(arg instanceof DataFlowExpression ? ((DataFlowExpression) arg).value : arg); } @Override protected void subscribe(final DataFlowExpressionsCollector listener) { arg = listener.subscribe(arg); } } private static class TransformMany extends DataFlowComplexExpression { private static final long serialVersionUID = 4115456542358280855L; private final Closure closure; private TransformMany(final Collection collection, final Closure closure) { super(collection.toArray()); this.closure = closure; subscribe(); } @Override protected V evaluate() { super.evaluate(); //noinspection unchecked return (V) closure.call(args); } } //todo sort out generics /** * Represents a remote message binding a value to a remoted DataFlowExpression */ public static class BindDataFlow extends SerialMsg { private static final long serialVersionUID = -8674023870562062769L; private final DataFlowExpression expr; private final Object message; /** * @param expr The local DataFlowExpression instance * @param message The actual value to bind * @param hostId The identification of the host to send the bind information to */ public BindDataFlow(final DataFlowExpression expr, final Object message, final UUID hostId) { super(hostId); this.expr = expr; this.message = message; } /** * Performs the actual bind on the remote host * * @param conn The connection object */ @Override public void execute(final RemoteConnection conn) { expr.doBindRemote(hostId, message); } } } libgpars-groovy-java-0.10.orig/groovyx/gpars/dataflow/DataFlows.groovy0000644000000000000000000001441511347765306023132 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-9 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.dataflow import groovyx.gpars.dataflow.DataFlowVariable as DF import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.ConcurrentMap /** * Convenience class that makes working with DataFlowVariables more comfortable. * * See the implementation of {@link groovyx.gpars.samples.dataflow.DemoDataFlows} for a full example. * * A DataFlows instance is a bean with properties of type DataFlowVariable. * Property access is relayed to the access methods of DataFlowVariable. * Each property is initialized lazily the first time it is accessed. * Non-String named properties can be also accessed using array-like indexing syntax * This allows a rather compact usage of DataFlowVariables like * *

 final df = new DataFlows()
 start { df[0] = df.x + df.y }
 start { df.x = 10 }
 start { df.y = 5 }
 assert 15 == df[0]
 * 
* * @author Vaclav Pech, Dierk Koenig, Alex Tkachman * Date: Sep 3, 2009 */ public final class DataFlows { private final static DF DUMMY = new DF() private final lock = new Object() private ConcurrentMap variables = null // copy from ConcurrentHashMap for jdk 1.5 backwards compatibility static final int DEFAULT_INITIAL_CAPACITY = 16 static final float DEFAULT_LOAD_FACTOR = 0.75f static final int DEFAULT_CONCURRENCY_LEVEL = 16 static final int MAX_SEGMENTS = 1 << 16; /** * Constructor that supports the various constructors of the underlying * ConcurrentHashMap (unless the one with Map parameter). * @see java.util.concurrent.ConcurrentHashMap */ DataFlows( int initialCapacity = DEFAULT_INITIAL_CAPACITY, float loadFactor = DEFAULT_LOAD_FACTOR, int concurrencyLevel = DEFAULT_CONCURRENCY_LEVEL) { variables = new ConcurrentHashMap(initialCapacity, loadFactor, concurrencyLevel) } /** * Binds the value to the DataFlowVariable that is associated with the property "name". * @param value a scalar or a DataFlowVariable that may block on value access * @see DataFlowVariable#bind */ void setProperty(String name, value) { ensureToContainVariable(name) << value } /** * @return the value of the DataFlowVariable associated with the property "name". * May block if the value is not scalar. * @see DataFlowVariable#getVal */ def getProperty(String name) { ensureToContainVariable(name).val } /** * Invokes the given method. * Allows for invoking whenBound() on the dataflow variables. *
     * def df = new DataFlows()
     * df.var {*     println "Variable bound to $it"
     *}* 
* * @param name the name of the method to call (the variable name) * @param args the arguments to use for the method call (a closure to invoke when a value is bound) * @return the result of invoking the method (void) */ def invokeMethod(String name, Object args) { def df = ensureToContainVariable(name) if (args instanceof Object[] && args.length == 1 && args[0] instanceof Closure) { df >> args[0] return this } else throw new MissingMethodException(name, DataFlows, args) } /** * @return the value of the DataFlowVariable associated with the property "name". * May block if the value is not scalar. * @see DataFlowVariable#getVal */ def getAt(index) { ensureToContainVariable(index).val } /** * Binds the value to the DataFlowVariable that is associated with the property "index". * @param value a scalar or a DataFlowVariable that may block on value access * @see DataFlowVariable#bind */ void putAt(index, value) { ensureToContainVariable(index) << value } /** * The idea is following: * - we try to putIfAbsent dummy DFV in to map * - if something real already there we are done * - if not we obtain lock and put new DFV with double check * * Unfortunately we have to sync on this as there is no better option (God forbid to sync on name) * * @return DataFlowVariable corresponding to name */ private def ensureToContainVariable(name) { def df = variables.putIfAbsent(name, DUMMY) if (!df || df == DUMMY) { df = putNewUnderLock(name) } df } /** * Utility method extracted just to help JIT * * @return DFV */ private def putNewUnderLock(name) { synchronized (lock) { def df = variables[name] if (!df || (df == DUMMY)) { df = new DF() variables[name] = df; } return df } } /** * Removes a DFV from the map and binds it to null, if it has not been bound yet * @param name The name of the DFV to remove. */ public def remove(name) { synchronized (lock) { def df = variables.remove(name) if (df) df.bindSafely(null) } } /** * Checks whether a certain key is contained in the map. Doesn't check, whether the variable has already been bound. * @param name The name of the DFV to check. */ public def contains(name) { variables.containsKey(name) } /** * Convenience method to play nicely with Groovy object iteration methods. * The iteration restrictions of ConcurrentHashMap concerning parallel access and * ConcurrentModificationException apply. * @return iterator over the stored key:DataFlowVariable value pairs * @see DataFlowsTest#testIterator */ public Iterator iterator() { variables.entrySet().iterator() } } libgpars-groovy-java-0.10.orig/groovyx/gpars/dataflow/operator/0000755000000000000000000000000011365257450021621 5ustar libgpars-groovy-java-0.10.orig/groovyx/gpars/dataflow/operator/DataFlowOperator.groovy0000644000000000000000000001634711365257450026320 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-10 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.dataflow.operator import groovyx.gpars.actor.AbstractPooledActor import groovyx.gpars.group.PGroup import java.util.concurrent.Semaphore /** * Dataflow operators form the basic units in dataflow networks. Operators are typically combined into oriented graphs that transform data. * They accept a set of input and output dataflow channels so that once values are available to be consumed in all * the input channels the operator's body is triggered on the values, potentially generating values for the output channels. * The output channels at the same time are suitable to be used as input channels by some other dataflow operators. * The channels allow operators to communicate. * * Dataflow operators enable creation of highly concurrent applications yet the abstraction hides the low-level concurrency primitives * and exposes much friendlier API. * Since operators internally leverage the actor implementation, they reuse a pool of threads and so the actual number of threads * used by the calculation can be kept much lower than the actual number of operators used in the network. * * @author Vaclav Pech * Date: Sep 9, 2009 */ public final class DataFlowOperator { /** * The internal actor performing on behalf of the operator */ private final DataFlowOperatorActor actor /** * Creates an operator * @param channels A map specifying "inputs" and "outputs" - dataflow channels (instances of the DataFlowStream or DataFlowVariable classes) to use for inputs and outputs * @param code The operator's body to run each time all inputs have a value to read */ private def DataFlowOperator(final Map channels, final Closure code) { final int parameters = code.maximumNumberOfParameters if (!channels || (channels.inputs == null) || (parameters != channels.inputs.size())) throw new IllegalArgumentException("The operator's body accepts $parameters parameters while it is given ${channels?.inputs?.size()} input streams. The numbers must match.") code.delegate = this if (channels.maxForks != null && channels.maxForks != 1) { if (channels.maxForks < 1) throw new IllegalArgumentException("The maxForks argument must be a positive value. ${channels.maxForks} was provided.") this.actor = new ForkingDataFlowOperatorActor(this, channels.outputs?.asImmutable(), channels.inputs.asImmutable(), code.clone(), channels.maxForks) } else { this.actor = new DataFlowOperatorActor(this, channels.outputs?.asImmutable(), channels.inputs.asImmutable(), code.clone()) } } /** * Starts an operator using the specified operator actor group * @param group The operator actor group to use with the operator */ DataFlowOperator start(PGroup group) { actor.actorGroup = group actor.start() return this } /** * Stops the operator */ public void stop() { actor.stop() } /** * Joins the operator waiting for it to finish */ public void join() { actor.join() } /** * Used by the operator's body to send a value to the given output channel */ void bindOutput(final int idx, final value) { actor.outputs[idx] << value } /** * Used by the operator's body to send a value to the first / only output channel */ void bindOutput(final value) { bindOutput 0, value } /** * The operator's output channel of the given index */ public getOutputs(int idx) { actor.outputs[idx] } /** * The operator's output channel of the given index */ public getOutputs() { actor.outputs } /** * The operator's first / only output channel */ public getOutput() { actor.outputs[0] } /** * Is invoked in case the actor throws an exception. */ protected void reportError(Throwable e) { System.err.println "The dataflow operator experienced an exception and is about to terminate. $e" stop() } } /** * An operator's internal actor. Repeatedly polls inputs and once they're all available it performs the operator's body. */ private class DataFlowOperatorActor extends AbstractPooledActor { final List inputs final List outputs final Closure code final def owningOperator def DataFlowOperatorActor(owningOperator, outputs, inputs, code) { this.owningOperator = owningOperator this.outputs = outputs this.inputs = inputs this.code = code } protected final void act() { loop { inputs.eachWithIndex {input, index -> input.getValAsync(index, this)} def values = [:] handleValueMessage(values, inputs.size()) } } /** * Calls itself recursively within a react() call, if more input values are still needed. * Once all required inputs are available (received as messages), the operator's body is run. */ final void handleValueMessage(Map values, count) { if (values.size() < count) { react { values[it.attachment] = it.result handleValueMessage(values, count) } } else { def results = values.sort {it.key}.values() as List startTask(results) } } def startTask(results) { try { code.call(* results) } catch (Throwable e) { reportException(e) } } final reportException(Throwable e) { owningOperator.reportError(e) } } /** * An operator's internal actor. Repeatedly polls inputs and once they're all available it performs the operator's body. * The operator's body is executed in as a separate task, allowing multiple copies of the body to be run concurrently. * The maxForks property guards the maximum number or concurrently run copies. */ private final class ForkingDataFlowOperatorActor extends DataFlowOperatorActor { final Semaphore semaphore def ForkingDataFlowOperatorActor(owningOperator, outputs, inputs, code, maxForks) { super(owningOperator, outputs, inputs, code) this.semaphore = new Semaphore(5) } def startTask(results) { semaphore.acquire() actorGroup.threadPool.execute { try { code.call(* results) } catch (Throwable e) { reportException(e) } finally { semaphore.release() } } } } libgpars-groovy-java-0.10.orig/groovyx/gpars/dataflow/DataFlowComplexExpression.java0000644000000000000000000000261611347765306025753 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-9 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.dataflow; /** * @author Alex Tkachman */ public abstract class DataFlowComplexExpression extends DataFlowExpression { protected Object[] args; protected DataFlowComplexExpression(final Object... elements) { this.args = elements; } @Override protected void subscribe(final DataFlowExpressionsCollector listener) { for (int i = 0; i != args.length; ++i) { args[i] = listener.subscribe(args[i]); } } @Override protected T evaluate() { for (int i = 0; i != args.length; ++i) { if (args[i] instanceof DataFlowExpression) { args[i] = ((DataFlowExpression) args[i]).value; } } return null; } } libgpars-groovy-java-0.10.orig/groovyx/gpars/dataflow/DataFlowActor.groovy0000644000000000000000000000211111363317620023714 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-9 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.dataflow import groovyx.gpars.actor.AbstractPooledActor /** * A parent actor for all actors used in Dataflow Concurrency implementation * * @author Vaclav Pech * Date: Jun 5, 2009 */ abstract class DataFlowActor extends AbstractPooledActor { /** * Sets the default Dataflow Concurrency actor group on the actor. */ def DataFlowActor() { this.actorGroup = DataFlow.DATA_FLOW_GROUP } } libgpars-groovy-java-0.10.orig/groovyx/gpars/dataflow/DataFlowStream.java0000644000000000000000000002412311365257450023510 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-10 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.dataflow; import groovy.lang.Closure; import groovyx.gpars.actor.impl.MessageStream; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.LinkedBlockingQueue; /** * Represents a thread-safe data flow stream. Values or DataFlowVariables are added using the '<<' operator * and safely read once available using the 'val' property. * The iterative methods like each(), collect(), iterator(), any(), all() or the for loops work with snapshots * of the stream at the time of calling the particular method. * For actors and Dataflow Operators the asynchronous non-blocking variants of the getValAsync() methods can be used. * They register the request to read a value and will send a message to the actor or operator once the value is available. * * @author Vaclav Pech * Date: Jun 5, 2009 */ @SuppressWarnings({"LawOfDemeter", "MethodReturnOfConcreteClass", "AnonymousInnerClass", "AnonymousInnerClassWithTooManyMethods"}) public final class DataFlowStream { /** * Internal lock */ private final Object queueLock = new Object(); /** * Stores the received DataFlowVariables in the buffer. */ private final LinkedBlockingQueue> queue = new LinkedBlockingQueue>(); /** * Stores unsatisfied requests for values */ private final LinkedBlockingQueue> requests = new LinkedBlockingQueue>(); /** * A collection of listeners who need to be informed each time the stream is bound to a value */ private final Collection whenBoundListeners = new CopyOnWriteArrayList(); /** * Adds a DataFlowVariable to the buffer. * Implementation detail - in fact another DFV is added to the buffer and an asynchronous 'whenBound' handler * is registered with the supplied DFV to update the one stored in the buffer. * * @param ref The DFV to add to the stream */ @SuppressWarnings("unchecked") public void leftShift(final DataFlowExpression ref) { final DataFlowVariable originalRef = retrieveForBind(); hookWhenBoundListeners(originalRef); ref.getValAsync(new MessageStream() { private static final long serialVersionUID = -4966523895011173569L; @Override public MessageStream send(final Object message) { originalRef.bind((T) message); return this; } }); } /** * Adds a DataFlowVariable representing the passed in value to the buffer. * * @param value The value to bind to the head of the stream */ public void leftShift(final T value) { hookWhenBoundListeners(retrieveForBind()).bind(value); } /** * Hooks the registered when bound handlers to the supplied dataflow expression * * @param expr The expression to hook all the when bound listeners to * @return The supplied expression handler to allow method chaining */ private DataFlowExpression hookWhenBoundListeners(final DataFlowExpression expr) { for (final MessageStream listener : whenBoundListeners) { expr.whenBound(listener); } return expr; } /** * Takes the first unsatisfied value request and binds a value on it. * If there are no unsatisfied value requests, a new DFV is stored in the queue. * * @return The DFV to bind the value on */ private DataFlowVariable retrieveForBind() { return copyDFV(requests, queue); } private DataFlowVariable copyDFV(final LinkedBlockingQueue> from, final LinkedBlockingQueue> to) { DataFlowVariable ref; synchronized (queueLock) { ref = from.poll(); if (ref == null) { ref = new DataFlowVariable(); to.offer(ref); } } return ref; } /** * Retrieves the value at the head of the buffer. Blocks until a value is available. * * @return The value bound to the DFV at the head of the stream * @throws InterruptedException If the current thread is interrupted */ public T getVal() throws InterruptedException { return retrieveOrCreateVariable().getVal(); } /** * Asynchronously retrieves the value at the head of the buffer. Sends the actual value of the variable as a message * back the the supplied actor once the value has been bound. * The actor can perform other activities or release a thread back to the pool by calling react() waiting for the message * with the value of the Dataflow Variable. * * @param messageStream The actor to notify when a value is bound */ public void getValAsync(final MessageStream messageStream) { getValAsync(null, messageStream); } /** * Asynchronously retrieves the value at the head of the buffer. Sends a message back the the supplied actor / operator * with a map holding the supplied index under the 'index' key and the actual value of the variable under * the 'result' key once the value has been bound. * The actor/operator can perform other activities or release a thread back to the pool by calling react() waiting for the message * with the value of the Dataflow Variable. * * @param attachment An arbitrary value to identify operator channels and so match requests and replies * @param messageStream The actor / operator to notify when a value is bound */ public void getValAsync(final Object attachment, final MessageStream messageStream) { retrieveOrCreateVariable().getValAsync(attachment, messageStream); } /** * Schedule closure to be executed by pooled actor after data became available * It is important to notice that even if data already available the execution of closure * will not happen immediately but will be scheduled * * @param closure closure to execute when data available */ public void rightShift(final Closure closure) { whenNextBound(closure); } /** * Schedule closure to be executed by pooled actor after the next data becomes available * It is important to notice that even if data already available the execution of closure * will not happen immediately but will be scheduled. * * @param closure closure to execute when data available */ public void whenNextBound(final Closure closure) { getValAsync(new DataCallback(closure)); } /** * Send the next bound piece of data to the provided stream when it becomes available * * @param stream stream where to send result */ public void whenNextBound(final MessageStream stream) { getValAsync(stream); } /** * Schedule closure to be executed by pooled actor each time after data becomes available * It is important to notice that even if data already available the execution of closure * will not happen immediately but will be scheduled. * * @param closure closure to execute when data available */ public void whenBound(final Closure closure) { whenBoundListeners.add(new DataCallback(closure)); } /** * Send all pieces of data bound in the future to the provided stream when it becomes available * * @param stream stream where to send result */ public void whenBound(final MessageStream stream) { whenBoundListeners.add(stream); } /** * Checks whether there's a DFV waiting in the queue and retrieves it. If not, a new unmatched value request, represented * by a new DFV, is added to the requests queue. * * @return The DFV to wait for value on */ private DataFlowVariable retrieveOrCreateVariable() { return copyDFV(queue, requests); } /** * Returns the current size of the buffer * * @return Number of DFVs in the queue */ public int length() { return queue.size(); } /** * Returns an iterator over a current snapshot of the buffer's content. The next() method returns actual values * not the DataFlowVariables. * * @return AN iterator over all DFVs in the queue */ public Iterator iterator() { final Iterator> iterator = queue.iterator(); return new Iterator() { public boolean hasNext() { return iterator.hasNext(); } public T next() { try { return iterator.next().getVal(); } catch (InterruptedException e) { throw new IllegalStateException("The thread has been interrupted, which prevented the iterator from retrieving the next element.", e); } } public void remove() { throw new UnsupportedOperationException("Remove not available"); } }; } @Override public String toString() { return "DataFlowStream(queue=" + new ArrayList>(queue).toString() + ')'; } } libgpars-groovy-java-0.10.orig/groovyx/gpars/dataflow/DataFlowInvocationExpression.java0000644000000000000000000000362511365257450026452 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-9 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.dataflow; import org.codehaus.groovy.runtime.InvokerHelper; /** * Data flow expression which invokes method of object after receiver and all arguments became available * * @author Alex Tkachman */ public class DataFlowInvocationExpression extends DataFlowComplexExpression { private static final long serialVersionUID = -678669663648650627L; private Object receiver; private final String methodName; public DataFlowInvocationExpression(final Object receiver, final String methodName, final Object[] args) { super(args); this.receiver = receiver; this.methodName = methodName; subscribe(); } @Override protected Object evaluate() { if (receiver instanceof DataFlowExpression) { receiver = ((DataFlowExpression) receiver).value; } super.evaluate(); return InvokerHelper.invokeMethod(receiver, methodName, args); } @Override protected void subscribe(final DataFlowExpressionsCollector listener) { if (receiver instanceof DataFlowExpression) { receiver = listener.subscribe(receiver); } super.subscribe(listener); } } libgpars-groovy-java-0.10.orig/groovyx/gpars/dataflow/DataFlowGetPropertyExpression.java0000644000000000000000000000313511365257450026621 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-9 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.dataflow; import org.codehaus.groovy.runtime.InvokerHelper; /** * DFE which evaluate property when receiver became available * * @author Alex Tkachman */ public class DataFlowGetPropertyExpression extends DataFlowExpression { private static final long serialVersionUID = 2984824057556784227L; private final DataFlowExpression receiver; private final String name; public DataFlowGetPropertyExpression(final DataFlowExpression expression, final String name) { this.receiver = expression; this.name = name; subscribe(); } @Override protected void subscribe(final DataFlowExpressionsCollector listener) { listener.subscribe(receiver); } @Override @SuppressWarnings("unchecked") protected T evaluate() { //noinspection unchecked return (T) InvokerHelper.getProperty(receiver.value, name); } } libgpars-groovy-java-0.10.orig/groovyx/gpars/dataflow/DataFlowPGroup.java0000644000000000000000000000305211365257450023467 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-9 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.dataflow; import groovyx.gpars.group.PGroup; import groovyx.gpars.scheduler.ResizeablePool; /** * Groups all dataflow threads, tasks and operators. * DataFlow leverages a resizeable pool of non-daemon threads. * DataFlowPGroup can be used directly to create and group dataflow actors (threads) *
 * DataFlowPGroup group = new DataFlowPGroup()
 * group.actor {
 *     ....
 * }
 * 
* * @author Vaclav Pech, Alex Tkachman * Date: Jun 21, 2009 */ public final class DataFlowPGroup extends PGroup { /** * Creates a default group for dataflow tasks and operators. The actors will share a common non-daemon thread pool. * * @param poolSize The initial size of the underlying thread pool */ public DataFlowPGroup(final int poolSize) { super(new ResizeablePool(false, poolSize)); } } libgpars-groovy-java-0.10.orig/groovyx/gpars/dataflow/DataFlowVariable.java0000644000000000000000000000716511371773756024022 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-9 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.dataflow; import groovyx.gpars.actor.impl.MessageStream; import groovyx.gpars.remote.RemoteHost; import groovyx.gpars.serial.RemoteSerialized; /** * Represents a thread-safe single-assignment, multi-read variable. * Each instance of DataFlowVariable can be read repeatedly any time using the 'val' property and assigned once * in its lifetime using the '<<' operator. Reads preceding assignment will be blocked until the value * is assigned. * For actors and Dataflow Operators the asynchronous non-blocking variants of the getValAsync() methods can be used. * They register the request to read a value and will send a message to the actor or operator once the value is available. * * @author Vaclav Pech, Alex Tkachman * Date: Jun 4, 2009 * @param Type of values to bind with the DataFlowVariable */ @SuppressWarnings({"AccessingNonPublicFieldOfAnotherObject", "UnqualifiedStaticUsage"}) public class DataFlowVariable extends DataFlowExpression { private static final long serialVersionUID = 1340439210749936258L; /** * Creates a new unbound Dataflow Variable */ public DataFlowVariable() { } /** * Assigns a value to the variable. Can only be invoked once on each instance of DataFlowVariable * * @param value The value to assign */ public void leftShift(final T value) { bind(value); } /** * Assigns a value from one DataFlowVariable instance to this variable. * Can only be invoked once on each instance of DataFlowVariable * * @param ref The DataFlowVariable instance the value of which to bind */ public void leftShift(final DataFlowExpression ref) { ref.getValAsync(new MessageStream() { private static final long serialVersionUID = -458384302762038543L; @Override public MessageStream send(final Object message) { bind(ref.value); return this; } }); } @Override public Class getRemoteClass() { return RemoteDataFlowVariable.class; } public static class RemoteDataFlowVariable extends DataFlowVariable implements RemoteSerialized { private static final long serialVersionUID = -420013188758006693L; private final RemoteHost remoteHost; private boolean disconnected; public RemoteDataFlowVariable(final RemoteHost host) { remoteHost = host; getValAsync(new MessageStream() { private static final long serialVersionUID = 7968302123667353660L; @Override public MessageStream send(final Object message) { if (!disconnected) { remoteHost.write(new BindDataFlow(RemoteDataFlowVariable.this, message, remoteHost.getHostId())); } return this; } }); } } } libgpars-groovy-java-0.10.orig/groovyx/gpars/dataflow/DataCallback.groovy0000644000000000000000000000336411365257450023531 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-9 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.dataflow import groovyx.gpars.actor.Actors import groovyx.gpars.actor.impl.MessageStream /** * * A helper class enabling the 'whenBound()' functionality of a DataFlowVariable. * An actor that waits asynchronously on the DFV to be bound. Once the DFV is bound, * upon receiving the message the actor runs the supplied closure / code with the DFV value as a parameter. * * @author Vaclav Pech, Alex Tkachman * Date: Sep 13, 2009 */ final class DataCallback extends MessageStream { private static final long serialVersionUID = 6512046150477794254L; private final Closure code /** * @param code The closure to run */ DataCallback(final Closure code) { this.code = code } /** * Sends a message back to the DataCallback. * Will schedule processing the internal closure with the thread pool */ @Override public MessageStream send(Object message) { Actors.defaultActorPGroup.threadPool.execute { code.call message }; return this; } }libgpars-groovy-java-0.10.orig/groovyx/gpars/dataflow/RemoteDataFlowExpression.java0000644000000000000000000000343211374454000025556 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-10 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.dataflow; import groovyx.gpars.actor.impl.MessageStream; import groovyx.gpars.remote.RemoteHost; import groovyx.gpars.serial.RemoteSerialized; import groovyx.gpars.serial.SerialContext; /** * @author Alex Tkachman */ public class RemoteDataFlowExpression extends DataFlowExpression implements RemoteSerialized { private static final long serialVersionUID = -3166182949181062129L; private final RemoteHost remoteHost; public RemoteDataFlowExpression() { remoteHost = (RemoteHost) SerialContext.get(); getValAsync(new MessageStream() { private static final long serialVersionUID = -8868544599311892034L; public MessageStream send(final Object message) { remoteHost.write(new BindDataFlow(RemoteDataFlowExpression.this, message, remoteHost.getHostId())); return this; } }); } protected T evaluate() { return value; } protected void subscribe(final DataFlowExpression.DataFlowExpressionsCollector listener) { listener.subscribe(this); } } libgpars-groovy-java-0.10.orig/groovyx/gpars/dataflow/SingleRunActor.groovy0000644000000000000000000000177211347765306024147 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-9 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.dataflow /** * An actor representing a dataflow thread. Runs the supplied block of code inside the act() actor method once. * * @author Vaclav Pech, Dierk Koenig * Date: Jun 5, 2009 */ final class SingleRunActor extends DataFlowActor { Closure body void act() { body.delegate = this body() } } libgpars-groovy-java-0.10.orig/groovyx/gpars/dataflow/DataFlow.groovy0000644000000000000000000000472011365257450022741 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-10 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.dataflow import groovyx.gpars.actor.Actor import groovyx.gpars.dataflow.operator.DataFlowOperator /** * Contains factory methods to create dataflow actors and starting them. * * @author Vaclav Pech, Dierk Koenig * Date: Jun 4, 2009 */ public abstract class DataFlow { /** * The actor group used by all Dataflow Concurrency actors by default. */ public static final DataFlowPGroup DATA_FLOW_GROUP = new DataFlowPGroup(1) /** * Tasks need no channels */ private static def taskChannels = [inputs: [], outputs: []] /** * Creates a new instance of SingleRunActor to run the supplied code. * In general cases prefer task() instead, which is more lightweight. */ public static Actor start(final Closure code) { new SingleRunActor(body: code).start() } /** * Creates a new task assigned to a thread from the default dataflow actor group. * Tasks are a lightweight version of dataflow operators, which do not define their communication channels explicitly, * but can only exchange data using explicit DataFlowVariables and Streams. * @param code The task body to run */ public static void task(final Closure code) { DataFlow.DATA_FLOW_GROUP.task code } /** * Creates an operator using the default operator actor group * @param channels A map specifying "inputs" and "outputs" - dataflow channels (instances of the DataFlowStream or DataFlowVariable classes) to use for inputs and outputs * @param code The operator's body to run each time all inputs have a value to read */ public static DataFlowOperator operator(final Map channels, final Closure code) { DataFlow.DATA_FLOW_GROUP.operator(channels, code) } } libgpars-groovy-java-0.10.orig/groovyx/gpars/GParsPool.groovy0000644000000000000000000003477011374454000021303 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-10 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars import groovyx.gpars.util.PoolUtils import java.lang.Thread.UncaughtExceptionHandler import java.util.concurrent.Future import java.util.concurrent.TimeUnit import jsr166y.forkjoin.RecursiveTask /** * Enables a ParallelArray-based (from JSR-166y) DSL on collections. In general cases the Parallel Array implementation * shows to be much faster (10 - 20 times) compared to the executor service implementation in GParsExecutorsPool. * E.g.
 GParsPool.withPool(5) {final AtomicInteger result = new AtomicInteger(0)
 [1, 2, 3, 4, 5].eachParallel {result.addAndGet(it)}assertEquals 15, result}GParsPool.withPool(5) {final List result = [1, 2, 3, 4, 5].collectParallel {it * 2}assert ([2, 4, 6, 8, 10].equals(result))}GParsPool.withPool(5) {assert [1, 2, 3, 4, 5].everyParallel {it > 0}assert ![1, 2, 3, 4, 5].everyParallel {it > 1}}
* @author Vaclav Pech * Date: Oct 23, 2008 */ public class GParsPool { /** * Maps threads to their appropriate thread pools */ private static final ThreadLocalPools currentPoolStack = new ThreadLocalPools() /** * Caches the default pool size. */ private static final int defaultPoolSize = PoolUtils.retrieveDefaultPoolSize() /** * Retrieves the pool assigned to the current thread. */ protected static retrieveCurrentPool() { currentPoolStack.current } /** * Creates a new pool with the default size() */ private static createPool() { return createPool(PoolUtils.retrieveDefaultPoolSize()) } /** * Creates a new pool with the given size() */ private static createPool(int poolSize) { return createPool(poolSize, createDefaultUncaughtExceptionHandler()) } private static createPool(int poolSize, UncaughtExceptionHandler handler) { if (!(poolSize in 1..Integer.MAX_VALUE)) throw new IllegalArgumentException("Invalid value $poolSize for the pool size has been specified. Please supply a positive int number.") final jsr166y.forkjoin.ForkJoinPool pool = new jsr166y.forkjoin.ForkJoinPool(poolSize) pool.uncaughtExceptionHandler = handler return pool } /** * Creates a new instance of ForkJoinPool, binds it to the current thread, enables the ParallelArray DSL * and runs the supplied closure. * Within the supplied code block the ForkJoinPool is available as the only parameter, collections have been * enhanced with the eachParallel(), collectParallel() and other methods from the GParsPoolUtil * category class. * E.g. calling images.eachParallel{processImage(it}} will call the potentially long-lasting processImage() * operation on each image in the images collection in parallel. * Be sure to synchronize all modifiable state shared by the asynchronously running closures. *
     * GParsPool.withPool {GParsPool pool ->
     *     def result = Collections.synchronizedSet(new HashSet())
     *     [1, 2, 3, 4, 5].eachParallel {Number number -> result.add(number * 10)}*     assertEquals(new HashSet([10, 20, 30, 40, 50]), result)
     *}* 
* @param cl The block of code to invoke with the DSL enabled */ public static withPool(Closure cl) { return withPool(defaultPoolSize, cl) } /** * Creates a new instance of ForkJoinPool, binds it to the current thread, enables the ParallelArray DSL * and runs the supplied closure. * Within the supplied code block the ForkJoinPool is available as the only parameter, collections have been * enhanced with the eachParallel(), collectParallel() and other methods from the GParsPoolUtil * category class. * E.g. calling images.eachParallel{processImage(it}} will call the potentially long-lasting processImage() * operation on each image in the images collection in parallel. * Be sure to synchronize all modifiable state shared by the asynchronously running closures. *
     * GParsPool.withPool(5) {GParsPool pool ->
     *     def result = Collections.synchronizedSet(new HashSet())
     *     [1, 2, 3, 4, 5].eachParallel {Number number -> result.add(number * 10)}*     assertEquals(new HashSet([10, 20, 30, 40, 50]), result)
     *}* 
* @param numberOfThreads Number of threads in the newly created thread pool * @param cl The block of code to invoke with the DSL enabled */ public static withPool(int numberOfThreads, Closure cl) { return withPool(numberOfThreads, createDefaultUncaughtExceptionHandler(), cl) } /** * Creates a new instance of ForkJoinPool, binds it to the current thread, enables the ParallelArray DSL * and runs the supplied closure. * Within the supplied code block the ForkJoinPool is available as the only parameter, collections have been * enhanced with the eachParallel(), collectParallel() and other methods from the GParsPoolUtil * category class. * E.g. calling images.eachParallel{processImage(it}} will call the potentially long-lasting processImage() * operation on each image in the images collection in parallel. * Be sure to synchronize all modifiable state shared by the asynchronously running closures. *
     * GParsPool.withPool(5, handler) {GParsPool pool ->
     *     def result = Collections.synchronizedSet(new HashSet())
     *     [1, 2, 3, 4, 5].eachParallel {Number number -> result.add(number * 10)}*     assertEquals(new HashSet([10, 20, 30, 40, 50]), result)
     *}* 
* @param numberOfThreads Number of threads in the newly created thread pool * @param handler Handler for uncaught exceptions raised in code performed by the pooled threads * @param cl The block of code to invoke with the DSL enabled */ public static withPool(int numberOfThreads, UncaughtExceptionHandler handler, Closure cl) { final jsr166y.forkjoin.ForkJoinPool pool = createPool(numberOfThreads, handler) try { return withExistingPool(pool, cl) } finally { pool.shutdown() pool.awaitTermination(Long.MAX_VALUE, TimeUnit.MILLISECONDS) } } /** * Reuses an instance of ForkJoinPool, binds it to the current thread, enables the ParallelArray DSL * and runs the supplied closure. * Within the supplied code block the ForkJoinPool is available as the only parameter, collections have been * enhanced with the eachParallel(), collectParallel() and other methods from the GParsPoolUtil * category class. * E.g. calling images.eachParallel{processImage(it}} will call the potentially long-lasting processImage() * operation on each image in the images collection in parallel. * Be sure to synchronize all modifiable state shared by the asynchronously running closures. *
     * GParsPool.withExistingPool(anotherPool) {GParsPool pool ->
     *     def result = Collections.synchronizedSet(new HashSet())
     *     [1, 2, 3, 4, 5].eachParallel {Number number -> result.add(number * 10)}*     assertEquals(new HashSet([10, 20, 30, 40, 50]), result)
     *}*  
* @param pool The thread pool to use, the pool will not be shutdown after this method returns */ public static withExistingPool(jsr166y.forkjoin.ForkJoinPool pool, Closure cl) { currentPoolStack << pool def result = null try { use(GParsPoolUtil) { result = cl(pool) } } finally { currentPoolStack.pop() } return result } /** * Just like withExistingPool() registers a thread pool, but doesn't install the GParsPoolUtil category. * Used by ParallelEnhancer's Parallel mixins. */ static ensurePool(final jsr166y.forkjoin.ForkJoinPool pool, final Closure cl) { currentPoolStack << pool try { return cl(pool) } finally { currentPoolStack.pop() } } /** * Starts multiple closures in separate threads, collecting their return values * Reuses the pool defined by the surrounding withPool() call. * If an exception is thrown from the closure when called on any of the collection's elements, * it will be re-thrown in the calling thread when it calls the Future.get() method. * @return The result values of all closures * @throws AsyncException If any of the collection's elements causes the closure to throw an exception. The original exceptions will be stored in the AsyncException's concurrentExceptions field. */ public static List executeAsyncAndWait(Closure... closures) { return GParsExecutorsPoolUtil.processResult(executeAsync(closures)) } /** * Starts multiple closures in separate threads, collecting their return values * Reuses the pool defined by the surrounding withPool() call. * If an exception is thrown from the closure when called on any of the collection's elements, * it will be re-thrown in the calling thread when it calls the Future.get() method. * @return The result values of all closures * @throws AsyncException If any of the collection's elements causes the closure to throw an exception. The original exceptions will be stored in the AsyncException's concurrentExceptions field. */ public static List executeAsyncAndWait(List closures) { return executeAsyncAndWait(* closures) } /** * Starts multiple closures in separate threads, collecting Futures for their return values * Reuses the pool defined by the surrounding withPool() call. * If an exception is thrown from the closure when called on any of the collection's elements, * it will be re-thrown in the calling thread when it calls the Future.get() method. * @return Futures for the result values or exceptions of all closures */ public static List> executeAsync(Closure... closures) { jsr166y.forkjoin.ForkJoinPool pool = retrieveCurrentPool() if (pool == null) throw new IllegalStateException("No active Fork/Join thread pool available to execute closures asynchronously.") List> result = closures.collect {cl -> pool.submit([compute: { cl.call() }] as RecursiveTask) } result } /** * Starts multiple closures in separate threads, collecting Futures for their return values * Reuses the pool defined by the surrounding withPool() call. * If an exception is thrown from the closure when called on any of the collection's elements, * it will be re-thrown in the calling thread when it calls the Future.get() method. * @return Futures for the result values or exceptions of all closures */ public static List> executeAsync(List closures) { return executeAsync(* closures) } private static UncaughtExceptionHandler createDefaultUncaughtExceptionHandler() { return {Thread failedThread, Throwable throwable -> System.err.println "Error processing background thread ${failedThread.name}: ${throwable.message}" throwable.printStackTrace(System.err) } as UncaughtExceptionHandler } /** * Starts a ForkJoin calculation with the supplied root worker and waits for the result. * @param rootWorker The worker that calculates the root of the Fork/Join problem * @return The result of the whole calculation */ public static T runForkJoin(final AbstractForkJoinWorker rootWorker) { def pool = GParsPool.retrieveCurrentPool() if (pool == null) throw new IllegalStateException("Cannot initialize ForkJoin. The pool has not been set. Perhaps, we're not inside a GParsPool.withPool() block.") return pool.submit(rootWorker).get() } /** * Starts a ForkJoin calculation with the supplied root worker and waits for the result. * @param rootWorker The worker that calculates the root of the Fork/Join problem * @return The result of the whole calculation */ public static T runForkJoin(final Object... args) { if (args.size() == 0) throw new IllegalArgumentException("No arguments specified to the runForkJoin() method.") if (!(args[-1] instanceof Closure)) throw new IllegalArgumentException("A closure to run implementing the requested Fork/Join algorithm must be specified as the last argument passed to the runForkJoin() method.") Closure code = args[-1] as Closure if (args.size() - 1 != code.maximumNumberOfParameters) throw new IllegalArgumentException("The supplied Fork/Join closure expects ${code.maximumNumberOfParameters} arguments while only ${args.size()} arguments have been supplied to the orchestrate() method.") return runForkJoin(new FJWorker(args)) } } final class FJWorker extends AbstractForkJoinWorker { private final Closure code private final Object[] args def FJWorker(final Object... args) { final def size = args.size() assert size > 0 this.args = size > 1 ? args[0..-2] : ([] as Object[]) this.code = args[-1].clone(); this.code.delegate = this } protected void forkOffChild(Object... childArgs) { if (childArgs.size() != args.size()) throw new IllegalArgumentException("The forkOffChild() method requires ${args.size()} arguments, but received ${childArgs.size()} parameters.") forkOffChild new FJWorker(* childArgs, code) } protected T computeTask() { return code.call(* args) } } libgpars-groovy-java-0.10.orig/groovyx/gpars/TransparentParallel.groovy0000644000000000000000000000554111365257450023417 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-10 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars /** * Enhances objects by being mixed-in either within a GParsPool.withPool() block or after enhancement by * the ParallelEnhancer through the makeTransparent() method. * It overrides the iterative methods, like each, collect and such to delegate to eachParallel, collectParallel * and other parallel iterative methods. * The collections returned from collect(), findAll() and grep() are again mixed with a TransparentParallel instance, * so their iterative methods are transparently parallel as well. * * Author: Vaclav Pech, Dierk Koenig * Date: Oct 30, 2009 */ final class TransparentParallel { public def final each(Closure yield) { this.eachParallel(yield) } public def final eachWithIndex(Closure yield) { this.eachWithIndexParallel(yield)} public def final collect(Closure yield) { this.collectParallel(yield).makeTransparent()} public def final find(Closure yield) { this.findParallel(yield)} public def final findAny(Closure yield) { this.findAnyParallel(yield)} public def final findAll(Closure yield) { this.findAllParallel(yield).makeTransparent()} public def final grep(filter) { this.grepParallel(filter).makeTransparent()} public def final split(Closure yield) { this.splitParallel(yield).makeTransparent()} public def final count(filter) { this.countParallel(filter) } public def final every(Closure yield) { this.everyParallel(yield)} public def final any(Closure yield) { this.anyParallel(yield)} public def final groupBy(Closure yield) { this.groupByParallel(yield)} public def final min(Closure yield) { this.minParallel(yield)} public def final min() { this.minParallel()} public def final max(Closure yield) { this.maxParallel(yield)} public def final max() { this.maxParallel()} public def final sum() { this.sumParallel()} public def final fold(Closure yield) { this.foldParallel(yield)} public def final fold(seed, Closure yield) { this.foldParallel(seed, yield)} /** * Indicates, whether the iterative methods like each() or collect() have been made parallel. */ public def boolean isTransparent() {return true} } libgpars-groovy-java-0.10.orig/groovyx/gpars/serial/0000755000000000000000000000000011374454000017432 5ustar libgpars-groovy-java-0.10.orig/groovyx/gpars/serial/DefaultRemoteHandle.java0000644000000000000000000000277111347765306024176 0ustar // GPars (formerly GParallelizer) // // Copyright � 2008-9 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.serial; import groovyx.gpars.remote.RemoteHost; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.util.UUID; /** * @author Alex Tkachman */ public class DefaultRemoteHandle extends RemoteHandle { private static final long serialVersionUID = 3543416239144672233L; private final Class klazz; public DefaultRemoteHandle(final UUID id, final UUID hostId, final Class klazz) { super(hostId, id); this.klazz = klazz; } @Override protected WithSerialId createObject(final SerialContext context) throws InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException { final Constructor constructor = klazz.getConstructor(RemoteHost.class); return (WithSerialId) constructor.newInstance(context); } } libgpars-groovy-java-0.10.orig/groovyx/gpars/serial/RemoteHandle.java0000644000000000000000000000373711347765306022674 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-9 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.serial; import java.io.ObjectStreamException; import java.io.Serializable; import java.io.WriteAbortedException; import java.lang.reflect.InvocationTargetException; import java.util.UUID; /** * @author Alex Tkachman */ public abstract class RemoteHandle implements Serializable { protected final UUID serialId; protected final UUID hostId; public RemoteHandle(final UUID hostId, final UUID id) { this.hostId = hostId; serialId = id; } @SuppressWarnings({"CatchGenericClass", "UnusedDeclaration", "OverlyBroadCatchBlock"}) protected final Object readResolve() throws ObjectStreamException { final SerialContext context = SerialContext.get(); final SerialHandle serialHandle = context.get(serialId); WithSerialId obj; if (serialHandle == null || (obj = serialHandle.get()) == null) { try { obj = createObject(context); obj.serialHandle = SerialHandle.create(obj, serialId); } catch (Exception t) { throw new WriteAbortedException(t.getMessage(), t); } } return obj; } protected abstract WithSerialId createObject(SerialContext context) throws InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException; } libgpars-groovy-java-0.10.orig/groovyx/gpars/serial/SerialMsg.java0000644000000000000000000000222011347765306022175 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-9 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.serial; import groovyx.gpars.remote.RemoteConnection; import java.io.Serializable; import java.util.UUID; /** * Base class for all messages * * @author Alex Tkachman, Vaclav Pech */ public abstract class SerialMsg implements Serializable { public UUID hostId; protected SerialMsg() { } protected SerialMsg(final UUID hostId) { this.hostId = hostId; } public void execute(final RemoteConnection conn) { conn.onMessage(this); } } libgpars-groovy-java-0.10.orig/groovyx/gpars/serial/LocalHandle.java0000644000000000000000000000242111347765306022460 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-9 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.serial; import java.io.ObjectStreamException; import java.io.Serializable; import java.util.UUID; /** * @author Alex Tkachman */ public final class LocalHandle implements Serializable { private static final long serialVersionUID = -8206894167996286304L; private final UUID id; public LocalHandle(final UUID id) { this.id = id; } @SuppressWarnings({"UnusedDeclaration", "ProtectedMemberInFinalClass"}) protected Object readResolve() throws ObjectStreamException { return SerialContext.get().get(id).get(); } public UUID getId() { return id; } } libgpars-groovy-java-0.10.orig/groovyx/gpars/serial/WithSerialId.java0000644000000000000000000000657711347765306022662 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-9 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.serial; import java.io.ObjectStreamException; import java.io.Serializable; /** * Base class for objects which can be exposed to remote nodes via serialization. *

* Main concept is following: * - each object belongs to some LocalHost * - every object can be exposed to any {@link groovyx.gpars.remote.RemoteHost} * - on remote host object is represented by proxy usually called remote object * - for serialization we use writeReplace method, which creates special handle to be serialized instead of the object * - for deserialization handle's readResolve method creates remote object (proxy) *

* See {@link java.io.Serializable} for detailed description how methods writeReplace & readResolve works. *

* It is very important to know that (de)serialization never happens by itself but * always happens in context of {@link groovyx.gpars.remote.RemoteHost} and (@link LocalHost}. * Such context is used for right resolution/transformation of objects * * @author Alex Tkachman */ public abstract class WithSerialId implements Serializable { /** * See SerialHandle class for details */ public volatile SerialHandle serialHandle; /** * Gets serial handle for the object * If needed new handle created and serialization host subscribed for the object handle * * @return serial handle for the object */ public final SerialHandle getOrCreateSerialHandle() { if (serialHandle == null) { synchronized (this) { if (serialHandle == null) { serialHandle = SerialHandle.create(this, null); } } } return serialHandle; } /** * Class of remote object to be created * * @return Throws UnsupportedOperationException */ public Class getRemoteClass() { throw new UnsupportedOperationException(); } /** * Replace object by handle for serialization * * @return handle to serialize * @throws ObjectStreamException If the object cannot be serialized */ @SuppressWarnings({"UnusedDeclaration"}) protected final Object writeReplace() throws ObjectStreamException { final SerialHandle handle = getOrCreateSerialHandle(); if (this instanceof RemoteSerialized) { return new LocalHandle(handle.getSerialId()); } final SerialContext host = SerialContext.get(); handle.subscribe(host); return createRemoteHandle(handle, host); } protected RemoteHandle createRemoteHandle(final SerialHandle handle, final SerialContext host) { return new DefaultRemoteHandle(handle.getSerialId(), host.getHostId(), getRemoteClass()); } } libgpars-groovy-java-0.10.orig/groovyx/gpars/serial/RemoteSerialized.java0000644000000000000000000000151711347765306023566 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-9 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.serial; /** * Marker interface for objects, which are proxies to objects on other nodes. * * @author Alex Tkachman */ public interface RemoteSerialized { } libgpars-groovy-java-0.10.orig/groovyx/gpars/serial/SerialHandle.java0000644000000000000000000001446211365257450022651 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-9 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.serial; import groovyx.gpars.remote.RemoteConnection; import groovyx.gpars.remote.RemoteHost; import org.codehaus.groovy.util.ManagedReference; import org.codehaus.groovy.util.ReferenceBundle; import org.codehaus.groovy.util.ReferenceManager; import org.codehaus.groovy.util.ReferenceType; import java.lang.ref.ReferenceQueue; import java.util.ArrayList; import java.util.List; import java.util.UUID; /** * Weak reference to object, which was serialized to remote hosts. * Also keep ids of all hosts, where the object was serialized. *

* While subscribed by remote nodes it keeps object alive by holding strong reference (anchor) to it * * @author Alex Tkachman */ public class SerialHandle extends ManagedReference { private static final ReferenceQueue queue = new ReferenceQueue(); private static final ReferenceManager manager = ReferenceManager.createThreadedManager(queue); private static final ReferenceBundle bundle = new ReferenceBundle(manager, ReferenceType.WEAK); /** * serial id of the object */ protected final UUID serialId; /** * local host */ protected final SerialContext context; /** * remote hosts subscribed to this objects */ private volatile Object subscribers; private volatile WithSerialId anchor; /** * Construct handle for object with given id to it * * @param value */ private SerialHandle(final WithSerialId value, final UUID id) { super(bundle, value); context = SerialContext.get(); if (id == null) { serialId = UUID.randomUUID(); } else { serialId = id; } context.add(this); } /** * Serial id of the object * * @return The serial id */ public UUID getSerialId() { return serialId; } @Override public void finalizeReference() { context.finalizeHandle(this); super.finalizeReference(); } /** * Getter for subscribers * * @return The current subscribers */ public Object getSubscribers() { return subscribers; } /** * Subscribes host as interested in the object * * @param context */ public void subscribe(final SerialContext context) { synchronized (this) { if (subscribers == null) { subscribers = context; } else { if (subscribers instanceof SerialContext) { if (subscribers != context) { final ArrayList list = new ArrayList(2); list.add((SerialContext) subscribers); list.add(context); subscribers = list; } } else { @SuppressWarnings({"unchecked"}) final List list = (List) subscribers; for (final SerialContext remoteHost : list) { if (remoteHost == context) { return; } } list.add(context); } } anchor = get(); } } public void unsubscribe(final SerialContext context) { synchronized (this) { if (subscribers != null) { if (subscribers instanceof SerialContext) { if (subscribers == context) { subscribers = null; } } else { @SuppressWarnings({"unchecked"}) final List list = (List) subscribers; list.remove(context); if (list.size() == 1) { subscribers = list.get(0); } } } if (subscribers == null) { anchor = null; } } } public static SerialHandle create(final WithSerialId obj, final UUID id) { if (id == null) { return new LocalSerialHandle(obj, UUID.randomUUID()); } else { return new RemoteSerialHandle(obj, id); } } private static class LocalSerialHandle extends SerialHandle { public LocalSerialHandle(final WithSerialId obj, final UUID uuid) { super(obj, uuid); } } private static class RemoteSerialHandle extends SerialHandle { private RemoteSerialHandle(final WithSerialId obj, final UUID uuid) { super(obj, uuid); } @Override public void finalizeReference() { super.finalizeReference(); context.write(new ReleaseHandle(serialId)); } public static class ReleaseHandle extends SerialMsg { private static final long serialVersionUID = -951052191389868427L; private final UUID serialId; public ReleaseHandle(final UUID serialId) { this.serialId = serialId; } @Override public void execute(final RemoteConnection conn) { final RemoteHost remoteHost = conn.getHost(); final SerialHandle handle = remoteHost.get(serialId); if (handle instanceof LocalSerialHandle) { handle.unsubscribe(remoteHost); } } } } } libgpars-groovy-java-0.10.orig/groovyx/gpars/serial/SerialContext.java0000644000000000000000000000473311374454000023070 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-10 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.serial; import java.util.UUID; /** * @author Alex Tkachman */ public abstract class SerialContext { private static final ThreadLocal threadContext = new ThreadLocal(); protected final SerialHandles localHost; protected final UUID hostId; public SerialContext(final SerialHandles localHost, final UUID hostId) { this.localHost = localHost; this.hostId = hostId; } public static SerialContext get() { return threadContext.get(); } public UUID getHostId() { return hostId; } /** * Enter to the context */ public final void enter() { if (threadContext.get() != null) { throw new IllegalStateException("Serialization context already defined"); } threadContext.set(this); } /** * Leave this context */ public final void leave() { if (threadContext.get() != this) { throw new IllegalStateException("Wrong serialization context"); } threadContext.set(null); } public UUID getLocalHostId() { return localHost.getId(); } public void add(final SerialHandle serialHandle) { localHost.add(serialHandle); } public void remove(final SerialHandle serialHandle) { localHost.remove(serialHandle); } public SerialHandle get(final UUID id) { return localHost.get(id); } public void finalizeHandle(final SerialHandle handle) { localHost.finalizeHandle(handle); } public SerialContext getSerialHost(final UUID hostId, final Object attachment) { return localHost.getSerialHost(hostId, attachment); } public abstract void write(SerialMsg msg); } libgpars-groovy-java-0.10.orig/groovyx/gpars/serial/SerialHandles.java0000644000000000000000000000330311347765306023030 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-9 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.serial; import java.util.HashMap; import java.util.UUID; /** * @author Alex Tkachman */ public abstract class SerialHandles { /** * Unique id of the provider */ protected final UUID id = UUID.randomUUID(); /** * Table of local objects serialized out to remote nodes */ private final HashMap localHandles = new HashMap(); /** * Getter for provider id * * @return unique id */ public UUID getId() { return id; } public void add(final SerialHandle handle) { localHandles.put(handle.getSerialId(), handle); } public void remove(final SerialHandle handle) { localHandles.remove(handle.getSerialId()); } public SerialHandle get(final UUID id) { return localHandles.get(id); } public void finalizeHandle(final SerialHandle handle) { localHandles.remove(handle.getSerialId()); } public abstract SerialContext getSerialHost(UUID hostId, Object attachment); } libgpars-groovy-java-0.10.orig/groovyx/gpars/group/0000755000000000000000000000000011365257450017321 5ustar libgpars-groovy-java-0.10.orig/groovyx/gpars/group/ActorGroup.groovy0000644000000000000000000001340011371776724022662 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-10 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.group import groovyx.gpars.actor.AbstractPooledActor import groovyx.gpars.actor.DynamicDispatchActor import groovyx.gpars.actor.ReactiveActor import groovyx.gpars.actor.impl.RunnableBackedPooledActor import groovyx.gpars.agent.Agent import groovyx.gpars.dataflow.operator.DataFlowOperator import groovyx.gpars.scheduler.Pool /** * Provides a common super class of pooled actor groups. * * @author Vaclav Pech, Alex Tkachman * Date: May 8, 2009 */ public abstract class PGroup { /** * Stores the group actors' thread pool */ private @Delegate Pool threadPool public Pool getThreadPool() { return threadPool; } /** * Creates a group for actors, agents, tasks and operators. The actors will share a common daemon thread pool. */ protected def PGroup(final Pool threadPool) { this.threadPool = threadPool } /** * Creates a new instance of PooledActor, using the passed-in runnable/closure as the body of the actor's act() method. * The created actor will belong to the pooled actor group. * @param handler The body of the newly created actor's act method. * @return A newly created instance of the AbstractPooledActor class */ public final AbstractPooledActor actor(Runnable handler) { final AbstractPooledActor actor = new RunnableBackedPooledActor(handler) actor.actorGroup = this actor.start() return actor } /** * Creates a reactor around the supplied code. * When a reactor receives a message, the supplied block of code is run with the message * as a parameter and the result of the code is send in reply. * @param The code to invoke for each received message * @return A new instance of ReactiveEventBasedThread */ public final AbstractPooledActor reactor(final Closure code) { final def actor = new ReactiveActor(code) actor.actorGroup = this actor.start() actor } /** * Creates an instance of DynamicDispatchActor. * @param code The closure specifying individual message handlers. */ public final AbstractPooledActor messageHandler(final Closure code) { final def actor = new DynamicDispatchActor(code) actor.actorGroup = this actor.start() actor } /** * Creates an agent instance initialized with the given state * @param state The initial internal state of the new Agent instance * @return The created instance */ public final Agent agent(final def state) { final Agent safe = new Agent(state) safe.attachToThreadPool threadPool return safe } /** * Creates an agent instance initialized with the given state * @param state The initial internal state of the new Agent instance * @param copy A closure to use to create a copy of the internal state when sending the internal state out * @return The created instance */ public final Agent agent(final def state, final Closure copy) { final Agent safe = new Agent(state, copy) safe.attachToThreadPool threadPool return safe } /** * Creates an agent instance initialized with the given state, which will cooperate in thread sharing with other Agent instances * in a fair manner. * @param state The initial internal state of the new Agent instance * @return The created instance */ public final Agent fairAgent(final def state) { final Agent safe = agent(state) safe.makeFair() return safe } /** * Creates an agent instance initialized with the given state, which will cooperate in thread sharing with other Agent instances * in a fair manner. * @param copy A closure to use to create a copy of the internal state when sending the internal state out * @param state The initial internal state of the new Agent instance * @return The created instance */ public final Agent fairAgent(final def state, final Closure copy) { final Agent safe = agent(state, copy) safe.makeFair() return safe } /** * Creates a new task assigned to a thread from the current actor group. * Tasks are a lightweight version of dataflow operators, which do not define their communication channels explicitly, * but can only exchange data using explicit DataFlowVariables and Streams. * @param code The task body to run */ public void task(final Closure code) { threadPool.execute code } /** * Creates an operator using the current actor group * @param channels A map specifying "inputs" and "outputs" - dataflow channels (instances of the DataFlowStream or DataFlowVariable classes) to use for inputs and outputs * @param code The operator's body to run each time all inputs have a value to read */ public DataFlowOperator operator(final Map channels, final Closure code) { return new DataFlowOperator(channels, code).start(this) } } libgpars-groovy-java-0.10.orig/groovyx/gpars/group/NonDaemonPGroup.groovy0000644000000000000000000000371611371776724023621 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-10 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.group import groovyx.gpars.scheduler.DefaultPool /** * Provides logical grouping for actors, agents and dataflow tasks and operators. Each group has an underlying thread pool, which will perform actions * on behalf of the users belonging to the group. Actors created through the DefaultPGroup.actor() method * will automatically belong to the group through which they were created, just like agents created through the agent() or fairAgent() methods * or dataflow tasks and operators created through the task() or operator() methods. * Uses a pool of non-daemon threads. * The DefaultPGroup class implements the Pool interface through @Delegate. * * @author Vaclav Pech * Date: Jun 17, 2009 */ public final class NonDaemonPGroup extends PGroup { /** * Creates a group for actors, agents, tasks and operators. The actors will share a common non-daemon thread pool. */ def NonDaemonPGroup() { super(new DefaultPool(false)) } /** * Creates a group for actors, agents, tasks and operators. The actors will share a common non-daemon thread pool. * @param poolSize The initial size of the underlying thread pool */ def NonDaemonPGroup(final int poolSize) { super(new DefaultPool(false, poolSize)) } } libgpars-groovy-java-0.10.orig/groovyx/gpars/group/DefaultPGroup.groovy0000644000000000000000000000556111371776724023327 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-10 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.group import groovyx.gpars.scheduler.DefaultPool import groovyx.gpars.scheduler.Pool /** * Provides logical grouping for actors, agents and dataflow tasks and operators. Each group has an underlying thread pool, which will perform actions * on behalf of the users belonging to the group. Actors created through the DefaultPGroup.actor() method * will automatically belong to the group through which they were created, just like agents created through the agent() or fairAgent() methods * or dataflow tasks and operators created through the task() or operator() methods. * Uses a pool of non-daemon threads. * The DefaultPGroup class implements the Pool interface through @Delegate. *

 *
 * def group = new DefaultPGroup()
 * group.resize 1
 *
 * def actor = group.actor {*     react {message ->
 *         println message
 *}*}.start()
 *
 * actor.send 'Hi!'
 * ...
 * group.shutdown()
 * 
* * Otherwise, if constructing Actors directly through their constructors, the AbstractPooledActor.actorGroup property, * which defaults to the Actors.defaultActorPGroup, can be set before the actor is started. * *
 * def group = new DefaultPGroup()
 *
 * def actor = new MyActor()
 * actor.actorGroup = group
 * actor.start()
 * ...
 * group.shutdown()
 *
 * 
* * @author Vaclav Pech * Date: May 4, 2009 */ public final class DefaultPGroup extends PGroup { /** * Creates a group for actors, agents, tasks and operators. The actors will share the supplied thread pool. * @param threadPool The thread pool to use for the group */ public def DefaultPGroup(final Pool threadPool) { super(threadPool) } /** * Creates a group for actors, agents, tasks and operators. The actors will share a common daemon thread pool. */ def DefaultPGroup() { super(new DefaultPool(true)) } /** * Creates a group for actors, agents, tasks and operators. The actors will share a common daemon thread pool. * @param poolSize The initial size of the underlying thread pool */ def DefaultPGroup(final int poolSize) { super(new DefaultPool(true, poolSize)) } } libgpars-groovy-java-0.10.orig/groovyx/gpars/GParsExecutorsPoolUtil.groovy0000644000000000000000000005106111365257450024045 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-10 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars import java.util.concurrent.Callable import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.ConcurrentLinkedQueue import java.util.concurrent.ExecutorService import java.util.concurrent.Future import java.util.concurrent.Semaphore import java.util.concurrent.atomic.AtomicBoolean import java.util.concurrent.atomic.AtomicReference /** * This class forms the core of the DSL initialized by GParsExecutorsPool. The static methods of GParsExecutorsPoolUtil * get attached to their first arguments (the Groovy Category mechanism) and can be then invoked as if they were part of * the argument classes. * @see groovyx.gpars.GParsExecutorsPool * * @author Vaclav Pech * Date: Oct 23, 2008 */ public class GParsExecutorsPoolUtil { /** * schedules the supplied closure for processing in the underlying thread pool. */ private static Future callParallel(Closure task) { final ExecutorService pool = GParsExecutorsPool.retrieveCurrentPool() if (!pool) throw new IllegalStateException("No ExecutorService available for the current thread.") return pool.submit(task as Callable) } /** * Calls a closure in a separate thread supplying the given arguments, returning a future for the potential return value, */ public static Future callAsync(final Closure cl, final Object... args) { callParallel {-> cl(* args)} } /** * Submits the task for asynchronous processing returning the Future received from the executor service. * Allows for the following syntax: *
     * executorService << {println 'Inside parallel task'}* 
*/ public static Future leftShift(ExecutorService executorService, Closure task) { return executorService.submit(task as Callable) } /** * Creates an asynchronous variant of the supplied closure, which, when invoked returns a future for the potential return value */ public static Closure async(Closure cl) { return {Object... args -> callAsync(cl, * args)} } /** * Iterates over a collection/object with the each() method using an asynchronous variant of the supplied closure * to evaluate each collection's element. A Semaphore is used to make the calling thread wait for all the results. * After this method returns, all the closures have been finished and all the potential shared resources have been updated * by the threads. * It's important to protect any shared resources used by the supplied closure from race conditions caused by multi-threaded access. * Example: * GParsExecutorsPool.withPool(5) {ExecutorService service -> * def result = Collections.synchronizedSet(new HashSet()) * service.eachParallel([1, 2, 3, 4, 5]) {Number number -> result.add(number * 10)}* assertEquals(new HashSet([10, 20, 30, 40, 50]), result) *}* Note that the result variable is synchronized to prevent race conditions between multiple threads. * Alternatively a DSL can be used to simplify the code. All collections/objects within the withPool block * have a new eachParallel(Closure cl) method, which delegates to the GParsExecutorsPoolUtil class. * GParsExecutorsPool.withPool(5) {ExecutorService service -> * def result = Collections.synchronizedSet(new HashSet()) * [1, 2, 3, 4, 5].eachParallel { Number number -> result.add(number * 10) }* assertEquals(new HashSet([10, 20, 30, 40, 50]), result) *}* @throws AsyncException If any of the collection's elements causes the closure to throw an exception. The original exceptions will be stored in the AsyncException's concurrentExceptions field. */ public static def eachParallel(Object collection, Closure cl) { final List exceptions = Collections.synchronizedList(new ArrayList()) final Semaphore semaphore = new Semaphore(0) Closure code = async({Object... args -> try { cl(* args) } catch (Throwable e) { exceptions.add(e) } finally { semaphore.release() } }) int count = 0 for (element in collection) { count += 1 code.call(element) } semaphore.acquire(count) if (exceptions.empty) return collection else throw new AsyncException("Some asynchronous operations failed. ${exceptions}", exceptions) } /** * Iterates over a collection/object with the eachWithIndex() method using an asynchronous variant of the supplied closure * to evaluate each collection's element. A Semaphore is used to make the calling thread wait for all the results. * After this method returns, all the closures have been finished and all the potential shared resources have been updated * by the threads. * It's important to protect any shared resources used by the supplied closure from race conditions caused by multi-threaded access. * Example: * GParsExecutorsPool.withPool(5) {ExecutorService service -> * def result = Collections.synchronizedSet(new HashSet()) * service.eachWithIndexParallel([1, 2, 3, 4, 5]) {Number number -> result.add(number * 10)}* assertEquals(new HashSet([10, 20, 30, 40, 50]), result) *}* Note that the result variable is synchronized to prevent race conditions between multiple threads. * Alternatively a DSL can be used to simplify the code. All collections/objects within the withPool block * have a new eachParallel(Closure cl) method, which delegates to the GParsExecutorsPoolUtil class. * GParsExecutorsPool.withPool(5) {ExecutorService service -> * def result = Collections.synchronizedSet(new HashSet()) * [1, 2, 3, 4, 5].eachWithIndexParallel { Number number, int index -> result.add(number * 10) }* assertEquals(new HashSet([10, 20, 30, 40, 50]), result) *}* @throws AsyncException If any of the collection's elements causes the closure to throw an exception. The original exceptions will be stored in the AsyncException's concurrentExceptions field. */ public static def eachWithIndexParallel(Object collection, Closure cl) { final List exceptions = Collections.synchronizedList(new ArrayList()) final Semaphore semaphore = new Semaphore(0) Closure code = async({Object element, int index -> try { cl(element, index) } catch (Throwable e) { exceptions.add(e) } finally { semaphore.release() } }) int count = 0 for (element in collection) { code.call(element, count) count += 1 } semaphore.acquire(count) if (exceptions.empty) return collection else throw new AsyncException("Some asynchronous operations failed. ${exceptions}", exceptions) } /** * Iterates over a collection/object with the collect() method using an asynchronous variant of the supplied closure * to evaluate each collection's element. * After this method returns, all the closures have been finished and the caller can safely use the result. * It's important to protect any shared resources used by the supplied closure from race conditions caused by multi-threaded access. * GParsExecutorsPool.withPool(5) {ExecutorService service -> * def result = service.collectParallel([1, 2, 3, 4, 5]){Number number -> number * 10}* assertEquals(new HashSet([10, 20, 30, 40, 50]), new HashSet((Collection)result)) *}* * Alternatively a DSL can be used to simplify the code. All collections/objects within the withPool block * have a new collectParallel(Closure cl) method, which delegates to the GParsExecutorsPoolUtil class. * GParsExecutorsPool.withPool(5) {ExecutorService service -> * def result = [1, 2, 3, 4, 5].collectParallel{Number number -> number * 10}* assertEquals(new HashSet([10, 20, 30, 40, 50]), new HashSet((Collection)result)) *}* @throws AsyncException If any of the collection's elements causes the closure to throw an exception. The original exceptions will be stored in the AsyncException's concurrentExceptions field. */ public static def collectParallel(Object collection, Closure cl) { return processResult(collection.collect(async(cl))) } /** * Performs the findAll() operation using an asynchronous variant of the supplied closure * to evaluate each collection's/object's element. * After this method returns, all the closures have been finished and the caller can safely use the result. * It's important to protect any shared resources used by the supplied closure from race conditions caused by multi-threaded access. * GParsExecutorsPool.withPool(5) {ExecutorService service -> * def result = service.findAllParallel([1, 2, 3, 4, 5]){Number number -> number > 2}* assertEquals(new HashSet([3, 4, 5]), new HashSet((Collection)result)) *}* * Alternatively a DSL can be used to simplify the code. All collections/objects within the withPool block * have a new findAllParallel(Closure cl) method, which delegates to the GParsExecutorsPoolUtil class. * GParsExecutorsPool.withPool(5) {ExecutorService service -> * def result = [1, 2, 3, 4, 5].findAllParallel{Number number -> number > 2}* assertEquals(new HashSet([3, 4, 5]), new HashSet((Collection)result)) *}* @throws AsyncException If any of the collection's elements causes the closure to throw an exception. The original exceptions will be stored in the AsyncException's concurrentExceptions field. */ public static def findAllParallel(Object collection, Closure cl) { collectParallel(collection, {if (cl(it)) return it else return null}).findAll {it != null} } /** * Performs the grep()() operation using an asynchronous variant of the supplied closure * to evaluate each collection's/object's element. * After this method returns, all the closures have been finished and the caller can safely use the result. * It's important to protect any shared resources used by the supplied closure from race conditions caused by multi-threaded access. * GParsExecutorsPool.withPool(5) {ExecutorService service -> * def result = service.grepParallel([1, 2, 3, 4, 5])(3..6) * assertEquals(new HashSet([3, 4, 5]), new HashSet((Collection)result)) *}* * Alternatively a DSL can be used to simplify the code. All collections/objects within the withPool block * have a new findAllParallel(Closure cl) method, which delegates to the GParsExecutorsPoolUtil class. * GParsExecutorsPool.withPool(5) {ExecutorService service -> * def result = [1, 2, 3, 4, 5].grepParallel(3..6) * assertEquals(new HashSet([3, 4, 5]), new HashSet((Collection)result)) *}* @throws AsyncException If any of the collection's elements causes the closure to throw an exception. The original exceptions will be stored in the AsyncException's concurrentExceptions field. */ public static def grepParallel(Object collection, filter) { collectParallel(collection, {if (filter.isCase(it)) return it else return null}).findAll {it != null} } /** * Performs the find() operation using an asynchronous variant of the supplied closure * to evaluate each collection's/object's element. * After this method returns, all the closures have been finished and the caller can safely use the result. * It's important to protect any shared resources used by the supplied closure from race conditions caused by multi-threaded access. * GParsExecutorsPool.withPool(5) {ExecutorService service -> * def result = service.findParallel([1, 2, 3, 4, 5]){Number number -> number > 2}* assert result in [3, 4, 5] *}* * Alternatively a DSL can be used to simplify the code. All collections/objects within the withPool block * have a new findAllParallel(Closure cl) method, which delegates to the GParsExecutorsPoolUtil class. * GParsExecutorsPool.withPool(5) {ExecutorService service -> * def result = [1, 2, 3, 4, 5].findParallel{Number number -> number > 2}* assert result in [3, 4, 5] *}* @throws AsyncException If any of the collection's elements causes the closure to throw an exception. The original exceptions will be stored in the AsyncException's concurrentExceptions field. */ public static def findParallel(Object collection, Closure cl) { collectParallel(collection, {if (cl(it)) return it else return null}).find {it != null} } /** * Performs the find() operation using an asynchronous variant of the supplied closure * to evaluate each collection's/object's element. Unlike with the find method, findAnyParallel() does not guarantee * that the a matching element with the lowest index is returned. * The findAnyParallel() method evaluates elements lazily and stops processing further elements of the collection once a match has been found. * After this method returns, all the closures have been finished and the caller can safely use the result. * It's important to protect any shared resources used by the supplied closure from race conditions caused by multi-threaded access. * GParsExecutorsPool.withPool(5) {ExecutorService service -> * def result = service.findParallel([1, 2, 3, 4, 5]){Number number -> number > 2}* assert result in [3, 4, 5] *}* * Alternatively a DSL can be used to simplify the code. All collections/objects within the withPool block * have a new findAllParallel(Closure cl) method, which delegates to the GParsExecutorsPoolUtil class. * GParsExecutorsPool.withPool(5) {ExecutorService service -> * def result = [1, 2, 3, 4, 5].findParallel{Number number -> number > 2}* assert result in [3, 4, 5] *}* @throws AsyncException If any of the collection's elements causes the closure to throw an exception. The original exceptions will be stored in the AsyncException's concurrentExceptions field. */ public static def findAnyParallel(Object collection, Closure cl) { final AtomicReference result = new AtomicReference(null) collectParallel(collection, {if ((result.get() == null) && cl(it)) {result.set(it); return it} else return null}).find {it != null} } /** * Performs the all() operation using an asynchronous variant of the supplied closure * to evaluate each collection's/object's element. * After this method returns, all the closures have been finished and the caller can safely use the result. * It's important to protect any shared resources used by the supplied closure from race conditions caused by multi-threaded access. * GParsExecutorsPool.withPool(5) {ExecutorService service -> * assert service.everyParallel([1, 2, 3, 4, 5]){Number number -> number > 0}* assert !service.everyParallel([1, 2, 3, 4, 5]){Number number -> number > 2}*}* * Alternatively a DSL can be used to simplify the code. All collections/objects within the withPool block * have a new findAllParallel(Closure cl) method, which delegates to the GParsExecutorsPoolUtil class. * GParsExecutorsPool.withPool(5) {ExecutorService service -> * assert [1, 2, 3, 4, 5].everyParallel{Number number -> number > 0}* assert ![1, 2, 3, 4, 5].everyParallel{Number number -> number > 2}*}* @throws AsyncException If any of the collection's elements causes the closure to throw an exception. The original exceptions will be stored in the AsyncException's concurrentExceptions field. */ public static boolean everyParallel(Object collection, Closure cl) { final AtomicBoolean flag = new AtomicBoolean(true) eachParallel(collection, {value -> if (!cl(value)) flag.set(false)}) return flag.get() } /** * Performs the any() operation using an asynchronous variant of the supplied closure * to evaluate each collection's/object's element. * After this method returns, all the closures have been finished and the caller can safely use the result. * The anyParallel() method is lazy and once a positive answer has been given by at least one element, it avoids running * the supplied closure on subsequent elements. * It's important to protect any shared resources used by the supplied closure from race conditions caused by multi-threaded access. * GParsExecutorsPool.withPool(5) {ExecutorService service -> * assert service.anyParallel([1, 2, 3, 4, 5]){Number number -> number > 2}* assert !service.anyParallel([1, 2, 3, 4, 5]){Number number -> number > 6}*}* * Alternatively a DSL can be used to simplify the code. All collections/objects within the withPool block * have a new anyParallel(Closure cl) method, which delegates to the GParsExecutorsPoolUtil class. * GParsExecutorsPool.withPool(5) {ExecutorService service -> * assert [1, 2, 3, 4, 5].anyParallel{Number number -> number > 2}* assert ![1, 2, 3, 4, 5].anyParallel{Number number -> number > 6}*}* @throws AsyncException If any of the collection's elements causes the closure to throw an exception. The original exceptions will be stored in the AsyncException's concurrentExceptions field. */ public static boolean anyParallel(Object collection, Closure cl) { final AtomicBoolean flag = new AtomicBoolean(false) eachParallel(collection, {if ((!flag.get()) && cl(it)) flag.set(true)}) return flag.get() } /** * Performs the groupBy() operation using an asynchronous variant of the supplied closure * to evaluate each collection's/object's element. * After this method returns, all the closures have been finished and the caller can safely use the result. * It's important to protect any shared resources used by the supplied closure from race conditions caused by multi-threaded access. * GParsExecutorsPool.withPool(5) {ExecutorService service -> * assert service.groupByParallel(([1, 2, 3, 4, 5]){Number number -> number % 2}).size() == 2 * Alternatively a DSL can be used to simplify the code. All collections/objects within the withPool block * have a new groupByParallel(Closure cl) method, which delegates to the GParsExecutorsPoolUtil class. * GParsExecutorsPool.withPool(5) {ExecutorService service -> * assert ([1, 2, 3, 4, 5].groupByParallel{Number number -> number % 2}).size() == 2 */ public static Map groupByParallel(Object collection, Closure cl) { final def map = new ConcurrentHashMap() eachParallel(collection, { def result = cl(it) final def myList = [it].asSynchronized() def list = map.putIfAbsent(result, myList) if (list != null) list.add(it) }) return map } static List processResult(List> futures) { final Collection exceptions = new ConcurrentLinkedQueue() final List result = futures.collect { try { return it.get() } catch (Throwable e) { exceptions.add(e) return e } } if (exceptions.empty) return result else throw new AsyncException("Some asynchronous operations failed. ${exceptions}", new ArrayList(exceptions)) } } libgpars-groovy-java-0.10.orig/groovyx/gpars/scheduler/0000755000000000000000000000000011374454000020131 5ustar libgpars-groovy-java-0.10.orig/groovyx/gpars/scheduler/Pool.java0000644000000000000000000000270211347765306021724 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-9 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.scheduler; /** * Represents an actor's thread pool * * @author Vaclav Pech * Date: Feb 27, 2009 */ public interface Pool { String POOL_SIZE_MUST_BE_A_POSITIVE_NUMBER = "Pool size must be a positive number."; String UNCAUGHT_EXCEPTION_OCCURRED_IN_ACTOR_POOL = "Uncaught exception occurred in actor pool "; /** * Resizes the thread pool to the specified value * * @param poolSize The new pool size */ void resize(int poolSize); /** * Sets the pool size to the default */ void resetDefaultSize(); /** * schedules a new task for processing with the pool * * @param task The task to schedule */ void execute(Runnable task); /** * Gently stops the pool */ void shutdown(); } libgpars-groovy-java-0.10.orig/groovyx/gpars/scheduler/Scheduler.java0000644000000000000000000001173711374454000022723 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-10 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.scheduler; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; /** * Prototype of self-regulated thread pooled scheduler *

* Self regulation happened according to following rules * - worker thread, which had nothing to do 10 seconds dies * - if no tasks were taken for processing during last 0.5sec new worker starts */ public final class Scheduler implements Pool { private final BlockingQueue queue = new LinkedBlockingQueue(); AtomicInteger threadCount = new AtomicInteger(); volatile long lastTaskPoke = -10L; volatile long schedulerTime; volatile boolean terminating; private final int coreSize; static final RuntimeException TERMINATE = new RuntimeException("terminate"); public Scheduler() { this(0); } public Scheduler(final int coreSize) { this.coreSize = coreSize; new WatchdogThread().start(); for (int i = 0; i != coreSize; ++i) { startNewThread(); } } public void execute(final Runnable task) { if (terminating) { throw new RuntimeException("Scheduler is shutting down"); } try { queue.put(task); if (threadCount.get() == 0) { startNewThread(); } } catch (InterruptedException ignored) { Thread.currentThread().interrupt(); } } public Runnable loop(final Runnable operation) { return new Runnable() { public void run() { operation.run(); if (!terminating) { execute(this); } } }; } private void startNewThread() { threadCount.incrementAndGet(); new WorkerThread().start(); } public void resize(final int poolSize) { throw new UnsupportedOperationException(); } public void resetDefaultSize() { throw new UnsupportedOperationException(); } @SuppressWarnings({"ObjectAllocationInLoop"}) public void shutdown() { terminating = true; final int count = threadCount.get(); for (int i = 0; i != count; ++i) { try { queue.put(new Runnable() { public void run() { throw Scheduler.TERMINATE; } }); } catch (InterruptedException ignored) { // Thread.currentThread().interrupt(); } } } private class WorkerThread extends Thread { { setDaemon(true); } @Override public void run() { try { try { while (!terminating) { final Runnable task = queue.poll(10L, TimeUnit.SECONDS); if (task == null) { return; } lastTaskPoke = schedulerTime; try { task.run(); } catch (Throwable t) { if (Scheduler.TERMINATE != t) { //todo allow for a customizable handler t.printStackTrace(); } } } } catch (InterruptedException e) {// } } finally { threadCount.decrementAndGet(); } } } private class WatchdogThread extends Thread { { setDaemon(true); } @Override public void run() { while (!terminating) { try { schedulerTime++; if (schedulerTime > lastTaskPoke + 10L) { startNewThread(); } Thread.sleep(50L); } catch (InterruptedException e) { break; } } } } } libgpars-groovy-java-0.10.orig/groovyx/gpars/scheduler/DefaultPool.java0000644000000000000000000001253411347765306023235 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-9 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.scheduler; import groovyx.gpars.util.PoolUtils; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicLong; /** * Represents the actors' thread pool, which performs tasks on behalf of the actors. * The actors' thread pool size defaults to the n + 1, where n is the number of processors/cores available on the machine. * The VM parameter -Dgpars.poolsize can be used the configure the default size of the actors' thread pool. * The resize() and resetDefaultSize() methods can be used to configure size of the thread pool at runtime. * * @author Vaclav Pech * Date: Feb 27, 2009 */ public class DefaultPool implements Pool { private ThreadPoolExecutor pool; private static final long SHUTDOWN_TIMEOUT = 30L; /** * Creates the pool with default number of daemon threads. */ public DefaultPool() { this(true); } /** * Creates the pool with default number of threads. * * @param daemon Sets the daemon flag of threads in the pool. */ public DefaultPool(final boolean daemon) { this(daemon, PoolUtils.retrieveDefaultPoolSize()); } /** * Creates the pool with specified number of threads. * * @param daemon Sets the daemon flag of threads in the pool. * @param poolSize The required size of the pool */ public DefaultPool(final boolean daemon, final int poolSize) { PoolUtils.checkValidPoolSize(poolSize); this.pool = DefaultPool.createPool(daemon, poolSize); } /** * Creates the pool around the given executor service * * @param pool The executor service to use */ public DefaultPool(final ThreadPoolExecutor pool) { this.pool = pool; } /** * Creates a fixed-thread pool of given size. Each thread will have the uncaught exception handler set * to print the unhandled exception to standard error output. * * @param daemon Sets the daemon flag of threads in the pool. * @param poolSize The required pool size @return The created thread pool * @return The newly created thread pool */ private static ThreadPoolExecutor createPool(final boolean daemon, final int poolSize) { assert poolSize > 0; return (ThreadPoolExecutor) Executors.newFixedThreadPool(poolSize, new ThreadFactory() { public Thread newThread(final Runnable r) { final Thread thread = new Thread(r, DefaultPool.createThreadName()); thread.setDaemon(daemon); thread.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { @SuppressWarnings({"UseOfSystemOutOrSystemErr"}) public void uncaughtException(final Thread t, final Throwable e) { System.err.println(Pool.UNCAUGHT_EXCEPTION_OCCURRED_IN_ACTOR_POOL + t.getName()); e.printStackTrace(System.err); } }); return thread; } }); } /** * Created a JVM-unique name for Actors' threads. * * @return The name prefix */ protected static String createThreadName() { return "Actor Thread " + DefaultPool.threadCount.incrementAndGet(); } /** * Unique counter for Actors' threads */ private static final AtomicLong threadCount = new AtomicLong(0L); /** * Resizes the thread pool to the specified value * * @param poolSize The new pool size */ public final void resize(final int poolSize) { PoolUtils.checkValidPoolSize(poolSize); pool.setCorePoolSize(poolSize); } /** * Sets the pool size to the default */ public final void resetDefaultSize() { resize(PoolUtils.retrieveDefaultPoolSize()); } /** * schedules a new task for processing with the pool * * @param task The task to schedule */ public final void execute(final Runnable task) { pool.execute(task); } /** * Retrieves the internal executor service. * * @return The underlying thread pool */ public final ExecutorService getExecutorService() { return this.pool; } /** * Gently stops the pool */ public final void shutdown() { pool.shutdown(); try { pool.awaitTermination(DefaultPool.SHUTDOWN_TIMEOUT, TimeUnit.SECONDS); } catch (InterruptedException ignored) { Thread.currentThread().interrupt(); // set the interrupted flag } } } libgpars-groovy-java-0.10.orig/groovyx/gpars/scheduler/FJPool.java0000644000000000000000000001033211374454000022124 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-10 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.scheduler; import groovyx.gpars.util.PoolUtils; import jsr166y.forkjoin.ForkJoinPool; import java.util.concurrent.TimeUnit; /** * Represents the actors' thread pool, which performs tasks on behalf of the actors. Uses a ForkJoinPool from JSR-166y * The actors' thread pool size defaults to the n + 1, where n is the number of processors/cores available on the machine. * The VM parameter -Dgpars.poolsize can be used the configure the default size of the actors' thread pool. * The resize() and resetDefaultSize() methods can be used to configure size of the thread pool at runtime. * * @author Vaclav Pech * Date: Feb 27, 2009 */ public class FJPool implements Pool { protected ForkJoinPool pool; private final int configuredPoolSize; private static final long DEFAULT_SHUTDOWN_TIMEOUT = 30L; /** * Creates the pool with default number of threads. */ public FJPool() { this(PoolUtils.retrieveDefaultPoolSize()); } /** * Creates the pool with specified number of threads. * * @param configuredPoolSize The required size of the pool */ public FJPool(final int configuredPoolSize) { PoolUtils.checkValidPoolSize(configuredPoolSize); this.configuredPoolSize = configuredPoolSize; pool = FJPool.createPool(configuredPoolSize); } /** * Creates a fork/join pool of given size. Each thread will have the uncaught exception handler set * to print the unhandled exception to standard error output. * * @param poolSize The required pool size @return The created thread pool * @return The newly created thread pool */ private static ForkJoinPool createPool(final int poolSize) { assert poolSize > 0; final ForkJoinPool pool = new ForkJoinPool(poolSize); pool.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { @SuppressWarnings({"UseOfSystemOutOrSystemErr"}) public void uncaughtException(final Thread t, final Throwable e) { System.err.println(Pool.UNCAUGHT_EXCEPTION_OCCURRED_IN_ACTOR_POOL + t.getName()); e.printStackTrace(System.err); } }); return pool; } /** * Resizes the thread pool to the specified value * * @param poolSize The new pool size */ public final void resize(final int poolSize) { PoolUtils.checkValidPoolSize(poolSize); pool.setPoolSize(poolSize); } /** * Sets the pool size to the default */ public final void resetDefaultSize() { resize(PoolUtils.retrieveDefaultPoolSize()); } /** * schedules a new task for processing with the pool * * @param task The task to schedule */ public void execute(final Runnable task) { pool.submit(new FJRunnableTask(task)); } /** * Retrieves the internal executor service. * * @return The underlying thread pool */ public final ForkJoinPool getForkJoinPool() { return pool; } /** * Gently stops the pool */ public final void shutdown() { pool.shutdown(); try { pool.awaitTermination(FJPool.DEFAULT_SHUTDOWN_TIMEOUT, TimeUnit.SECONDS); } catch (InterruptedException ignored) { Thread.currentThread().interrupt(); // set the interrupted flag } } protected final int getConfiguredPoolSize() { return configuredPoolSize; } } libgpars-groovy-java-0.10.orig/groovyx/gpars/scheduler/FJRunnableTask.java0000644000000000000000000000236411347765306023630 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-9 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.scheduler; import jsr166y.forkjoin.AsyncAction; /** * Adapts Runnable instances to the Fork Join framework. * * @author Vaclav Pech * Date: Jun 16, 2009 */ final class FJRunnableTask extends AsyncAction { private final Runnable runnable; FJRunnableTask(final Runnable runnable) { this.runnable = runnable; } @SuppressWarnings({"CatchGenericClass"}) @Override protected void compute() { try { runnable.run(); finish(); } catch (Exception e) { finishExceptionally(e); } } } libgpars-groovy-java-0.10.orig/groovyx/gpars/scheduler/ResizeablePool.java0000644000000000000000000000767211347765306023745 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-9 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.scheduler; import groovyx.gpars.util.PoolUtils; import java.util.concurrent.RejectedExecutionHandler; import java.util.concurrent.SynchronousQueue; import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; /** * Represents the actors' thread pool, which performs tasks on behalf of the actors. * The actors' thread pool size defaults to the n + 1, where n is the number of processors/cores available on the machine. * The VM parameter -Dgpars.poolsize can be used the configure the default size of the actors' thread pool. * The resize() and resetDefaultSize() methods can be used to configure size of the thread pool at runtime. * * @author Vaclav Pech * Date: Feb 27, 2009 */ public final class ResizeablePool extends DefaultPool { private static final long KEEP_ALIVE_TIME = 10L; /** * Creates the pool with default number of threads. * * @param daemon Sets the daemon flag of threads in the pool. */ public ResizeablePool(final boolean daemon) { this(daemon, PoolUtils.retrieveDefaultPoolSize()); } /** * Creates the pool with specified number of threads. * * @param daemon Sets the daemon flag of threads in the pool. * @param poolSize The required size of the pool */ public ResizeablePool(final boolean daemon, final int poolSize) { super(ResizeablePool.createResizeablePool(daemon, poolSize)); } /** * Creates a fixed-thread pool of given size. Each thread will have the uncaught exception handler set * to print the unhandled exception to standard error output. * * @param daemon Sets the daemon flag of threads in the pool. * @param poolSize The required pool size @return The created thread pool * @return The newly created thread pool */ private static ThreadPoolExecutor createResizeablePool(final boolean daemon, final int poolSize) { assert poolSize > 0; return new ThreadPoolExecutor(poolSize, 1000, ResizeablePool.KEEP_ALIVE_TIME, TimeUnit.SECONDS, new SynchronousQueue(), new ThreadFactory() { public Thread newThread(final Runnable r) { final Thread thread = new Thread(r, DefaultPool.createThreadName()); thread.setDaemon(daemon); thread.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { public void uncaughtException(final Thread t, final Throwable e) { System.err.println(); e.printStackTrace(System.err); } }); return thread; } }, new RejectedExecutionHandler() { public void rejectedExecution(final Runnable r, final ThreadPoolExecutor executor) { final int currentPoolSize = executor.getPoolSize(); final int maximumPoolSize = executor.getMaximumPoolSize(); throw new IllegalStateException("The thread pool executor cannot run the task. " + "The upper limit of the thread pool size has probably been reached. " + "Current pool size: " + currentPoolSize + " Maximum pool size: " + maximumPoolSize); } }); } } libgpars-groovy-java-0.10.orig/groovyx/gpars/scheduler/ResizeableFJPool.java0000644000000000000000000000634511347765306024161 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-9 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.scheduler; import java.text.MessageFormat; /** * Represents the actors' thread pool, which performs tasks on behalf of the actors. Uses a ForkJoinPool from JSR-166y * The actors' thread pool size defaults to the n + 1, where n is the number of processors/cores available on the machine. * The VM parameter -Dgpars.poolsize can be used the configure the default size of the actors' thread pool. * The resize() and resetDefaultSize() methods can be used to configure size of the thread pool at runtime. * * @author Vaclav Pech * Date: Feb 27, 2009 */ public final class ResizeableFJPool extends FJPool { private static final int MAX_POOL_SIZE = 1000; private final Object lock = new Object(); /** * Creates the pool with default number of threads. */ public ResizeableFJPool() { } /** * Creates the pool with specified number of threads. * * @param poolSize The required size of the pool */ public ResizeableFJPool(final int poolSize) { super(poolSize); } /** * schedules a new task for processing with the pool * * @param task The task to schedule */ @Override public void execute(final Runnable task) { synchronized (lock) { final int currentPoolSize = pool.getPoolSize(); final int submissionCount = pool.getActiveSubmissionCount(); final int needForThreads = submissionCount + 1 - currentPoolSize; if (needForThreads > 0) { if (currentPoolSize + needForThreads > ResizeableFJPool.MAX_POOL_SIZE) { //noinspection AutoBoxing throw new IllegalStateException(MessageFormat.format("The thread pool executor cannot run the task. The upper limit of the thread pool size has probably been reached. Current pool size: {0} Maximum pool size: {1}", currentPoolSize, ResizeableFJPool.MAX_POOL_SIZE)); } pool.addWorkers(needForThreads); } } super.execute(new Runnable() { public void run() { task.run(); synchronized (ResizeableFJPool.this.lock) { final int currentPoolSize = pool.getPoolSize(); final int submissionCount = pool.getActiveSubmissionCount(); final int desiredPoolSize = Math.max(submissionCount, getConfiguredPoolSize()); final int change = currentPoolSize - desiredPoolSize; if (change >= 3) pool.removeWorkers(change); } } }); } } libgpars-groovy-java-0.10.orig/groovyx/gpars/util/0000755000000000000000000000000011374454000017130 5ustar libgpars-groovy-java-0.10.orig/groovyx/gpars/util/EnhancedRWLock.groovy0000644000000000000000000000376011347765306023212 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-9 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.util import java.util.concurrent.locks.ReentrantReadWriteLock /** * Extends ReentrantReadWriteLock with handy withReadLock(Closure) and withWriteLock(Closure) methods to safely lock * and unlock the lock for the passed-in closure. * Use: * def extendedLock = new ExtendedRWLock() * extendedLock.withReadLock() {* //read lock locked here *}* * @author Vaclav Pech * Date: Feb 18, 2009 */ public class EnhancedRWLock extends ReentrantReadWriteLock { def EnhancedRWLock() { super() } def EnhancedRWLock(final boolean fair) { super(fair); } /** * Performs the passed-in closure with the read lock locked and unlocks the read lock automatically * after the closure finishes. * @param cl The closure to perform with the read lock held */ public void withReadLock(Closure cl) { readLock().lock() try { cl.call() } finally { readLock().unlock() } } /** * Performs the passed-in closure with the write lock locked and unlocks the write lock automatically * after the closure finishes. * @param cl The closure to perform with the write lock held */ public void withWriteLock(Closure cl) { writeLock().lock() try { cl.call() } finally { writeLock().unlock() } } } libgpars-groovy-java-0.10.orig/groovyx/gpars/util/EnhancedSemaphore.groovy0000644000000000000000000000330511347765306023767 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-9 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.util import java.util.concurrent.Semaphore /** * Extends Semaphore with a handy withSemaphore(Closure) method to safely acquire and release the Semaphore * for the passed-in closure. * Use: * def extendedSemaphore = new ExtendedSemaphore() * extendedSemaphore.withSemaphore() {* //semaphore acquired here *}* * @author Vaclav Pech * Date: Jan 8, 2009 */ public class EnhancedSemaphore extends Semaphore { /** * Creates a new EnhancedSemaphore, delegating to the Semaphore class constructor. * @param permits Maximum number of concurrently accepted threads. */ def EnhancedSemaphore(final int permits) { super(permits); } /** * Performs the passed-in closure with the Semaphore acquired and releases the Semaphore automatically * after the closure finishes. * @param cl The closure to perform with the Semaphore acquired */ public void withSemaphore(Closure cl) { acquire() try { cl.call() } finally { release() } } } libgpars-groovy-java-0.10.orig/groovyx/gpars/util/PoolUtils.java0000644000000000000000000000307711374454000021734 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-10 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.util; import groovyx.gpars.scheduler.Pool; /** * Provides a couple of utility methods to pools and schedulers. * * @author Vaclav Pech * Date: Oct 31, 2009 */ @SuppressWarnings({"AccessOfSystemProperties", "UtilityClass"}) public final class PoolUtils { private static final String GPARS_POOLSIZE = "gpars.poolsize"; private PoolUtils() { } public static int retrieveDefaultPoolSize() { final String poolSizeValue = System.getProperty(PoolUtils.GPARS_POOLSIZE); try { return Integer.parseInt(poolSizeValue); } catch (NumberFormatException ignored) { return Runtime.getRuntime().availableProcessors() + 1; } } public static void checkValidPoolSize(final int poolSize) { if (poolSize <= 0) throw new IllegalStateException(Pool.POOL_SIZE_MUST_BE_A_POSITIVE_NUMBER); } } libgpars-groovy-java-0.10.orig/groovyx/gpars/ParallelEnhancer.groovy0000644000000000000000000000457411347765306022652 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-9 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars import groovyx.gpars.scheduler.FJPool import groovyx.gpars.scheduler.Pool /** * ParallelEnhancer allows classes or instances to be enhanced with parallel variants of iterative methods, * like eachParallel(), collectParallel(), findAllParallel() and others. These operations split processing into multiple * concurrently executable tasks and perform them on the underlying instance of the ForkJoinPool class from JSR-166y. * The pool itself is stored in a final property threadPool and can be managed through static methods * on the ParallelEnhancer class. * All enhanced classes and instances will share the underlying pool. Use the getThreadPool() method to get hold of the thread pool. * * @author Vaclav Pech * Date: Jun 15, 2009 */ public final class ParallelEnhancer { /** * Holds the internal ForkJoinPool instance wrapped into a FJPool */ private final static FJPool threadPool = new FJPool() /** * Enhances a single instance by mixing-in an instance of Parallel. */ public static Object enhanceInstance(Object collection) { //noinspection GroovyGetterCallCanBePropertyAccess collection.getMetaClass().mixin Parallel return collection } /** * Enhances a class and so all instances created in the future by mixing-in an instance of Parallel. * Enhancing classes needs to be done with caution, since it may have impact in unrelated parts of the application. */ public static void enhanceClass(Class clazz) { //noinspection GroovyGetterCallCanBePropertyAccess clazz.getMetaClass().mixin Parallel } /** * Retrieves the underlying pool */ public static Pool getThreadPool() { return threadPool } } libgpars-groovy-java-0.10.orig/groovyx/gpars/agent/0000755000000000000000000000000011374454000017251 5ustar libgpars-groovy-java-0.10.orig/groovyx/gpars/agent/Agent.groovy0000644000000000000000000002103311371776724021576 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-10 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.agent import groovyx.gpars.actor.Actors import groovyx.gpars.dataflow.DataFlowVariable import groovyx.gpars.util.EnhancedRWLock import org.codehaus.groovy.runtime.NullObject /** * A special-purpose thread-safe non-blocking reference implementation inspired by Agents in Clojure. * Agents safe-guard mutable values by allowing only a single agent-managed thread to make modifications to them. * The mutable values are not directly accessible from outside, but instead requests have to be sent to the agent * and the agent guarantees to process the requests sequentially on behalf of the callers. Agents guarantee sequential * execution of all requests and so consistency of the values. * An agent wraps a reference to mutable state, held inside a single field, and accepts code (closures / commands) * as messages, which can be sent to the Agent just like to any other actor using the '<<' operator * or any of the send() methods. * After reception of a closure / command, the closure is invoked against the internal mutable field. The closure is guaranteed * to be run without intervention from other threads and so may freely alter the internal state of the Agent * held in the internal data field. * The return value of the submitted closure is sent in reply to the sender of the closure. * If the message sent to an agent is not a closure, it is considered to be a new value for the internal * reference field. The internal reference can also be changed using the updateValue() method from within the received * closures. * The 'val' property of an agent will safely return the current value of the Agent, while the valAsync() method * will do the same without blocking the caller. * The 'instantVal' property will retrieve the current value of the Agent without having to wait in the queue of tasks. * The initial internal value can be passed to the constructor. The two-parameter constructor allows to alter the way * the internal value is returned from val/valAsync. By default the original reference is returned, but in many scenarios a copy * or a clone might be more appropriate. * * @author Vaclav Pech * Date: Jul 2, 2009 */ public class Agent extends AgentCore { /** * Allows reads not to wait in the message queue. * Writes and reads are mutually separated by using write or read locks respectively. */ private EnhancedRWLock lock = new EnhancedRWLock() /** * Holds the internal mutable state */ protected T data /** * Function converting the internal state during read to prevent internal state escape from * the protected boundary of the agent */ final Closure copy = {it} /** * Creates a new Agent with the internal state set to null */ def Agent() { this(null) } /** * Creates a new Agent around the supplied modifiable object * @param data The object to use for storing the internal state of the variable */ def Agent(final T data) { this.data = data } /** * Creates a new Agent around the supplied modifiable object * @param data The object to use for storing the internal state of the variable * @param copy A closure to use to create a copy of the internal state when sending the internal state out */ def Agent(final T data, final Closure copy) { this.data = data this.copy = copy } /** * Accepts a NullObject instance and sets the internal state to null */ final void onMessage(NullObject obj) { lock.withWriteLock { updateValue null } } /** * Accepts and invokes the closure */ final void onMessage(Closure code) { lock.withWriteLock { code.delegate = this code.call(data) } } /** * Other messages than closures are accepted as new values for the internal state */ final void onMessage(T message) { lock.withWriteLock { updateValue message } } /** * Allows closures to set the new internal state as a whole */ final void updateValue(T newValue) { data = newValue } /** * A shorthand method for safe message-based retrieval of the internal state. * Retrieves the internal state immediately by-passing the queue of tasks waiting to be processed. */ final public T getInstantVal() { T result = null lock.withReadLock { result = copy(data) } return result } /** * A shorthand method for safe message-based retrieval of the internal state. * The request to retrieve a value is put into the message queue, so will wait for all messages delivered earlier to complete. */ @SuppressWarnings("GroovyAssignabilityCheck") final public T getVal() { sendAndWait { copy it } } /** * A shorthand method for safe asynchronous message-based retrieval of the internal state. * The request to retrieve a value is put into the message queue, so will wait for all messages delivered earlier to complete. * @param callback A closure to invoke with the internal state as a parameter */ final public void valAsync(Closure callback) { send {callback.call(copy(it))} } /** * Submits the closure waiting for the result */ final def sendAndWait(Closure message) { final DataFlowVariable result = new DataFlowVariable() this.send { result.bind message.call(it) } return result.val } /** * Blocks until all messages in the queue prior to call to await() complete. * Provides a means to synchronize with the Agent */ final public void await() { sendAndWait {} } /** * Dynamically dispatches the method call */ void handleMessage(final Object message) { onMessage message } /** * Creates an agent instance initialized with the given state. * The instance will use the default thread pool. * @param state The initial internal state of the new Agent instance * @return The created instance */ public static final Agent agent(final def state) { Actors.defaultActorPGroup.agent(state) } /** * Creates an agent instance initialized with the given state. * The instance will use the default thread pool. * @param state The initial internal state of the new Agent instance * @param copy A closure to use to create a copy of the internal state when sending the internal state out * @return The created instance */ public static final Agent agent(final def state, final Closure copy) { Actors.defaultActorPGroup.agent(state, copy) } /** * Creates an agent instance initialized with the given state, which will cooperate in thread sharing with other Agent instances * in a fair manner. * The instance will use the default thread pool. * @param state The initial internal state of the new Agent instance * @return The created instance */ public static final Agent fairAgent(final def state) { Actors.defaultActorPGroup.fairAgent(state) } /** * Creates an agent instance initialized with the given state, which will cooperate in thread sharing with other Agent instances * in a fair manner. * The instance will use the default thread pool. * @param state The initial internal state of the new Agent instance * @param copy A closure to use to create a copy of the internal state when sending the internal state out * @return The created instance */ public static final Agent fairAgent(final def state, final Closure copy) { Actors.defaultActorPGroup.fairAgent(state, copy) } } libgpars-groovy-java-0.10.orig/groovyx/gpars/agent/AgentThreadFactory.java0000644000000000000000000000210711365257450023644 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-10 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.agent; import java.util.concurrent.ThreadFactory; /** * Creates daemon threads for the default agent thread pools * * @author Vaclav Pech * Date: 13.4.2010 */ final class AgentThreadFactory implements ThreadFactory { public Thread newThread(final Runnable r) { final Thread thread = new Thread(r); thread.setDaemon(true); return thread; } }libgpars-groovy-java-0.10.orig/groovyx/gpars/agent/AgentCore.java0000644000000000000000000001445611374454000021775 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-10 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.agent; import groovyx.gpars.actor.Actors; import groovyx.gpars.group.PGroup; import groovyx.gpars.scheduler.Pool; import org.codehaus.groovy.runtime.NullObject; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; /** * @author Vaclav Pech * Date: 13.4.2010 */ @SuppressWarnings({"UnqualifiedStaticUsage"}) public abstract class AgentCore implements Runnable { /** * The thread pool to use with this agent */ private volatile Pool threadPool = Actors.defaultActorPGroup.getThreadPool(); /** * Retrieves the thread pool used by the agent * * @return The thread pool */ public final Pool getThreadPool() { return threadPool; } /** * Sets a new thread pool to be used by the agent * * @param threadPool The thread pool to use */ public final void attachToThreadPool(final Pool threadPool) { this.threadPool = threadPool; } /** * Sets an actor group to use for task scheduling * * @param pGroup The pGroup to use */ public void setPGroup(final PGroup pGroup) { attachToThreadPool(pGroup.getThreadPool()); } /** * Fair agents give up the thread after processing each message, non-fair agents keep a thread until their message queue is empty. */ private volatile boolean fair = false; /** * Retrieves the agent's fairness flag * Fair agents give up the thread after processing each message, non-fair agents keep a thread until their message queue is empty. * Non-fair agents tends to perform better than fair ones. * * @return True for fair agents, false for non-fair ones. Agents are non-fair by default. */ public boolean isFair() { return fair; } /** * Makes the agent fair. Agents are non-fair by default. * Fair agents give up the thread after processing each message, non-fair agents keep a thread until their message queue is empty. * Non-fair agents tends to perform better than fair ones. */ public void makeFair() { this.fair = true; } /** * Holds agent errors */ private List errors; /** * Incoming messages */ private final Queue queue = new ConcurrentLinkedQueue(); /** * Indicates, whether there's an active thread handling a message inside the agent's body */ @SuppressWarnings({"FieldMayBeFinal"}) private volatile int active = AgentCore.PASSIVE; private static final AtomicIntegerFieldUpdater activeUpdater = AtomicIntegerFieldUpdater.newUpdater(AgentCore.class, "active"); private static final int PASSIVE = 0; private static final int ACTIVE = 1; /** * Adds the message to the agent\s message queue * * @param message A value or a closure */ public final void send(final Object message) { queue.add(message != null ? message : NullObject.getNullObject()); schedule(); } /** * Adds the message to the agent\s message queue * * @param message A value or a closure */ @SuppressWarnings({"UnusedDeclaration"}) public final void leftShift(final Object message) { send(message); } /** * Adds the message to the agent\s message queue * * @param message A value or a closure */ @SuppressWarnings({"UnusedDeclaration"}) public final void call(final Object message) { send(message); } /** * Dynamically dispatches the method call * * @param message A value or a closure */ abstract void handleMessage(final Object message); /** * Schedules processing of a next message, if there are some and if there isn't an active thread handling a message at the moment */ void schedule() { if (!queue.isEmpty() && activeUpdater.compareAndSet(this, PASSIVE, ACTIVE)) { threadPool.execute(this); } } /** * Handles a single message from the message queue */ @SuppressWarnings({"CatchGenericClass"}) public void run() { try { Object message = queue.poll(); while (message != null) { this.handleMessage(message); if (fair) break; message = queue.poll(); } } catch (Exception e) { registerError(e); } finally { activeUpdater.set(this, PASSIVE); schedule(); } } /** * Adds the exception to the list of thrown exceptions * * @param e The exception to store */ @SuppressWarnings({"MethodOnlyUsedFromInnerClass", "SynchronizedMethod"}) private synchronized void registerError(final Exception e) { if (errors == null) errors = new ArrayList(); errors.add(e); } /** * Retrieves a list of exception thrown within the agent's body. * Clears the exception history * * @return A detached collection of exception that have occurred in the agent's body */ @SuppressWarnings({"SynchronizedMethod", "ReturnOfCollectionOrArrayField"}) public synchronized List getErrors() { if (errors == null) return Collections.emptyList(); try { return errors; } finally { errors = null; } } } libgpars-groovy-java-0.10.orig/groovyx/gpars/remote/0000755000000000000000000000000011374454000017446 5ustar libgpars-groovy-java-0.10.orig/groovyx/gpars/remote/LocalHost.java0000644000000000000000000001416311347765306022224 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-9 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.remote; import groovyx.gpars.actor.Actor; import groovyx.gpars.serial.SerialContext; import groovyx.gpars.serial.SerialHandles; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.Map; import java.util.UUID; /** * Represents communication point with other local hosts. * Usually it is enough to have one LocalHost per JVM but it is possible to have several. *

* It can be one or several local nodes hosted on local host. For most applications one should be enough * but sometimes several can be useful as well. *

* Local host contains * - remote hosts connected with this one * - remote nodes known to this host * - local nodes available on this host * * @author Alex Tkachman */ public class LocalHost extends SerialHandles { /** * Registry of remote nodes known to the provider */ protected final HashMap remoteNodes = new HashMap(); /** * Hosts known to the provider */ protected final Map remoteHosts = new HashMap(); /** * Local nodes known to the provider */ protected final Map localNodes = new HashMap(); /** * Connect local node to the provider * * @param node local node */ public void connect(final LocalNode node) { synchronized (localNodes) { localNodes.put(node.getId(), node); } synchronized (remoteNodes) { for (final RemoteNode n : remoteNodes.values()) { if (!n.getId().equals(node.getId())) { node.onConnect(n); } } } synchronized (remoteHosts) { for (final RemoteHost host : remoteHosts.values()) { host.connect(node); } } } /** * Disconnect local node from the provider * * @param node local node */ public void disconnect(final LocalNode node) { synchronized (remoteHosts) { for (final RemoteHost host : remoteHosts.values()) { host.disconnect(node); } } synchronized (remoteNodes) { for (final RemoteNode n : remoteNodes.values()) { if (!n.getId().equals(node.getId())) { node.onDisconnect(n); } } } synchronized (localNodes) { localNodes.remove(node.getId()); } } public void disconnect() { synchronized (localNodes) { final ArrayList copy = new ArrayList(localNodes.values()); localNodes.clear(); for (final LocalNode localNode : copy) { disconnect(localNode); } } synchronized (remoteHosts) { final ArrayList copy = new ArrayList(remoteHosts.values()); remoteHosts.clear(); for (final RemoteHost remoteHost : copy) { remoteHost.disconnect(); } } LocalHostRegistry.removeLocalHost(this); } public SerialContext getSerialHost(final UUID hostId, final Object conn) { final RemoteConnection connection = (RemoteConnection) conn; synchronized (remoteHosts) { RemoteHost host = remoteHosts.get(hostId); if (host == null) { host = new RemoteHost(this, hostId); remoteHosts.put(hostId, host); } if (connection != null) { connection.setHost(host); host.addConnection(connection); } return host; } } public void connectRemoteNode(final UUID nodeId, final SerialContext host, final Actor mainActor) { RemoteNode node; synchronized (remoteNodes) { node = remoteNodes.get(nodeId); if (node == null) { node = new RemoteNode(nodeId, host, mainActor); remoteNodes.put(nodeId, node); } } synchronized (localNodes) { for (final LocalNode localNode : localNodes.values()) { localNode.onConnect(node); } } } public void disconnectRemoteNode(final UUID nodeId) { final RemoteNode node; synchronized (remoteNodes) { node = remoteNodes.remove(nodeId); } if (node != null) { synchronized (localNodes) { onDisconnectForLocalNodes(node); } } } public void onDisconnect(final SerialContext host) { final Collection toRemove = new ArrayList(); synchronized (remoteNodes) { for (final RemoteNode t : remoteNodes.values()) { if (t.getRemoteHost() == host) { toRemove.add(t); } } for (final RemoteNode t : toRemove) { remoteNodes.remove(t.getId()); } } synchronized (localNodes) { //todo consider moving the synchronized block inside the onDisconnectForLocalNodes() method for (final RemoteNode t : toRemove) { onDisconnectForLocalNodes(t); } } } private void onDisconnectForLocalNodes(final RemoteNode t) { for (final LocalNode localNode : localNodes.values()) { localNode.onDisconnect(t); } } } libgpars-groovy-java-0.10.orig/groovyx/gpars/remote/LocalHostRegistry.java0000644000000000000000000000346511374454000023742 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-10 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.remote; import java.util.Collections; import java.util.HashSet; import java.util.Set; /** * Registry of local hosts * * @author Alex Tkachman */ public class LocalHostRegistry { public static final Set localHosts = Collections.synchronizedSet(new HashSet()); public static synchronized void connect(final LocalNode node) { for (final LocalHost transportProvider : LocalHostRegistry.localHosts) { node.connect(transportProvider); } } public static synchronized void disconnect(final LocalNode node) { for (final LocalHost transportProvider : LocalHostRegistry.localHosts) { node.getScheduler().execute(new Runnable() { public void run() { transportProvider.disconnect(node); } }); } } public static synchronized void removeLocalHost(final LocalHost localHost) { localHosts.remove(localHost); } public static synchronized void addLocalHost(final LocalHost localHost) { localHosts.add(localHost); } } libgpars-groovy-java-0.10.orig/groovyx/gpars/remote/BroadcastDiscovery.java0000644000000000000000000001252111347765306024122 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-9 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.remote; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.net.DatagramPacket; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.MulticastSocket; import java.net.SocketAddress; import java.net.UnknownHostException; import java.util.UUID; public class BroadcastDiscovery { private static InetAddress GROUP; private static final int PORT = 4239; private static final long MAGIC = 0x23982391L; private final UUID uid; private final InetSocketAddress address; private Thread sendThread; private Thread receiveThread; private volatile boolean stopped; private MulticastSocket socket; static { try { GROUP = InetAddress.getByName("230.0.0.239"); } catch (UnknownHostException ignored) { GROUP = null; } } public BroadcastDiscovery(final UUID uid, final InetSocketAddress address) { this.uid = uid; this.address = address; } public void start() { try { socket = new MulticastSocket(PORT); final InetAddress group = GROUP; socket.joinGroup(group); final ByteArrayOutputStream out = new ByteArrayOutputStream(); final DataOutputStream stream = new DataOutputStream(out); stream.writeLong(MAGIC); stream.writeLong(uid.getMostSignificantBits()); stream.writeLong(uid.getLeastSignificantBits()); stream.writeInt(address.getPort()); final byte[] addrBytes = address.getAddress().getAddress(); stream.writeInt(addrBytes.length); stream.write(addrBytes); stream.close(); final byte[] bytes = out.toByteArray(); sendThread = new Thread() { @Override public void run() { while (!stopped) { try { Thread.sleep(1000L); } catch (InterruptedException e) { } try { final DatagramPacket packet = new DatagramPacket(bytes, bytes.length, GROUP, PORT); socket.send(packet); } catch (IOException e) { e.printStackTrace(); } } } }; sendThread.start(); receiveThread = new Thread() { @Override public void run() { final byte[] buf = new byte[3 * 8 + 3 * 4]; final byte[] addrBuf4 = new byte[4]; final byte[] addrBuf6 = new byte[6]; while (!stopped) { final DatagramPacket packet = new DatagramPacket(buf, buf.length); try { socket.receive(packet); final DataInputStream in = new DataInputStream(new ByteArrayInputStream(buf)); if (in.readLong() == MAGIC) { final UUID uuid = new UUID(in.readLong(), in.readLong()); final int port = in.readInt(); final int addrLen = in.readInt(); if (addrLen == 4) { in.read(addrBuf4); onDiscovery(uuid, new InetSocketAddress(InetAddress.getByAddress(addrBuf4), port)); } else { in.read(addrBuf6); onDiscovery(uuid, new InetSocketAddress(InetAddress.getByAddress(addrBuf6), port)); } } } catch (IOException e) { e.printStackTrace(); } } } }; receiveThread.start(); } catch (Throwable t) { t.printStackTrace(); } } public void stop() { try { stopped = true; if (sendThread != null) { sendThread.join(); } if (receiveThread != null) { receiveThread.join(); } if (socket != null) { socket.close(); } } catch (InterruptedException e) { e.printStackTrace(); } } protected void onDiscovery(final UUID uuid, final SocketAddress address) { } } libgpars-groovy-java-0.10.orig/groovyx/gpars/remote/RemoteHost.java0000644000000000000000000000614111374457552022423 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-10 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.remote; import groovyx.gpars.remote.message.NodeConnectedMsg; import groovyx.gpars.remote.message.NodeDisconnectedMsg; import groovyx.gpars.serial.SerialContext; import groovyx.gpars.serial.SerialMsg; import java.util.ArrayList; import java.util.Map; import java.util.UUID; /** * Representation of remote host connected to transport provider * * @author Alex Tkachman */ public final class RemoteHost extends SerialContext { private final ArrayList connections = new ArrayList(); public RemoteHost(final LocalHost localHost, final UUID hostId) { super(localHost, hostId); } public void addConnection(final RemoteConnection connection) { synchronized (connections) { final boolean wasConnected = isConnected(); connections.add(connection); if (wasConnected != isConnected()) { final Map localNodes = ((LocalHost) localHost).localNodes; //noinspection SynchronizationOnLocalVariableOrMethodParameter synchronized (localNodes) { for (final LocalNode localNode : localNodes.values()) { connection.write(new NodeConnectedMsg(localNode)); } } } } } public void removeConnection(final RemoteConnection connection) { synchronized (connections) { final boolean wasConnected = isConnected(); connections.remove(connection); if (wasConnected != isConnected()) { // sendLocalNodes(); } } } public void disconnect() { for (final RemoteConnection connection : connections) { connection.disconnect(); } } public boolean isConnected() { return !connections.isEmpty(); } @Override public void write(final SerialMsg msg) { msg.hostId = getLocalHost().getId(); getConnection().write(msg); } public RemoteConnection getConnection() { return connections.get(0); } public void connect(final LocalNode node) { write(new NodeConnectedMsg(node)); } public void disconnect(final LocalNode node) { write(new NodeDisconnectedMsg(node)); } public LocalHost getLocalHost() { return (LocalHost) localHost; } } libgpars-groovy-java-0.10.orig/groovyx/gpars/remote/RemoteNodeDiscoveryListener.java0000644000000000000000000000326211374454000025753 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-10 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.remote; import groovy.lang.Closure; /** * Listener for remote node events */ public class RemoteNodeDiscoveryListener { public void onConnect(final RemoteNode node) { } public void onDisconnect(final RemoteNode node) { } /** * Discovery listener backed by closure with two params * - node * - "connected" | "disconnected" * * @author Alex Tkachman */ public static class RemoteNodeDiscoveryListenerClosure extends RemoteNodeDiscoveryListener { private final Closure closure; public RemoteNodeDiscoveryListenerClosure(final Closure closure) { this.closure = (Closure) closure.clone(); } @Override public void onConnect(final RemoteNode node) { closure.call(new Object[]{node, "connected"}); } @Override public void onDisconnect(final RemoteNode node) { closure.call(new Object[]{node, "disconnected"}); } } } libgpars-groovy-java-0.10.orig/groovyx/gpars/remote/LocalNode.java0000644000000000000000000001341511365257450022167 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-9 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.remote; import groovy.lang.Closure; import groovyx.gpars.actor.Actor; import groovyx.gpars.group.DefaultPGroup; import groovyx.gpars.group.PGroup; import groovyx.gpars.scheduler.DefaultPool; import groovyx.gpars.scheduler.Pool; import groovyx.gpars.serial.SerialHandles; import java.util.Collections; import java.util.LinkedList; import java.util.List; import java.util.UUID; import java.util.concurrent.Executor; import java.util.concurrent.Executors; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; /** * Representation of local node * * @author Alex Tkachman */ public class LocalNode { private final List listeners = Collections.synchronizedList(new LinkedList()); private final ThreadPoolExecutor scheduler; private final Actor mainActor; private final UUID id = UUID.randomUUID(); private LocalHost localHost; public LocalNode() { this(null, null); } public LocalNode(final Runnable runnable) { this(null, runnable); } public LocalNode(final LocalHost provider) { this(provider, null); } public LocalNode(final LocalHost provider, final Runnable runnable) { this.scheduler = new ThreadPoolExecutor(1, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new LinkedBlockingQueue(100), new ThreadFactory() { ThreadFactory threadFactory = Executors.defaultThreadFactory(); public Thread newThread(final Runnable r) { final Thread thread = threadFactory.newThread(r); thread.setDaemon(true); thread.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { public void uncaughtException(final Thread t, final Throwable e) { System.err.println(Pool.UNCAUGHT_EXCEPTION_OCCURRED_IN_ACTOR_POOL + t.getName()); e.printStackTrace(System.err); } }); return thread; } }); final PGroup group = new DefaultPGroup(new DefaultPool(scheduler)); if (runnable != null) { if (runnable instanceof Closure) { ((Closure) runnable).setDelegate(this); ((Closure) runnable).setResolveStrategy(Closure.DELEGATE_FIRST); } mainActor = group.actor(runnable); } else { mainActor = null; } localHost = provider; if (runnable != null) { connect(provider); } } public void connect() { if (localHost != null) { connect(localHost); } else { LocalHostRegistry.connect(this); } } public void connect(final LocalHost provider) { scheduler.execute(new Runnable() { public void run() { provider.connect(LocalNode.this); } }); } public void disconnect() { if (mainActor != null && mainActor.isActive()) { mainActor.stop(); } if (localHost == null) { LocalHostRegistry.disconnect(this); } else { scheduler.execute(new Runnable() { public void run() { localHost.disconnect(LocalNode.this); } }); } } public void addDiscoveryListener(final RemoteNodeDiscoveryListener listener) { listeners.add(listener); } public void addDiscoveryListener(final Closure listener) { listeners.add(new RemoteNodeDiscoveryListener.RemoteNodeDiscoveryListenerClosure(listener)); } public void removeDiscoveryListener(final RemoteNodeDiscoveryListener listener) { listeners.remove(listener); } public void onConnect(final RemoteNode node) { for (final RemoteNodeDiscoveryListener listener : listeners) { scheduler.execute(new Runnable() { public void run() { listener.onConnect(node); } }); } } public void onDisconnect(final RemoteNode node) { for (final RemoteNodeDiscoveryListener listener : listeners) { scheduler.execute(new Runnable() { public void run() { listener.onDisconnect(node); } }); } } public Actor getMainActor() { return mainActor; } public Executor getScheduler() { return scheduler; } public UUID getId() { return id; } @Override public String toString() { return id.toString(); } public SerialHandles getLocalHost() { return localHost; } } libgpars-groovy-java-0.10.orig/groovyx/gpars/remote/RemoteConnection.java0000644000000000000000000000355111374454000023570 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-10 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.remote; import groovyx.gpars.remote.message.HostIdMsg; import groovyx.gpars.serial.SerialMsg; /** * Represents connection to remote host * * @author Alex Tkachman */ public abstract class RemoteConnection { private final LocalHost localHost; private RemoteHost host; public RemoteConnection(final LocalHost provider) { this.localHost = provider; } public void onMessage(final SerialMsg msg) { if (host == null) { final HostIdMsg idMsg = (HostIdMsg) msg; host = (RemoteHost) localHost.getSerialHost(idMsg.hostId, this); } else { throw new IllegalStateException("Unexpected message: " + msg); } } public void onException(final Throwable cause) { } public void onConnect() { write(new HostIdMsg(localHost.getId())); } public void onDisconnect() { localHost.onDisconnect(host); } public abstract void write(SerialMsg msg); public RemoteHost getHost() { return host; } public void setHost(final RemoteHost host) { this.host = host; } public abstract void disconnect(); } libgpars-groovy-java-0.10.orig/groovyx/gpars/remote/netty/0000755000000000000000000000000011354370540020615 5ustar libgpars-groovy-java-0.10.orig/groovyx/gpars/remote/netty/NettyRemoteConnection.java0000644000000000000000000000556511347765306026004 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-9 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.remote.netty; import groovyx.gpars.remote.RemoteConnection; import groovyx.gpars.serial.SerialMsg; import org.jboss.netty.channel.ChannelFuture; import org.jboss.netty.channel.ChannelFutureListener; import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicInteger; /** * Connection using Netty * * @author Alex Tkachman */ public class NettyRemoteConnection extends RemoteConnection { private final NettyHandler handler; private final MyChannelFutureListener writeListener = new MyChannelFutureListener(); public NettyRemoteConnection(final NettyTransportProvider provider, final NettyHandler netHandler) { super(provider); this.handler = netHandler; } @Override public void write(final SerialMsg msg) { if (handler.getChannel().isConnected() && handler.getChannel().isOpen()) { writeListener.incrementAndGet(); handler.getChannel().write(msg).addListener(writeListener); } } @Override public void disconnect() { writeListener.incrementAndGet(); writeListener.handler = handler; try { writeListener.operationComplete(null); } catch (Exception ignored) { } } private static class MyChannelFutureListener extends AtomicInteger implements ChannelFutureListener { private static final long serialVersionUID = -3054880716233778157L; public volatile NettyHandler handler; public void operationComplete(final ChannelFuture future) throws Exception { if (decrementAndGet() == 0 && handler != null) { final CountDownLatch cdl = new CountDownLatch(1); handler.getChannel().close().addListener(new ChannelFutureListener() { @SuppressWarnings({"AnonymousClassVariableHidesContainingMethodVariable"}) public void operationComplete(final ChannelFuture future) throws Exception { cdl.countDown(); } }); try { cdl.await(); } catch (InterruptedException e) {// e.printStackTrace(); } } } } } libgpars-groovy-java-0.10.orig/groovyx/gpars/remote/netty/RemoteObjectEncoder.java0000644000000000000000000000350711347765306025361 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-9 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.remote.netty; import groovyx.gpars.remote.RemoteConnection; import groovyx.gpars.remote.RemoteHost; import org.jboss.netty.channel.Channel; import org.jboss.netty.channel.ChannelHandlerContext; import org.jboss.netty.channel.ChannelPipelineCoverage; import org.jboss.netty.handler.codec.serialization.ObjectEncoder; @ChannelPipelineCoverage("one") public class RemoteObjectEncoder extends ObjectEncoder { private final RemoteConnection connection; /** * Creates a new encoder. * * @param connection connection handling serialization details */ public RemoteObjectEncoder(final RemoteConnection connection) { super(); this.connection = connection; } @Override protected Object encode(final ChannelHandlerContext ctx, final Channel channel, final Object msg) throws Exception { final RemoteHost remoteHost = connection.getHost(); if (remoteHost != null) { remoteHost.enter(); } try { return super.encode(ctx, channel, msg); } finally { if (remoteHost != null) { remoteHost.leave(); } } } } libgpars-groovy-java-0.10.orig/groovyx/gpars/remote/netty/RemoteObjectDecoder.java0000644000000000000000000000360111347765306025342 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-9 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.remote.netty; import groovyx.gpars.remote.RemoteConnection; import groovyx.gpars.remote.RemoteHost; import org.jboss.netty.buffer.ChannelBuffer; import org.jboss.netty.channel.Channel; import org.jboss.netty.channel.ChannelHandlerContext; import org.jboss.netty.channel.ChannelPipelineCoverage; import org.jboss.netty.handler.codec.serialization.ObjectDecoder; @ChannelPipelineCoverage("one") public class RemoteObjectDecoder extends ObjectDecoder { private final RemoteConnection connection; /** * Creates a new encoder. * * @param connection connection handling serialization details */ public RemoteObjectDecoder(final RemoteConnection connection) { super(); this.connection = connection; } @Override protected Object decode(final ChannelHandlerContext ctx, final Channel channel, final ChannelBuffer buffer) throws Exception { final RemoteHost remoteHost = connection.getHost(); if (remoteHost != null) { remoteHost.enter(); } try { return super.decode(ctx, channel, buffer); } finally { if (remoteHost != null) { remoteHost.leave(); } } } } libgpars-groovy-java-0.10.orig/groovyx/gpars/remote/netty/NettyHandler.java0000644000000000000000000000515211347765306024076 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-9 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.remote.netty; import groovyx.gpars.remote.RemoteConnection; import groovyx.gpars.serial.SerialMsg; import org.jboss.netty.channel.Channel; import org.jboss.netty.channel.ChannelHandlerContext; import org.jboss.netty.channel.ChannelPipelineCoverage; import org.jboss.netty.channel.ChannelStateEvent; import org.jboss.netty.channel.ExceptionEvent; import org.jboss.netty.channel.MessageEvent; import org.jboss.netty.channel.SimpleChannelHandler; /** * @author Alex Tkachman */ @ChannelPipelineCoverage("one") public class NettyHandler extends SimpleChannelHandler { private Channel channel; private final RemoteConnection connection; public NettyHandler(final NettyTransportProvider provider) { connection = new NettyRemoteConnection(provider, this); } @Override public void channelOpen(final ChannelHandlerContext ctx, final ChannelStateEvent e) throws Exception { channel = e.getChannel(); channel.getPipeline().addFirst("encoder", new RemoteObjectEncoder(connection)); channel.getPipeline().addFirst("decoder", new RemoteObjectDecoder(connection)); } @Override public void channelConnected(final ChannelHandlerContext ctx, final ChannelStateEvent e) throws Exception { connection.onConnect(); } @Override public void channelDisconnected(final ChannelHandlerContext ctx, final ChannelStateEvent e) throws Exception { connection.onDisconnect(); } @Override public void messageReceived(final ChannelHandlerContext ctx, final MessageEvent e) { final SerialMsg msg = (SerialMsg) e.getMessage(); msg.execute(connection); } @Override public void exceptionCaught(final ChannelHandlerContext ctx, final ExceptionEvent e) { //noinspection ThrowableResultOfMethodCallIgnored connection.onException(e.getCause()); e.getCause().printStackTrace(); } public Channel getChannel() { return channel; } } libgpars-groovy-java-0.10.orig/groovyx/gpars/remote/netty/NettyTransportProvider.java0000644000000000000000000001744211347765306026235 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-9 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.remote.netty; import groovyx.gpars.remote.BroadcastDiscovery; import groovyx.gpars.remote.LocalHost; import org.jboss.netty.bootstrap.ClientBootstrap; import org.jboss.netty.bootstrap.ServerBootstrap; import org.jboss.netty.channel.Channel; import org.jboss.netty.channel.ChannelFactory; import org.jboss.netty.channel.ChannelFuture; import org.jboss.netty.channel.ChannelFutureListener; import org.jboss.netty.channel.ChannelHandlerContext; import org.jboss.netty.channel.ChannelPipeline; import org.jboss.netty.channel.ChannelPipelineCoverage; import org.jboss.netty.channel.ChannelPipelineFactory; import org.jboss.netty.channel.ChannelStateEvent; import org.jboss.netty.channel.Channels; import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory; import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.SocketAddress; import java.net.UnknownHostException; import java.util.HashMap; import java.util.Map; import java.util.UUID; import java.util.concurrent.CountDownLatch; import java.util.concurrent.Executors; import java.util.concurrent.ThreadFactory; /** * Transport provider using Netty * * @author Alex Tkachman */ public class NettyTransportProvider extends LocalHost { private final Map clients = new HashMap(); final Server server = new Server(); final BroadcastDiscovery broadcastDiscovery; public NettyTransportProvider() { server.start(this); this.broadcastDiscovery = new BroadcastDiscovery(getId(), server.getAddress()) { @Override protected void onDiscovery(final UUID uuid, final SocketAddress address) { if (uuid.equals(getId())) { return; } synchronized (clients) { final Client client = clients.get(uuid); if (client == null) { clients.put(uuid, new Client(NettyTransportProvider.this, address, uuid)); } } } }; broadcastDiscovery.start(); } @Override public void disconnect() { broadcastDiscovery.stop(); super.disconnect(); server.stop(); for (final Client client : clients.values()) { client.stop(); } } public static class Server { private InetSocketAddress address; ChannelFactory factory; ServerBootstrap bootstrap; Channel channel; private ServerPipelineFactory pipelineFactory; public Server() { factory = new NioServerSocketChannelFactory( Executors.newCachedThreadPool(MyThreadFactory.instance), Executors.newCachedThreadPool(MyThreadFactory.instance)); bootstrap = new ServerBootstrap(factory); } public InetSocketAddress getAddress() { return address; } public void start(final NettyTransportProvider provider) { pipelineFactory = new ServerPipelineFactory(provider); bootstrap.setPipelineFactory(pipelineFactory); bootstrap.setOption("child.tcpNoDelay", true); bootstrap.setOption("child.keepAlive", true); channel = bootstrap.bind(new InetSocketAddress(0)); InetAddress inetAddress; try { inetAddress = InetAddress.getLocalHost(); } catch (UnknownHostException e) { // inetAddress = ((InetSocketAddress) channel.getLocalAddress()).getAddress(); } address = new InetSocketAddress(inetAddress, ((InetSocketAddress) channel.getLocalAddress()).getPort()); } public void stop() { final CountDownLatch latch = new CountDownLatch(1); channel.close().addListener(new ChannelFutureListener() { public void operationComplete(final ChannelFuture future) throws Exception { bootstrap.getFactory().releaseExternalResources(); latch.countDown(); } }); try { latch.await(); } catch (InterruptedException e) { e.printStackTrace(); } } } public static class Client { private final NettyTransportProvider provider; ChannelFuture channelFuture; final ChannelFactory factory; public Client(final NettyTransportProvider provider, final SocketAddress address, final UUID id) { this.provider = provider; factory = new NioClientSocketChannelFactory( Executors.newCachedThreadPool(MyThreadFactory.instance), Executors.newCachedThreadPool(MyThreadFactory.instance)); final ClientBootstrap bootstrap = new ClientBootstrap(factory); final NettyHandler handler = new ClientHandler(this.provider, id); bootstrap.getPipeline().addLast("handler", handler); bootstrap.setOption("tcpNoDelay", true); bootstrap.setOption("keepAlive", true); channelFuture = bootstrap.connect(address); } public void stop() { channelFuture.getChannel().close().addListener(new ChannelFutureListener() { public void operationComplete(final ChannelFuture future) throws Exception { factory.releaseExternalResources(); } }); } } public static class ServerPipelineFactory implements ChannelPipelineFactory { private final NettyTransportProvider provider; public ServerPipelineFactory(final NettyTransportProvider provider) { this.provider = provider; } public ChannelPipeline getPipeline() throws Exception { final ChannelPipeline pipeline = Channels.pipeline(); pipeline.addLast("handler", new NettyHandler(provider)); return pipeline; } } @ChannelPipelineCoverage("one") public static class ClientHandler extends NettyHandler { private final UUID id; private final NettyTransportProvider provider; public ClientHandler(final NettyTransportProvider provider, final UUID id) { super(provider); this.id = id; this.provider = provider; } @Override public void channelDisconnected(final ChannelHandlerContext ctx, final ChannelStateEvent e) throws Exception { provider.clients.remove(id); super.channelDisconnected(ctx, e); } } private static class MyThreadFactory implements ThreadFactory { static MyThreadFactory instance = new MyThreadFactory(); public Thread newThread(final Runnable r) { final Thread thread = new Thread(r); thread.setDaemon(true); thread.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { public void uncaughtException(final Thread t, final Throwable e) { e.printStackTrace(); } }); return thread; } } } libgpars-groovy-java-0.10.orig/groovyx/gpars/remote/message/0000755000000000000000000000000011374454000021072 5ustar libgpars-groovy-java-0.10.orig/groovyx/gpars/remote/message/HostIdMsg.java0000644000000000000000000000230111347765306023610 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-9 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.remote.message; import groovyx.gpars.serial.SerialMsg; import java.util.UUID; /** * Message sent by NetTransportProvider immediately after connection to another host is set up * * @author Alex Tkachman, Vaclav Pech */ public class HostIdMsg extends SerialMsg { private static final long serialVersionUID = -7805772642034504624L; /** * Construct message representing current state of the transport provider * @param id Local host id */ public HostIdMsg(final UUID id) { super(id); } } libgpars-groovy-java-0.10.orig/groovyx/gpars/remote/message/NodeDisconnectedMsg.java0000644000000000000000000000264511374454000025623 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-10 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.remote.message; import groovyx.gpars.remote.LocalNode; import groovyx.gpars.remote.RemoteConnection; import groovyx.gpars.serial.SerialMsg; import java.util.UUID; /** * Message sent when local node disconnected from remote host * * @author Alex Tkachman */ public class NodeDisconnectedMsg extends SerialMsg { private static final long serialVersionUID = 8082827710656359290L; /** * Id of node disconnected */ public final UUID nodeId; public NodeDisconnectedMsg(final LocalNode node) { super(); nodeId = node.getId(); } @Override public void execute(final RemoteConnection conn) { conn.getHost().getLocalHost().disconnectRemoteNode(nodeId); } } libgpars-groovy-java-0.10.orig/groovyx/gpars/remote/message/NodeConnectedMsg.java0000644000000000000000000000304211374454000025113 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-10 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.remote.message; import groovyx.gpars.actor.Actor; import groovyx.gpars.remote.LocalNode; import groovyx.gpars.remote.RemoteConnection; import groovyx.gpars.serial.SerialMsg; import java.util.UUID; /** * Message sent when local node connected to remote host * * @author Alex Tkachman */ public class NodeConnectedMsg extends SerialMsg { private static final long serialVersionUID = -2198640646677794254L; /** * Id of node connected */ public final UUID nodeId; public final Actor mainActor; public NodeConnectedMsg(final LocalNode node) { super(); nodeId = node.getId(); mainActor = node.getMainActor(); } @Override public void execute(final RemoteConnection conn) { conn.getHost().getLocalHost().connectRemoteNode(nodeId, conn.getHost(), mainActor); } } libgpars-groovy-java-0.10.orig/groovyx/gpars/remote/RemoteNode.java0000644000000000000000000000300311365257450022360 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-9 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.remote; import groovyx.gpars.actor.Actor; import groovyx.gpars.serial.SerialContext; import java.util.UUID; /** * Representation of remote node * * @author Alex Tkachman */ public final class RemoteNode { private final UUID id; private final SerialContext remoteHost; private final Actor mainActor; public RemoteNode(final UUID id, final SerialContext remoteHost, final Actor mainActor) { this.id = id; this.remoteHost = remoteHost; this.mainActor = mainActor; } public UUID getId() { return id; } @Override public String toString() { return id.toString(); } public Actor getMainActor() { return mainActor; } public SerialContext getRemoteHost() { return remoteHost; } } libgpars-groovy-java-0.10.orig/groovyx/gpars/AsyncException.java0000644000000000000000000000423211365257450021765 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-10 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars; import java.util.List; /** * This class wraps multiple exception, which occurred in concurrently run code inside one of the GParsExecutorsPoolUtil methods. * * @author Vaclav Pech * Date: Nov 17, 2008 * @see GParsExecutorsPoolUtil */ public final class AsyncException extends RuntimeException { private static final long serialVersionUID = 1573135643731810717L; private final List concurrentExceptions; @SuppressWarnings({"AssignmentToCollectionOrArrayFieldFromParameter"}) public AsyncException(final String message, final List concurrentExceptions) { super(message); this.concurrentExceptions = concurrentExceptions; } public List getConcurrentExceptions() { return concurrentExceptions; } @Override public String getMessage() { return super.getMessage() + ' ' + buildMessage(); } @Override public String toString() { return buildMessage(); } @SuppressWarnings({"StringBufferWithoutInitialCapacity"}) private String buildMessage() { final StringBuilder sb = new StringBuilder(); sb.append("AsyncException"); sb.append("{concurrentExceptions=").append("[\n"); for (final Throwable concurrentException : concurrentExceptions) { sb.append(concurrentException.toString()).append('\n'); } sb.append("]}"); return sb.toString(); } } libgpars-groovy-java-0.10.orig/groovyx/gpars/GParsExecutorsPoolEnhancer.groovy0000644000000000000000000002442411365257450024656 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-10 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars import groovyx.gpars.scheduler.DefaultPool import groovyx.gpars.scheduler.Pool /** * GParsExecutorsPoolEnhancer allows classes or instances to be enhanced with asynchronous variants of iterative methods, * like eachParallel(), collectParallel(), findAllParallel() and others. These operations split processing into multiple * concurrently executable tasks and perform them on the underlying instance of an ExecutorService. * The pool itself is stored in a final property threadPool and can be managed through static methods * on the GParsExecutorsPoolEnhancer class. * All enhanced classes and instances will share the underlying pool. * * @author Vaclav Pech * Date: Jun 15, 2009 */ public final class GParsExecutorsPoolEnhancer { /** * Holds the internal ExecutorService instance wrapped into a DefaultPool */ @SuppressWarnings("GroovyConstantNamingConvention") private final static DefaultPool threadPool = new DefaultPool(true) /** * Enhances a single instance by mixing-in an instance of GParsExecutorsPoolEnhancer. */ public static void enhanceInstance(Object collection) { //noinspection GroovyGetterCallCanBePropertyAccess collection.getMetaClass().mixin GParsExecutorsPoolEnhancer } /** * Enhances a class and so all instances created in the future by mixing-in an instance of GParsExecutorsPoolEnhancer. * Enhancing classes needs to be done with caution, since it may have impact in unrelated parts of the application. */ public static void enhanceClass(Class clazz) { //noinspection GroovyGetterCallCanBePropertyAccess clazz.getMetaClass().mixin GParsExecutorsPoolEnhancer } /** * Retrieves the underlying pool */ public Pool getThreadPool() { return threadPool } /** * Iterates over a collection/object with the each() method using an asynchronous variant of the supplied closure * to evaluate each collection's element. A CountDownLatch is used to make the calling thread wait for all the results. * After this method returns, all the closures have been finished and all the potential shared resources have been updated * by the threads. * It's important to protect any shared resources used by the supplied closure from race conditions caused by multi-threaded access. * @throws AsyncException If any of the collection's elements causes the closure to throw an exception. The original exceptions will be stored in the AsyncException's concurrentExceptions field. */ public def eachParallel(Closure cl) { groovyx.gpars.GParsExecutorsPool.withExistingPool(threadPool.executorService) { GParsExecutorsPoolUtil.eachParallel(mixedIn[Object], cl) } } /** * Iterates over a collection/object with the eachWithIndex() method using an asynchronous variant of the supplied closure * to evaluate each collection's element. A CountDownLatch is used to make the calling thread wait for all the results. * After this method returns, all the closures have been finished and all the potential shared resources have been updated * by the threads. * It's important to protect any shared resources used by the supplied closure from race conditions caused by multi-threaded access. * @throws AsyncException If any of the collection's elements causes the closure to throw an exception. The original exceptions will be stored in the AsyncException's concurrentExceptions field. */ public def eachWithIndexParallel(Closure cl) { groovyx.gpars.GParsExecutorsPool.withExistingPool(threadPool.executorService) { GParsExecutorsPoolUtil.eachWithIndexParallel(mixedIn[Object], cl) } } /** * Iterates over a collection/object with the collect() method using an asynchronous variant of the supplied closure * to evaluate each collection's element. * After this method returns, all the closures have been finished and the caller can safely use the result. * It's important to protect any shared resources used by the supplied closure from race conditions caused by multi-threaded access. * @throws AsyncException If any of the collection's elements causes the closure to throw an exception. The original exceptions will be stored in the AsyncException's concurrentExceptions field. */ public def collectParallel(Closure cl) { groovyx.gpars.GParsExecutorsPool.withExistingPool(threadPool.executorService) { GParsExecutorsPoolUtil.collectParallel(mixedIn[Object], cl) } } /** * Performs the findAll() operation using an asynchronous variant of the supplied closure * to evaluate each collection's/object's element. * After this method returns, all the closures have been finished and the caller can safely use the result. * It's important to protect any shared resources used by the supplied closure from race conditions caused by multi-threaded access. * @throws AsyncException If any of the collection's elements causes the closure to throw an exception. The original exceptions will be stored in the AsyncException's concurrentExceptions field. */ public def findAllParallel(Closure cl) { groovyx.gpars.GParsExecutorsPool.withExistingPool(threadPool.executorService) { GParsExecutorsPoolUtil.findAllParallel(mixedIn[Object], cl) } } /** * Performs the grep()() operation using an asynchronous variant of the supplied closure * to evaluate each collection's/object's element. * After this method returns, all the closures have been finished and the caller can safely use the result. * It's important to protect any shared resources used by the supplied closure from race conditions caused by multi-threaded access. * @throws AsyncException If any of the collection's elements causes the closure to throw an exception. The original exceptions will be stored in the AsyncException's concurrentExceptions field. */ public def grepParallel(Closure cl) { groovyx.gpars.GParsExecutorsPool.withExistingPool(threadPool.executorService) { GParsExecutorsPoolUtil.grepParallel(mixedIn[Object], cl) } } /** * Performs the find() operation using an asynchronous variant of the supplied closure * to evaluate each collection's/object's element. * After this method returns, all the closures have been finished and the caller can safely use the result. * It's important to protect any shared resources used by the supplied closure from race conditions caused by multi-threaded access. * @throws AsyncException If any of the collection's elements causes the closure to throw an exception. The original exceptions will be stored in the AsyncException's concurrentExceptions field. */ public def findParallel(Closure cl) { groovyx.gpars.GParsExecutorsPool.withExistingPool(threadPool.executorService) { GParsExecutorsPoolUtil.findParallel(mixedIn[Object], cl) } } /** * Performs the all() operation using an asynchronous variant of the supplied closure * to evaluate each collection's/object's element. * After this method returns, all the closures have been finished and the caller can safely use the result. * It's important to protect any shared resources used by the supplied closure from race conditions caused by multi-threaded access. * @throws AsyncException If any of the collection's elements causes the closure to throw an exception. The original exceptions will be stored in the AsyncException's concurrentExceptions field. */ public boolean everyParallel(Closure cl) { groovyx.gpars.GParsExecutorsPool.withExistingPool(threadPool.executorService) { GParsExecutorsPoolUtil.everyParallel(mixedIn[Object], cl) } } /** * Performs the any() operation using an asynchronous variant of the supplied closure * to evaluate each collection's/object's element. * After this method returns, all the closures have been finished and the caller can safely use the result. * It's important to protect any shared resources used by the supplied closure from race conditions caused by multi-threaded access. * @throws AsyncException If any of the collection's elements causes the closure to throw an exception. The original exceptions will be stored in the AsyncException's concurrentExceptions field. */ public boolean anyParallel(Closure cl) { groovyx.gpars.GParsExecutorsPool.withExistingPool(threadPool.executorService) { GParsExecutorsPoolUtil.anyParallel(mixedIn[Object], cl) } } /** * Performs the groupBy() operation using an asynchronous variant of the supplied closure * to evaluate each collection's/object's element. * After this method returns, all the closures have been finished and the caller can safely use the result. * It's important to protect any shared resources used by the supplied closure from race conditions caused by multi-threaded access. * @throws AsyncException If any of the collection's elements causes the closure to throw an exception. The original exceptions will be stored in the AsyncException's concurrentExceptions field. */ public def groupByParallel(Closure cl) { groovyx.gpars.GParsExecutorsPool.withExistingPool(threadPool.executorService) { GParsExecutorsPoolUtil.groupByParallel(mixedIn[Object], cl) } } } libgpars-groovy-java-0.10.orig/groovyx/gpars/actor/0000755000000000000000000000000011374454000017263 5ustar libgpars-groovy-java-0.10.orig/groovyx/gpars/actor/ActorMessage.java0000644000000000000000000000454711370236514022521 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-9 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.actor; import groovyx.gpars.actor.impl.MessageStream; import java.io.Serializable; /** * An internal representation of received messages holding both the original message plus the sender actor reference. * This class is not intended to be use directly by users. * * @author Vaclav Pech, Alex Tkachman * Date: Feb 27, 2009 */ public class ActorMessage implements Serializable { private static final long serialVersionUID = -2925547808451571430L; private Object payLoad; private MessageStream sender; //todo what are the values after deserialization? /** * Creates a new instance * * @param payLoad The original message * @param sender The sending actor, null, if the message was not sent by an actor */ public ActorMessage(final Object payLoad, final MessageStream sender) { this.payLoad = payLoad; this.sender = sender; } /** * Constructor for serialization */ protected ActorMessage() { // } public Object getPayLoad() { return payLoad; } public MessageStream getSender() { return sender; } /** * Factory method to create instances of ActorMessage with given payload. * The sender of the ActorMessage is retrieved from the ReplyRegistry. * * @param payLoad The original message * @return The newly created message */ public static ActorMessage build(final T payLoad) { return new ActorMessage(payLoad, Actor.threadBoundActor()); } @Override public String toString() { return "Message from " + sender + ": " + payLoad; } } libgpars-groovy-java-0.10.orig/groovyx/gpars/actor/DynamicDispatchActor.groovy0000644000000000000000000000526211374457570024613 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-10 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.actor import org.codehaus.groovy.runtime.DefaultGroovyMethods import org.codehaus.groovy.runtime.NullObject /** * A pooled actor allowing for an alternative structure of the message handling code. * In general DynamicDispatchActor repeatedly scans for messages and dispatches arrived messages to one * of the onMessage(message) methods defined on the actor. *

 * final class MyActor extends DynamicDispatchActor {*      void onMessage(String message) {*          println 'Received string'
 *}*      void onMessage(Integer message) {*          println 'Received integer'
 *}*      void onMessage(Object message) {*          println 'Received object'
 *}*      void onMessage(NullObject nullMessage) {*          println 'Received null'
 *}*} 
* * Method when {...} provides an alternative way to define message handlers * * @author Vaclav Pech, Alex Tkachman, Dierk Koenig * Date: Jun 26, 2009 */ @SuppressWarnings("GroovyAssignmentToMethodParameter") public class DynamicDispatchActor extends AbstractPooledActor { /** * Creates a new instance without any when handlers registered */ DynamicDispatchActor() { this(null) } /** * Creates an instance, processing all when{} calls in the supplied closure * @param closure A closure to run against te actor, typically to register handlers */ DynamicDispatchActor(Closure closure) { if (closure) { Closure cloned = (Closure) closure.clone() cloned.resolveStrategy = Closure.DELEGATE_FIRST cloned.delegate = this cloned.call() } } /** * Loops reading messages using the react() method and dispatches to the corresponding onMessage() method. */ final void act() { loop { react {msg -> if (msg == null) msg = NullObject.nullObject onMessage msg } } } void when(Closure closure) { DefaultGroovyMethods.getMetaClass(this).onMessage closure } } libgpars-groovy-java-0.10.orig/groovyx/gpars/actor/Actor.java0000644000000000000000000002253111374454000021201 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-10 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.actor; import groovy.time.BaseDuration; import groovyx.gpars.actor.impl.MessageStream; import groovyx.gpars.actor.impl.ReceivingMessageStream; import groovyx.gpars.dataflow.DataFlowExpression; import groovyx.gpars.dataflow.DataFlowVariable; import groovyx.gpars.remote.RemoteConnection; import groovyx.gpars.remote.RemoteHost; import groovyx.gpars.serial.DefaultRemoteHandle; import groovyx.gpars.serial.RemoteHandle; import groovyx.gpars.serial.RemoteSerialized; import groovyx.gpars.serial.SerialContext; import groovyx.gpars.serial.SerialHandle; import groovyx.gpars.serial.SerialMsg; import groovyx.gpars.serial.WithSerialId; import java.lang.reflect.InvocationTargetException; import java.util.concurrent.TimeUnit; /** * Actors are active objects, which borrow a thread from a thread pool. * The Actor interface provides means to send messages to the actor, start and stop the background thread as well as * check its status. * * @author Vaclav Pech, Alex Tkachman */ public abstract class Actor extends ReceivingMessageStream { /** * Maps each thread to the actor it currently processes. * Used in the send() method to remember the sender of each message for potential replies */ private static final ThreadLocal currentActorPerThread = new ThreadLocal(); private final DataFlowExpression joinLatch; protected Actor() { this(new DataFlowVariable()); } /** * Constructor to be used by deserialization * * @param joinLatch The instance of DataFlowExpression to use for join operation */ protected Actor(final DataFlowExpression joinLatch) { this.joinLatch = joinLatch; } /** * Starts the Actor. No messages can be sent or received before an Actor is started. * * @return same actor */ public abstract Actor start(); /** * Send message to stop to the Actor. All messages already in queue will be processed first. * No new messages will be accepted since that point. * Has no effect if the Actor is not started. * * @return same actor */ public abstract Actor stop(); /** * Terminates the Actor. Unprocessed messages will be passed to the afterStop method, if exists. * No new messages will be accepted since that point. * Has no effect if the Actor is not started. * * @return same actor */ public abstract Actor terminate(); /** * Checks the current status of the Actor. * * @return current status of the Actor. */ public abstract boolean isActive(); /** * Checks whether the current thread is the actor's worker thread. * * @return whether the current thread is the actor's worker thread */ public abstract boolean isActorThread(); /** * Joins the actor. Waits for its termination. * * @throws InterruptedException when interrupted while waiting */ public final void join() throws InterruptedException { joinLatch.getVal(); } /** * Notify listener when finished * * @param listener listener to notify * @throws InterruptedException if interrupted while waiting */ public final void join(final MessageStream listener) throws InterruptedException { joinLatch.getValAsync(listener); } /** * Joins the actor. Waits for its termination. * * @param timeout timeout * @param unit units of timeout * @throws InterruptedException if interrupted while waiting */ public final void join(final long timeout, final TimeUnit unit) throws InterruptedException { if (timeout > 0L) { joinLatch.getVal(timeout, unit); } else { joinLatch.getVal(); } } /** * Joins the actor. Waits for its termination. * * @param duration timeout to wait * @throws InterruptedException if interrupted while waiting */ public final void join(final BaseDuration duration) throws InterruptedException { join(duration.toMilliseconds(), TimeUnit.MILLISECONDS); } /** * Join-point for this actor * * @return The DataFlowExpression instance, which is used to join this actor */ public DataFlowExpression getJoinLatch() { return joinLatch; } /** * Registers the actor with the current thread * * @param currentActor The actor to register */ protected static void registerCurrentActorWithThread(final Actor currentActor) { Actor.currentActorPerThread.set(currentActor); } /** * Deregisters the actor registered from the thread */ protected static void deregisterCurrentActorWithThread() { Actor.currentActorPerThread.set(null); } /** * Retrieves the actor registered with the current thread * * @return The associated actor */ public static Actor threadBoundActor() { return Actor.currentActorPerThread.get(); } @Override protected RemoteHandle createRemoteHandle(final SerialHandle handle, final SerialContext host) { return new MyRemoteHandle(handle, host, joinLatch); } public static class MyRemoteHandle extends DefaultRemoteHandle { private final DataFlowExpression joinLatch; private static final long serialVersionUID = 3721849638877039035L; public MyRemoteHandle(final SerialHandle handle, final SerialContext host, final DataFlowExpression joinLatch) { super(handle.getSerialId(), host.getHostId(), RemoteActor.class); this.joinLatch = joinLatch; } @Override protected WithSerialId createObject(final SerialContext context) throws InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException { return new RemoteActor(context, joinLatch); } } public static class RemoteActor extends Actor implements RemoteSerialized { private final RemoteHost remoteHost; private static final long serialVersionUID = -1375776678860848278L; public RemoteActor(final SerialContext host, final DataFlowExpression jointLatch) { super(jointLatch); remoteHost = (RemoteHost) host; } @Override public Actor start() { throw new UnsupportedOperationException(); } @Override public Actor stop() { remoteHost.write(new StopActorMsg(this)); return this; } @Override public Actor terminate() { remoteHost.write(new TerminateActorMsg(this)); return this; } @Override public boolean isActive() { throw new UnsupportedOperationException(); } @Override public boolean isActorThread() { return false; } @SuppressWarnings({"AssignmentToMethodParameter"}) @Override public MessageStream send(Object message) { if (!(message instanceof ActorMessage)) { message = new ActorMessage(message, Actor.threadBoundActor()); } remoteHost.write(new SendTo(this, (ActorMessage) message)); return this; } @Override protected Object receiveImpl() throws InterruptedException { throw new UnsupportedOperationException(); } @Override protected Object receiveImpl(final long timeout, final TimeUnit units) throws InterruptedException { throw new UnsupportedOperationException(); } public static class StopActorMsg extends SerialMsg { private final Actor actor; private static final long serialVersionUID = -927785591952534581L; public StopActorMsg(final RemoteActor remoteActor) { actor = remoteActor; } @Override public void execute(final RemoteConnection conn) { actor.stop(); } } public static class TerminateActorMsg extends SerialMsg { private final Actor actor; private static final long serialVersionUID = -839334644951906974L; public TerminateActorMsg(final RemoteActor remoteActor) { actor = remoteActor; } @Override public void execute(final RemoteConnection conn) { actor.terminate(); } } } } libgpars-groovy-java-0.10.orig/groovyx/gpars/actor/Actors.groovy0000644000000000000000000000615211365257450022003 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-9 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.actor import groovyx.gpars.scheduler.ResizeablePool import groovyx.gpars.group.DefaultPGroup /** * Provides handy helper methods to create pooled actors and customize the underlying thread pool. * Use static import to be able to call Actors methods without the need to prepend them with the Actors identifier. *
 * import static org.gpars.actor.Actors.*
 *
 * Actors.defaultActorPGroup.resize 1
 *
 * def actor = actor {*     react {message ->
 *         println message
 *}*     //this line will never be reached
 *}.start()
 *
 * actor.send 'Hi!'
 * 
* * All actors created through the Actors class will belong to the same default actor group and run * on daemon threads. * The DefaultPGroup class should be used when actors need to be grouped into multiple groups or when non-daemon * threads are to be used. * @author Vaclav Pech, Alex Tkachman * Date: Feb 18, 2009 */ public abstract class Actors { /** * The default actor group to share by all actors created through the Actors class. */ public final static DefaultPGroup defaultActorPGroup = new DefaultPGroup(new ResizeablePool(true)) /** * Creates a new instance of PooledActor, using the passed-in closure as the body of the actor's act() method. * The created actor will be part of the default actor group. * @param handler The body of the newly created actor's act method. * @return A newly created instance of the AbstractPooledActor class */ public static AbstractPooledActor actor(Runnable handler) { return defaultActorPGroup.actor(handler) } /** * Creates a reactor around the supplied code. * When a reactor receives a message, the supplied block of code is run with the message * as a parameter and the result of the code is send in reply. * The created actor will be part of the default actor group. * @param The code to invoke for each received message * @return A new instance of ReactiveEventBasedThread */ public static AbstractPooledActor reactor(final Closure code) { return defaultActorPGroup.reactor(code) } /** * Creates an instance of DynamicDispatchActor. * @param code The closure specifying individual message handlers. */ public static AbstractPooledActor messageHandler(final Closure code) { return defaultActorPGroup.messageHandler(code) } } libgpars-groovy-java-0.10.orig/groovyx/gpars/actor/ReactiveActor.groovy0000644000000000000000000000276611347765306023316 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-9 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.actor import groovyx.gpars.actor.impl.RunnableBackedPooledActor /** * An actor representing a reactor. When it receives a message, the supplied block of code is run with the message * as a parameter and the result of the code is send in reply. * *
 * final def doubler = reactor {message ->
 *     2 * message
 *}*
 * def result = doubler.sendAndWait(10)
 *
 * 
* * @author Vaclav Pech, Alex Tkachman * Date: Jun 26, 2009 */ public class ReactiveActor extends RunnableBackedPooledActor { ReactiveActor(Closure body) { setAction { def cloned = body.clone() cloned.delegate = this cloned.resolveStrategy = Closure.DELEGATE_FIRST loop { react { it.replyIfExists cloned(it) } } } } } libgpars-groovy-java-0.10.orig/groovyx/gpars/actor/DefaultPooledActor.groovy0000644000000000000000000000175311347765306024276 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-10 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.actor /** * Default non-abstract AbstractPooledActor subclass for use in e.g. mixins. * * @author Vaclav Pech * Date: Feb 27, 2009 */ public class DefaultPooledActor extends AbstractPooledActor { protected void act() { throw new UnsupportedOperationException('The act method has not been specified.') } } libgpars-groovy-java-0.10.orig/groovyx/gpars/actor/impl/0000755000000000000000000000000011374454000020224 5ustar libgpars-groovy-java-0.10.orig/groovyx/gpars/actor/impl/MessageStream.java0000644000000000000000000002476011374454000023640 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-10 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.actor.impl; import groovy.lang.Closure; import groovy.time.Duration; import groovyx.gpars.actor.Actor; import groovyx.gpars.actor.ActorMessage; import groovyx.gpars.dataflow.DataCallback; import groovyx.gpars.remote.RemoteConnection; import groovyx.gpars.remote.RemoteHost; import groovyx.gpars.serial.RemoteSerialized; import groovyx.gpars.serial.SerialMsg; import groovyx.gpars.serial.WithSerialId; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.LockSupport; /** * Stream of abstract messages * * @author Alex Tkachman, Vaclav Pech, Dierk Koenig */ public abstract class MessageStream extends WithSerialId { /** * Send message to stream and return immediately * * @param message message to send * @return always return message stream itself */ public abstract MessageStream send(Object message); /** * Convenience method for send(new Object()). * * @return always return message stream itself */ public MessageStream send() { return send(new Object()); } /** * Send message to stream and return immediately. Allows to specify an arbitrary actor to send replies to. * By default replies are sent to the originator (sender) of each message, however, when a different actor * is specified as the optional second argument to the send() method, this supplied actor will receive the replies instead. * * @param message message to send * @param replyTo where to send reply * @param type of message accepted by the stream * @return always return message stream itself */ public final MessageStream send(final T message, final MessageStream replyTo) { return send(new ActorMessage(message, replyTo)); } /** * Same as send * * @param message to send * @return original stream */ public final MessageStream leftShift(final T message) { return send(message); } /** * Same as send * * @param message to send * @return original stream */ public final MessageStream call(final T message) { return send(message); } /** * Sends a message and waits for a reply. * Returns the reply or throws an IllegalStateException, if the target actor cannot reply. * * @param message message to send * @return The message that came in reply to the original send. * @throws InterruptedException if interrupted while waiting */ public final V sendAndWait(final T message) throws InterruptedException { final ResultWaiter to = new ResultWaiter(); send(new ActorMessage(message, to)); return to.getResult(); } /** * Sends a message and execute continuation when reply became available. * * @param message message to send * @param closure closure to execute when reply became available * @return The message that came in reply to the original send. * @throws InterruptedException if interrupted while waiting */ @SuppressWarnings({"AssignmentToMethodParameter"}) public final MessageStream sendAndContinue(final T message, Closure closure) throws InterruptedException { closure = (Closure) closure.clone(); closure.setDelegate(this); closure.setResolveStrategy(Closure.DELEGATE_FIRST); return send(message, new DataCallback(closure)); } /** * Sends a message and waits for a reply. Timeouts after the specified timeout. In case of timeout returns null. * Returns the reply or throws an IllegalStateException, if the target actor cannot reply. * * @param message message to send * @param timeout timeout * @param units units * @return The message that came in reply to the original send. * @throws InterruptedException if interrupted while waiting */ public final Object sendAndWait(final T message, final long timeout, final TimeUnit units) throws InterruptedException { final ResultWaiter to = new ResultWaiter(); send(new ActorMessage(message, to)); return to.getResult(timeout, units); } /** * Sends a message and waits for a reply. Timeouts after the specified timeout. In case of timeout returns null. * Returns the reply or throws an IllegalStateException, if the target actor cannot reply. * * @param message message to send * @param duration timeout * @return The message that came in reply to the original send. * @throws InterruptedException if interrupted while waiting */ public final Object sendAndWait(final T message, final Duration duration) throws InterruptedException { return sendAndWait(message, duration.toMilliseconds(), TimeUnit.MILLISECONDS); } @Override public Class getRemoteClass() { return RemoteMessageStream.class; } static void reInterrupt() throws InterruptedException { if (Thread.currentThread().isInterrupted()) { throw new InterruptedException(); } } /** * Represents a pending request for a reply from an actor. * * @param The type of expected reply message */ private static class ResultWaiter extends MessageStream { private static final long serialVersionUID = 6512046150496489148L; /** * Holds a reference to the calling thread, while waiting, and the received reply message, once it has arrived. */ private volatile Object value; private volatile boolean isSet; private ResultWaiter() { value = Thread.currentThread(); } /** * Accepts the message as a reply and wakes up the sleeping thread. * * @param message message to send * @return this */ @Override public MessageStream send(final Object message) { final Thread thread = (Thread) this.value; if (message instanceof ActorMessage) { this.value = ((ActorMessage) message).getPayLoad(); } else { this.value = message; } isSet = true; LockSupport.unpark(thread); return this; } /** * Retrieves the response blocking until a message arrives * * @return The received message * @throws InterruptedException If the thread gets interrupted */ public V getResult() throws InterruptedException { while (!isSet) { LockSupport.park(); final Thread thread = Thread.currentThread(); if (thread.isInterrupted()) { throw new InterruptedException(); } } rethrowException(); return (V) value; } /** * Retrieves the response blocking until a message arrives * * @param timeout How long to wait * @param units Unit for the timeout * @return The received message * @throws InterruptedException If the thread gets interrupted */ public Object getResult(final long timeout, final TimeUnit units) throws InterruptedException { final long endNano = System.nanoTime() + units.toNanos(timeout); while (!isSet) { final long toWait = endNano - System.nanoTime(); if (toWait <= 0L) { return null; } LockSupport.parkNanos(toWait); MessageStream.reInterrupt(); } rethrowException(); return value; } private void rethrowException() { if (value instanceof Throwable) { if (value instanceof RuntimeException) { throw (RuntimeException) value; } else { throw new RuntimeException((Throwable) value); } } } /** * Handle cases when the message sent to the actor doesn't get delivered */ public void onDeliveryError() { send(new IllegalStateException("Delivery error. Maybe target actor is not active")); } } public static class RemoteMessageStream extends MessageStream implements RemoteSerialized { private static final long serialVersionUID = 3936054469565089659L; private final RemoteHost remoteHost; public RemoteMessageStream(final RemoteHost host) { remoteHost = host; } @SuppressWarnings({"AssignmentToMethodParameter"}) @Override public MessageStream send(Object message) { if (!(message instanceof ActorMessage)) { message = new ActorMessage(message, Actor.threadBoundActor()); } remoteHost.write(new SendTo(this, (ActorMessage) message)); return this; } } public static class SendTo extends SerialMsg { private static final long serialVersionUID = 1989120447646342520L; private final MessageStream to; private final ActorMessage message; public SendTo(final MessageStream to, final ActorMessage message) { super(); this.to = to; this.message = message; } public MessageStream getTo() { return to; } public ActorMessage getMessage() { return message; } @Override public void execute(final RemoteConnection conn) { to.send(message); } } } libgpars-groovy-java-0.10.orig/groovyx/gpars/actor/impl/ActorContinuationException.java0000644000000000000000000000215711347765306026434 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-9 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.actor.impl; /** * An exception indicating end of a work chunk (ActorAction) allowing other ActorAction to get scheduled. * Implementing singleton pattern, ActorException holds the unique reference. * * @author Vaclav Pech * Date: Feb 17, 2009 */ public final class ActorContinuationException extends ActorException { private static final long serialVersionUID = -4978264308794524512L; ActorContinuationException() { } } libgpars-groovy-java-0.10.orig/groovyx/gpars/actor/impl/ActorTimeoutException.java0000644000000000000000000000205111347765306025401 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-9 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.actor.impl; /** * An exception indicating Actor react timeout. * Implementing singleton pattern, ActorException holds the unique reference. * * @author Vaclav Pech * Date: Feb 17, 2009 */ public final class ActorTimeoutException extends ActorException { private static final long serialVersionUID = 240177592831181888L; ActorTimeoutException() { } } libgpars-groovy-java-0.10.orig/groovyx/gpars/actor/impl/ActorTerminationException.java0000644000000000000000000000207111347765306026246 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-9 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.actor.impl; /** * An exception indicating Actor termination request. * Implementing singleton pattern, ActorException holds the unique reference. * * @author Vaclav Pech * Date: Feb 17, 2009 */ public final class ActorTerminationException extends ActorException { private static final long serialVersionUID = -1525695043073635315L; ActorTerminationException() { } } libgpars-groovy-java-0.10.orig/groovyx/gpars/actor/impl/ActorStopException.java0000644000000000000000000000205011347765306024677 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-9 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.actor.impl; /** * An exception indicating Actor stopping request. * Implementing singleton pattern, ActorException holds the unique reference. * * @author Alex Tkachman * Date: Feb 17, 2009 */ public final class ActorStopException extends ActorException { private static final long serialVersionUID = 6718779462386378739L; ActorStopException() { } }libgpars-groovy-java-0.10.orig/groovyx/gpars/actor/impl/RunnableBackedPooledActor.java0000644000000000000000000000754611354636736026117 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-9 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.actor.impl; import groovy.lang.Closure; import groovy.lang.GroovyObjectSupport; import groovy.lang.MissingMethodException; import groovy.lang.MissingPropertyException; import groovyx.gpars.actor.AbstractPooledActor; import org.codehaus.groovy.runtime.GroovyCategorySupport; import org.codehaus.groovy.runtime.InvokerHelper; import java.util.Arrays; /** * Utility class to implement AbstractPooledActor backed by any Runnable (including Closure) * * @author Alex Tkachman, Vaclav Pech */ public class RunnableBackedPooledActor extends AbstractPooledActor { private static final long serialVersionUID = 8992135845484038961L; private Runnable action; public RunnableBackedPooledActor() { } public RunnableBackedPooledActor(final Runnable handler) { setAction(handler); } final void setAction(final Runnable handler) { if (handler == null) { action = null; } else { if (handler instanceof Closure) { final Closure cloned = (Closure) ((Closure) handler).clone(); if (cloned.getOwner() == cloned.getDelegate()) { // otherwise someone else already took care for setting delegate for the closure cloned.setDelegate(this); cloned.setResolveStrategy(Closure.DELEGATE_FIRST); } else { cloned.setDelegate(new RunnableBackedPooledActorDelegate(cloned.getDelegate(), this)); } action = cloned; } else { action = handler; } } } @Override protected void act() { if (action != null) { if (action instanceof Closure) { GroovyCategorySupport.use(Arrays.asList(ReplyCategory.class), (Closure) action); } else { action.run(); } } } private static final class RunnableBackedPooledActorDelegate extends GroovyObjectSupport { private final Object first; private final Object second; RunnableBackedPooledActorDelegate(final Object first, final Object second) { this.first = first; this.second = second; } @Override public Object invokeMethod(final String name, final Object args) { try { return InvokerHelper.invokeMethod(first, name, args); } catch (MissingMethodException mme) { return InvokerHelper.invokeMethod(second, name, args); } } @Override public Object getProperty(final String propertyName) { try { return InvokerHelper.getProperty(first, propertyName); } catch (MissingPropertyException mpe) { return InvokerHelper.getProperty(second, propertyName); } } @Override public void setProperty(final String propertyName, final Object newValue) { try { InvokerHelper.setProperty(first, propertyName, newValue); } catch (MissingPropertyException mpe) { InvokerHelper.setProperty(second, propertyName, newValue); } } } } libgpars-groovy-java-0.10.orig/groovyx/gpars/actor/impl/ActorException.java0000644000000000000000000000320111347765306024030 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-9 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.actor.impl; /** * Pooled actors need to simulate continuations to create stacktrace-less chunks of work (ActorActions) to assign * to the threads from the pool. To achieve this ActorActions throw exceptions to terminate the current chuck of work * and allow another chunk of work on the same actor to begin. * ActorAction is a parent to these exception. It also holds initialized instances of each of the concrete subclasses * to avoid need for exception object creation each time. * * @author Vaclav Pech, Alex Tkachman * Date: Feb 17, 2009 */ public abstract class ActorException extends RuntimeException { public static final ActorException CONTINUE = new ActorContinuationException(); public static final ActorException TERMINATE = new ActorTerminationException(); public static final ActorException STOP = new ActorStopException(); public static final ActorException TIMEOUT = new ActorTimeoutException(); ActorException() { } } libgpars-groovy-java-0.10.orig/groovyx/gpars/actor/impl/ActorReplyException.java0000644000000000000000000000345611347765306025060 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-9 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.actor.impl; import java.util.Collections; import java.util.List; /** * Indicates problems sending replies to actors. Holds a list of exceptions that occurred during reply dispatch. * * @author Vaclav Pech * Date: Jun 11, 2009 */ public final class ActorReplyException extends RuntimeException { private static final long serialVersionUID = -3877063222143535104L; private final List issues; public ActorReplyException(final String message) { super(message); this.issues = Collections.emptyList(); } public ActorReplyException(final String message, final List issues) { super(message); this.issues = Collections.unmodifiableList(issues); } @SuppressWarnings({"ReturnOfCollectionOrArrayField"}) public List getIssues() { return issues; } @Override public String toString() { return super.toString() + issues; } @SuppressWarnings({"CallToPrintStackTrace"}) @Override public void printStackTrace() { super.printStackTrace(); for (final Exception e : issues) e.printStackTrace(); } } libgpars-groovy-java-0.10.orig/groovyx/gpars/actor/impl/SequentialProcessingActor.java0000644000000000000000000007574611374454000026252 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-10 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.actor.impl; import groovy.lang.Closure; import groovy.lang.GroovyRuntimeException; import groovy.time.Duration; import groovyx.gpars.actor.Actor; import groovyx.gpars.actor.ActorMessage; import groovyx.gpars.actor.Actors; import groovyx.gpars.group.PGroup; import org.codehaus.groovy.runtime.CurriedClosure; import org.codehaus.groovy.runtime.GeneratedClosure; import org.codehaus.groovy.runtime.GroovyCategorySupport; import org.codehaus.groovy.runtime.InvokerHelper; import org.codehaus.groovy.runtime.ScriptBytecodeAdapter; import java.util.Arrays; import java.util.List; import java.util.Timer; import java.util.TimerTask; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; import java.util.concurrent.locks.LockSupport; import static groovyx.gpars.actor.impl.ActorException.CONTINUE; import static groovyx.gpars.actor.impl.ActorException.STOP; import static groovyx.gpars.actor.impl.ActorException.TERMINATE; import static groovyx.gpars.actor.impl.ActorException.TIMEOUT; /** * @author Alex Tkachman, Vaclav Pech */ @SuppressWarnings({"UnqualifiedStaticUsage"}) public abstract class SequentialProcessingActor extends Actor implements Runnable { /** * The actor group to which the actor belongs */ protected volatile PGroup actorGroup; /** * Code for the loop, if any */ protected Runnable loopCode; /** * Code for the next action */ private volatile Reaction reaction; /** * Stored incoming messages. The most recently received message is in the head of the list. */ private volatile Node inputQueue; /** * Stores messages ready for processing by the actor. The oldest message is in the head of the list. * Messages are transferred from the inputQueue into the output queue in the transferQueues() method. */ private Node outputQueue; private final AtomicBoolean ongoingThreadTermination = new AtomicBoolean(false); /** * Counter of messages in the queues */ private volatile int count; private static final AtomicReferenceFieldUpdater inputQueueUpdater = AtomicReferenceFieldUpdater.newUpdater(SequentialProcessingActor.class, Node.class, "inputQueue"); private static final AtomicIntegerFieldUpdater countUpdater = AtomicIntegerFieldUpdater.newUpdater(SequentialProcessingActor.class, "count"); private volatile Thread waitingThread; private volatile Thread currentThread; private static final ActorMessage startMessage = new ActorMessage("startMessage", null); private static final ActorMessage stopMessage = new ActorMessage("stopMessage", null); private static final ActorMessage loopMessage = new ActorMessage("loopMessage", null); private static final ActorMessage terminateMessage = new ActorMessage("terminateMessage", null); protected static final int S_ACTIVE_MASK = 1; protected static final int S_FINISHING_MASK = 2; protected static final int S_FINISHED_MASK = 4; protected static final int S_STOP_TERMINATE_MASK = 8; protected static final int S_NOT_STARTED = 0; protected static final int S_RUNNING = S_ACTIVE_MASK; protected static final int S_STOPPING = S_STOP_TERMINATE_MASK | S_FINISHING_MASK | S_ACTIVE_MASK; protected static final int S_TERMINATING = S_FINISHING_MASK | S_ACTIVE_MASK; protected static final int S_STOPPED = S_STOP_TERMINATE_MASK | S_FINISHED_MASK; protected static final int S_TERMINATED = S_FINISHED_MASK; /** * Indicates whether the actor should terminate */ protected volatile int stopFlag = S_NOT_STARTED; protected static final AtomicIntegerFieldUpdater stopFlagUpdater = AtomicIntegerFieldUpdater.newUpdater(SequentialProcessingActor.class, "stopFlag"); /** * Timer holding timeouts for react methods */ private static final Timer timer = new Timer(true); /** * Checks whether the current thread is the actor's current thread. */ @Override public final boolean isActorThread() { return Thread.currentThread() == currentThread; } /** * Checks the current status of the Actor. */ @Override public final boolean isActive() { return (stopFlag & S_ACTIVE_MASK) != 0; } /** * Retrieves the next message from the queue * * @return The message */ private ActorMessage getMessage() { assert isActorThread(); transferQueues(); final ActorMessage toProcess = outputQueue.msg; outputQueue = outputQueue.next; throwIfNeeded(toProcess); return toProcess; } /** * Checks the supplied message and throws either STOP or TERMINATE, if the message is a Stop or Terminate message respectively. * * @param toProcess The next message to process by the actors */ private void throwIfNeeded(final ActorMessage toProcess) { if (toProcess == stopMessage) { stopFlag = S_STOPPING; throw STOP; } if (toProcess == terminateMessage) { stopFlag = S_TERMINATING; throw TERMINATE; } } /** * Polls a message from the queues * * @return The message */ protected final ActorMessage pollMessage() { assert isActorThread(); transferQueues(); ActorMessage toProcess = null; if (outputQueue != null) { toProcess = outputQueue.msg; outputQueue = outputQueue.next; } return toProcess; } /** * Takes a message from the queues. Blocks until a message is available. * * @return The message * @throws InterruptedException If the thread gets interrupted. */ protected final ActorMessage takeMessage() throws InterruptedException { assert isActorThread(); while (true) { final ActorMessage message = awaitNextMessage(0L); if (message != null) return message; } } /** * Takes a message from the queues. Blocks until a message is available. * * @param timeout Max time to wait for a message * @param timeUnit The units for the timeout * @return The message * @throws InterruptedException If the thread gets interrupted. */ protected ActorMessage takeMessage(final long timeout, final TimeUnit timeUnit) throws InterruptedException { assert isActorThread(); final long endTime = System.nanoTime() + timeUnit.toNanos(timeout); do { final ActorMessage message = awaitNextMessage(endTime); if (message != null) return message; } while (System.nanoTime() < endTime); return null; } /** * Holds common functionality for takeMessage() methods. * * @param endTime End of the timeout, 0 if no timeout was set * @return The next message * @throws InterruptedException If the thread has been interrupted */ private ActorMessage awaitNextMessage(final long endTime) throws InterruptedException { transferQueues(); waitingThread = Thread.currentThread(); if (outputQueue != null) return retrieveNextMessage(); if (endTime == 0L) LockSupport.park(); else LockSupport.parkNanos(endTime - System.nanoTime()); MessageStream.reInterrupt(); return null; } /** * Takes the next message from the outputQueue, decrements the counter and possibly throws control exceptions * * @return The next message */ private ActorMessage retrieveNextMessage() { final ActorMessage toProcess = outputQueue.msg; outputQueue = outputQueue.next; // we are in actor thread, so counter >= 1 // as we found message it is >= 2 // so we have to decrement countUpdater.decrementAndGet(this); throwIfNeeded(toProcess); return toProcess; } /** * Transfers messages from the input queue into the output queue, reverting the order of the elements. */ private void transferQueues() { if (outputQueue == null) { Node node = inputQueueUpdater.getAndSet(this, null); while (node != null) { final Node next = node.next; node.next = outputQueue; outputQueue = node; node = next; } } } /** * Creates a new instance, sets the default actor group. */ protected SequentialProcessingActor() { setActorGroup(Actors.defaultActorPGroup); } /** * Sets the actor's group. * It can only be invoked before the actor is started. * * @param group new group */ public final void setActorGroup(final PGroup group) { if (group == null) { throw new IllegalArgumentException("Cannot set actor's group to null."); } if (stopFlag != S_NOT_STARTED) { throw new IllegalStateException("Cannot reset actor's group after it was started."); } actorGroup = group; } /** * Retrieves the group to which the actor belongs * * @return The actor's group */ public PGroup getActorGroup() { return actorGroup; } @Override public final MessageStream send(final Object message) { if (stopFlag != S_RUNNING) { //noinspection ObjectEquality if (message != terminateMessage && message != stopMessage) throw new IllegalStateException("The actor cannot accept messages at this point."); } final ActorMessage actorMessage; if (message instanceof ActorMessage) { actorMessage = (ActorMessage) message; } else { actorMessage = ActorMessage.build(message); } final Node toAdd = new Node(actorMessage); while (true) { final Node prev = inputQueue; toAdd.next = prev; if (inputQueueUpdater.compareAndSet(this, prev, toAdd)) { final int cnt = countUpdater.getAndIncrement(this); if (cnt == 0) { if (stopFlag != S_STOPPED && stopFlag != S_TERMINATED) schedule(); } else { final Thread w = waitingThread; if (w != null) { waitingThread = null; LockSupport.unpark(w); } } break; } } return this; } /** * Schedules the current actor for processing on the actor group's thread pool. */ private void schedule() { actorGroup.getThreadPool().execute(this); } protected void scheduleLoop() { if (stopFlag == S_TERMINATING) throw TERMINATE; transferQueues(); if (outputQueue != null) { if (outputQueue.msg == stopMessage) { throw STOP; } } countUpdater.getAndIncrement(this); final Node node = new Node(loopMessage); node.next = outputQueue; outputQueue = node; throw CONTINUE; } private void handleStart() { doOnStart(); } /** * Allows subclasses to add behavior to run after actor's start */ protected abstract void doOnStart(); private void handleTimeout() { doOnTimeout(); } /** * Allows subclasses to add behavior to run after actor's timeout */ protected abstract void doOnTimeout(); private void handleTermination() { if (stopFlag == S_STOPPING) stopFlag = S_STOPPED; else if (stopFlag == S_TERMINATING) stopFlag = S_TERMINATED; else //noinspection ArithmeticOnVolatileField throw new IllegalStateException("Messed up actors state detected when terminating: " + stopFlag); try { doOnTermination(); } finally { getJoinLatch().bind(null); } } /** * Allows subclasses to add behavior to run after actor's termination */ protected abstract void doOnTermination(); private void handleException(final Throwable exception) { doOnException(exception); } /** * Allows subclasses to add behavior to run after exception in actor's body * * @param exception The exception that was fired */ protected abstract void doOnException(final Throwable exception); private void handleInterrupt(final InterruptedException exception) { Thread.interrupted(); doOnInterrupt(exception); } /** * Allows subclasses to add behavior to run after actor's interruption * * @param exception The InterruptedException */ protected void doOnInterrupt(final InterruptedException exception) { } /** * Starts the Actor. No messages can be send or received before an Actor is started. * * @return this (the actor itself) to allow method chaining */ @Override public final SequentialProcessingActor start() { if (!stopFlagUpdater.compareAndSet(this, S_NOT_STARTED, S_RUNNING)) { throw new IllegalStateException("Actor has already been started."); } send(startMessage); return this; } /** * Send message to stop to the actor. * All messages in queue will be processed before stopped but no new messages will be accepted * after that point * * @return this (the actor itself) to allow method chaining */ @Override public final Actor stop() { if (stopFlagUpdater.compareAndSet(this, S_RUNNING, S_STOPPING)) { send(stopMessage); } return this; } /** * Terminate the Actor. The background thread will be interrupted, unprocessed messages will be passed to the afterStop * method, if exists. * Has no effect if the Actor is not started. * * @return this (the actor itself) to allow method chaining */ @Override public final Actor terminate() { while (true) { final int flag = stopFlag; if ((flag & S_FINISHED_MASK) != 0 || flag == S_TERMINATING) break; if (stopFlagUpdater.compareAndSet(this, flag, S_TERMINATING)) { if (isActorThread()) { throw TERMINATE; } try { while (!ongoingThreadTermination.compareAndSet(false, true)) //noinspection CallToThreadYield Thread.yield(); if (currentThread != null) { currentThread.interrupt(); } else { // just to make sure that scheduled try { send(terminateMessage); } catch (IllegalStateException ignore) { } } } finally { ongoingThreadTermination.set(false); } break; } } return this; } /** * Schedules an ActorAction to take the next message off the message queue and to pass it on to the supplied closure. * The method never returns, but instead frees the processing thread back to the thread pool. * * @param duration Time to wait at most for a message to arrive. The actor terminates if a message doesn't arrive within the given timeout. * The TimeCategory DSL to specify timeouts must be enabled explicitly inside the Actor's act() method. * @param code The code to handle the next message. The reply() and replyIfExists() methods are available inside * the closure to send a reply back to the actor, which sent the original message. */ protected final void react(final Duration duration, final Closure code) { react(duration.toMilliseconds(), code); } /** * Schedules an ActorAction to take the next message off the message queue and to pass it on to the supplied closure. * The method never returns, but instead frees the processing thread back to the thread pool. * * @param code The code to handle the next message. The reply() and replyIfExists() methods are available inside * the closure to send a reply back to the actor, which sent the original message. */ protected final void react(final Closure code) { react(-1L, code); } /** * Schedules an ActorAction to take the next message off the message queue and to pass it on to the supplied closure. * The method never returns, but instead frees the processing thread back to the thread pool. * * @param timeout Time in milliseconds to wait at most for a message to arrive. The actor terminates if a message doesn't arrive within the given timeout. * @param timeUnit a TimeUnit determining how to interpret the timeout parameter * @param code The code to handle the next message. The reply() and replyIfExists() methods are available inside * the closure to send a reply back to the actor, which sent the original message. */ protected final void react(final long timeout, final TimeUnit timeUnit, final Closure code) { react(timeUnit.toMillis(timeout), code); } /** * Schedules an ActorAction to take the next message off the message queue and to pass it on to the supplied closure. * The method never returns, but instead frees the processing thread back to the thread pool. * Also adds reply() and replyIfExists() methods to the currentActor and the message. * These methods will call send() on the target actor (the sender of the original message). * The reply()/replyIfExists() methods invoked on the actor will be sent to all currently processed messages, * reply()/replyIfExists() invoked on a message will send a reply to the sender of that particular message only. * * @param timeout Time in milliseconds to wait at most for a message to arrive. The actor terminates if a message doesn't arrive within the given timeout. * @param code The code to handle the next message. The reply() and replyIfExists() methods are available inside * the closure to send a reply back to the actor, which sent the original message. */ protected final void react(final long timeout, final Closure code) { if (!isActorThread()) { throw new IllegalStateException("Cannot call react from thread which is not owned by the actor"); } getSenders().clear(); final int maxNumberOfParameters = code.getMaximumNumberOfParameters(); code.setResolveStrategy(Closure.DELEGATE_FIRST); code.setDelegate(this); if (maxNumberOfParameters > 1) { throw new IllegalArgumentException("Actor cannot process a multi-argument closures passed to react()."); // this.react(timeout, new MultiMessageReaction(code, maxNumberOfParameters, timeout, new ArrayList())); } else { assert reaction == null; assert maxNumberOfParameters <= 1; final Reaction reactCode = new Reaction(this, maxNumberOfParameters == 1, code); if (timeout >= 0L) { reactCode.setTimeout(timeout); } reaction = reactCode; throw CONTINUE; } } /** * Enables multiple argument closures to be passed to react(). * The MultiMessageReaction class takes just one argument and will wrap the intended closure. * After invoking the MultiMessageReaction will curry the obtained value onto the wrapped multi-argument closure. * The whole process of wrapping a multi-argument closure with MultiMessageReaction class instances is repeated until all arguments * are curried. At that moment the original closure, now worth all arguments curried, gets invoked. * * @author Vaclav Pech */ private final class MultiMessageReaction extends Closure implements GeneratedClosure { private static final long serialVersionUID = -4047888721838663324L; private final Closure code; private final int maxNumberOfParameters; private final long timeout; private final List localSenders; private MultiMessageReaction(final Closure code, final int maxNumberOfParameters, final long timeout, final List localSenders) { super(code.getThisObject()); this.code = code; this.maxNumberOfParameters = maxNumberOfParameters; this.timeout = timeout; this.localSenders = localSenders; } @Override public int getMaximumNumberOfParameters() { return 1; } @Override public Class[] getParameterTypes() { return new Class[]{Object.class}; } public Object doCall(final Object args) { localSenders.add((MessageStream) InvokerHelper.invokeMethod(args, "getSender", null)); final int newNumberOfParameters = maxNumberOfParameters - 1; if (newNumberOfParameters <= 0) { SequentialProcessingActor.this.getSenders().clear(); SequentialProcessingActor.this.getSenders().addAll(localSenders); InvokerHelper.invokeClosure(code.curry(new Object[]{args}), null); } else SequentialProcessingActor.this.react(timeout, new MultiMessageReaction(code.curry(new Object[]{args}), newNumberOfParameters, timeout, localSenders)); return null; } } /** * Represents an element in the message queue. Holds an ActorMessage and a reference to the next element in the queue. * The reference is null for the last element in the queue. */ private static class Node { volatile Node next; final ActorMessage msg; Node(final ActorMessage actorMessage) { this.msg = actorMessage; } } @SuppressWarnings({"ThrowCaughtLocally"}) public void run() { boolean shouldTerminate = false; //noinspection OverlyBroadCatchBlock try { assert currentThread == null; registerCurrentActorWithThread(this); currentThread = Thread.currentThread(); try { if (stopFlag == S_TERMINATING) { throw TERMINATE; } final ActorMessage toProcess = getMessage(); if (toProcess == startMessage) { handleStart(); // if we came here it means no loop was started stopFlag = S_STOPPING; throw STOP; } if (toProcess == loopMessage) { loopCode.run(); throw new IllegalStateException("Should not reach here"); } if (reaction != null) { reaction.offer(toProcess); throw CONTINUE; } throw new IllegalStateException("Unexpected message " + toProcess); } catch (GroovyRuntimeException gre) { throw ScriptBytecodeAdapter.unwrap(gre); } } catch (ActorContinuationException continuation) { if (Thread.currentThread().isInterrupted()) { shouldTerminate = true; assert stopFlag != S_STOPPED; assert stopFlag != S_TERMINATED; stopFlag = S_TERMINATING; //noinspection ThrowableInstanceNeverThrown handleInterrupt(new InterruptedException("Interruption of the actor thread detected.")); } } catch (ActorTerminationException termination) { shouldTerminate = true; } catch (ActorStopException termination) { assert stopFlag != S_STOPPED; assert stopFlag != S_TERMINATED; shouldTerminate = true; } catch (ActorTimeoutException timeout) { shouldTerminate = true; assert stopFlag != S_STOPPED; assert stopFlag != S_TERMINATED; stopFlag = S_TERMINATING; handleTimeout(); } catch (InterruptedException e) { shouldTerminate = true; assert stopFlag != S_STOPPED; assert stopFlag != S_TERMINATED; stopFlag = S_TERMINATING; handleInterrupt(e); } catch (Throwable e) { shouldTerminate = true; assert stopFlag != S_STOPPED; assert stopFlag != S_TERMINATED; stopFlag = S_TERMINATING; handleException(e); } finally { try { while (!ongoingThreadTermination.compareAndSet(false, true)) //noinspection CallToThreadYield Thread.yield(); Thread.interrupted(); if (shouldTerminate) handleTermination(); } finally { deregisterCurrentActorWithThread(); currentThread = null; ongoingThreadTermination.set(false); final int cnt = countUpdater.decrementAndGet(this); if (cnt > 0 && isActive()) { schedule(); } } } } /** * Ensures that the supplied closure will be invoked repeatedly in a loop. * The method never returns, but instead frees the processing thread back to the thread pool. * * @param code The closure to invoke repeatedly */ protected final void loop(final Runnable code) { if (loopCode != null) { throw new IllegalStateException("The loop method must be only called once"); } if (code instanceof Closure) { ((Closure) code).setResolveStrategy(Closure.DELEGATE_FIRST); ((Closure) code).setDelegate(this); } loopCode = new Runnable() { public void run() { getSenders().clear(); obj2Sender.clear(); if (code instanceof Closure) //noinspection deprecation { GroovyCategorySupport.use(Arrays.asList(ReplyCategory.class), (Closure) code); } else { code.run(); } doLoopCall(); } }; loopCode.run(); } private void doLoopCall() { checkStopTerminate(); if (loopCode != null) { scheduleLoop(); } else { // case of react called directly from act () stopFlag = S_STOPPING; throw STOP; } } protected final void checkStopTerminate() { if (stopFlag != S_RUNNING) { if (stopFlag == S_TERMINATING) throw TERMINATE; if (stopFlag != S_STOPPING) throw new IllegalStateException("Should not reach here"); } } void runReaction(final ActorMessage message, final Closure code) { assert message != null; if (message.getPayLoad() == TIMEOUT) throw TIMEOUT; getSenders().add(message.getSender()); obj2Sender.put(message.getPayLoad(), message.getSender()); //noinspection deprecation GroovyCategorySupport.use(Arrays.asList(ReplyCategory.class), code); doLoopCall(); } /** * Buffers messages for the next continuation of an event-driven actor, handles timeouts and no-param continuations. * * @author Vaclav Pech, Alex Tkachman * Date: May 22, 2009 */ @SuppressWarnings({"InstanceVariableOfConcreteClass"}) private static final class Reaction { private final boolean codeNeedsArgument; private final AtomicBoolean isReady = new AtomicBoolean(false); private final Closure code; private final SequentialProcessingActor actor; /** * Creates a new instance. * * @param actor actor * @param codeNeedsArgument Indicates, whether the provided code expects an argument * @param code code to execute */ Reaction(final SequentialProcessingActor actor, final boolean codeNeedsArgument, final Closure code) { this.actor = actor; this.code = code; this.codeNeedsArgument = codeNeedsArgument; } /** * Indicates whether a message or a timeout has arrived. * * @return True, if the next continuation can start. */ @SuppressWarnings({"BooleanMethodIsAlwaysInverted"}) public boolean isReady() { return isReady.get(); } public void offer(final ActorMessage actorMessage) { final boolean readyFlag = isReady.getAndSet(true); assert !readyFlag; actor.reaction = null; if (codeNeedsArgument) { actor.runReaction(actorMessage, new CurriedClosure(code, new Object[]{actorMessage.getPayLoad()})); } else { actor.runReaction(actorMessage, code); } } public void setTimeout(final long timeout) { timer.schedule(new TimerTask() { @Override public void run() { if (!isReady()) { actor.send(new ActorMessage(TIMEOUT, null)); } } }, timeout); } } } libgpars-groovy-java-0.10.orig/groovyx/gpars/actor/impl/ReceivingMessageStream.java0000644000000000000000000002324611374454000025472 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-10 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.actor.impl; import groovy.lang.Closure; import groovy.time.BaseDuration; import groovyx.gpars.actor.Actor; import groovyx.gpars.actor.ActorMessage; import java.text.MessageFormat; import java.util.ArrayList; import java.util.List; import java.util.WeakHashMap; import java.util.concurrent.TimeUnit; /** * @author Alex Tkachman, Vaclav Pech */ @SuppressWarnings({"ThrowableInstanceNeverThrown"}) public abstract class ReceivingMessageStream extends MessageStream { /** * A list of senders for the currently processed messages */ private final List senders = new ArrayList(); protected final WeakHashMap obj2Sender = new WeakHashMap(); @SuppressWarnings({"ReturnOfCollectionOrArrayField"}) protected final List getSenders() { return senders; } /** * Sends a reply to all currently processed messages. Throws ActorReplyException if some messages * have not been sent by an actor. For such cases use replyIfExists(). * Calling reply()/replyIfExist() on the actor with disabled replying (through the disableSendingReplies() method) * will result in IllegalStateException being thrown. * Sending replies is enabled by default. * * @param message reply message * @throws groovyx.gpars.actor.impl.ActorReplyException * If some of the replies failed to be sent. */ protected final void reply(final Object message) { assert senders != null; if (senders.isEmpty()) { throw new ActorReplyException("Cannot send replies. The list of recipients is empty."); } else { final List exceptions = new ArrayList(); for (final MessageStream sender : senders) { if (sender != null) { try { sender.send(message); } catch (IllegalStateException e) { exceptions.add(e); } } else { exceptions.add(new IllegalArgumentException(String.format("Cannot send a reply message %s to a null recipient.", message))); } } if (!exceptions.isEmpty()) { throw new ActorReplyException("Failed sending some replies. See the issues field for details", exceptions); } } } /** * Sends a reply to all currently processed messages, which have been sent by an actor. * Ignores potential errors when sending the replies, like no sender or sender already stopped. * Calling reply()/replyIfExist() on the actor with disabled replying (through the disableSendingReplies() method) * will result in IllegalStateException being thrown. * Sending replies is enabled by default. * * @param message reply message */ protected final void replyIfExists(final Object message) { assert senders != null; for (final MessageStream sender : senders) { try { if (sender != null) { sender.send(message); } } catch (IllegalStateException ignore) { } } } /** * Retrieves a message from the message queue, waiting, if necessary, for a message to arrive. * * @return The message retrieved from the queue, or null, if the timeout expires. * @throws InterruptedException If the thread is interrupted during the wait. Should propagate up to stop the thread. */ protected abstract Object receiveImpl() throws InterruptedException; /** * Retrieves a message from the message queue, waiting, if necessary, for a message to arrive. * * @param timeout how long to wait before giving up, in units of unit * @param units a TimeUnit determining how to interpret the timeout parameter * @return The message retrieved from the queue, or null, if the timeout expires. * @throws InterruptedException If the thread is interrupted during the wait. Should propagate up to stop the thread. */ protected abstract Object receiveImpl(final long timeout, final TimeUnit units) throws InterruptedException; /** * Retrieves a message from the message queue, waiting, if necessary, for a message to arrive. * * @return The message retrieved from the queue, or null, if the timeout expires. * @throws InterruptedException If the thread is interrupted during the wait. Should propagate up to stop the thread. */ protected final Object receive() throws InterruptedException { final Object msg = receiveImpl(); return ReceivingMessageStream.unwrapMessage(msg); } /** * Retrieves a message from the message queue, waiting, if necessary, for a message to arrive. * * @param timeout how long to wait before giving up, in units of unit * @param units a TimeUnit determining how to interpret the timeout parameter * @return The message retrieved from the queue, or null, if the timeout expires. * @throws InterruptedException If the thread is interrupted during the wait. Should propagate up to stop the thread. */ protected final Object receive(final long timeout, final TimeUnit units) throws InterruptedException { final Object msg = receiveImpl(timeout, units); return ReceivingMessageStream.unwrapMessage(msg); } private static Object unwrapMessage(final Object msg) { //more a double-check here, since all current implementations of the receiveImpl() method do unwrap already if (msg instanceof ActorMessage) { return ((ActorMessage) msg).getPayLoad(); } else { return msg; } } /** * Retrieves a message from the message queue, waiting, if necessary, for a message to arrive. * * @param duration how long to wait before giving up, in units of unit * @return The message retrieved from the queue, or null, if the timeout expires. * @throws InterruptedException If the thread is interrupted during the wait. Should propagate up to stop the thread. */ protected final Object receive(final BaseDuration duration) throws InterruptedException { return receive(duration.toMilliseconds(), TimeUnit.MILLISECONDS); } /** * Enhances objects with the ability to send replies and detect message originators. */ public static final class ReplyCategory { private ReplyCategory() { } /** * Retrieves the originator of a message * * @param original The message to detect the originator of * @return The message originator */ public static MessageStream getSender(final Object original) { final ReceivingMessageStream actor = Actor.threadBoundActor(); if (actor == null) { throw new IllegalStateException("message originator detection in a non-actor"); } return actor.obj2Sender.get(original); } public static void reply(final Object original, final Object reply) { if (original instanceof ReceivingMessageStream) { ((ReceivingMessageStream) original).reply(reply); return; } if (original instanceof Closure) { ((ReceivingMessageStream) ((Closure) original).getDelegate()).reply(reply); return; } final ReceivingMessageStream actor = Actor.threadBoundActor(); if (actor == null) { throw new IllegalStateException("reply from non-actor"); } final MessageStream sender = actor.obj2Sender.get(original); if (sender == null) { throw new IllegalStateException(MessageFormat.format("Cannot send a reply message {0} to a null recipient.", original.toString())); } sender.send(reply); } public static void replyIfExists(final Object original, final Object reply) { if (original instanceof ReceivingMessageStream) { ((ReceivingMessageStream) original).replyIfExists(reply); return; } if (original instanceof Closure) { ((ReceivingMessageStream) ((Closure) original).getDelegate()).replyIfExists(reply); return; } final ReceivingMessageStream actor = Actor.threadBoundActor(); if (actor != null) { final MessageStream sender = actor.obj2Sender.get(original); if (sender != null) { try { sender.send(reply); } catch (IllegalStateException ignored) { } } } } } } libgpars-groovy-java-0.10.orig/groovyx/gpars/actor/AbstractPooledActor.java0000644000000000000000000004437011365257450024047 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-9 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars.actor; import groovy.lang.Closure; import groovy.lang.MetaClass; import groovy.lang.MetaMethod; import groovy.time.Duration; import groovyx.gpars.actor.impl.MessageStream; import groovyx.gpars.actor.impl.SequentialProcessingActor; import org.codehaus.groovy.runtime.InvokerHelper; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.List; import java.util.concurrent.TimeUnit; /** * AbstractPooledActor provides the default Actor implementation. It represents a standalone active object (actor), * which reacts asynchronously to messages sent to it from outside through the send() method. * Each Actor has its own message queue and a thread pool shared with other Actors by means of an instance * of the PGroup, which they have in common. * The PGroup instance is responsible for the pool creation, management and shutdown. * All work performed by an Actor is divided into chunks, which are sequentially submitted as independent tasks * to the thread pool for processing. * Whenever an Actor looks for a new message through the react() method, the actor gets detached * from the thread, making the thread available for other actors. Thanks to the ability to dynamically attach and detach * threads to actors, Actors can scale far beyond the limits of the underlying platform on number of concurrently * available threads. * The receive() method can be used to read a message from the queue without giving up the thread. If no message is available, * the call to receive() blocks until a message arrives or the supplied timeout expires. * The loop() method allows to repeatedly invoke a closure and yet perform each of the iterations sequentially * in different thread from the thread pool. * To support continuations correctly the react() and loop() methods never return. *
 * import static groovyx.gpars.actor.Actors.actor
 * 

* def actor = actor { * loop { * react {message -> * println message * } * //this line will never be reached * } * //this line will never be reached * }.start() *

* actor.send 'Hi!' *

* This requires the code to be structured accordingly. *

*

 * def adder = actor {
 *     loop {
 *         react {a ->
 *             react {b ->
 *                 println a+b
 *                 replyIfExists a+b  //sends reply, if b was sent by a PooledActor
 *             }
 *         }
 *         //this line will never be reached
 *     }
 *     //this line will never be reached
 * }.start()
 * 
* The react method can accept multiple messages in the passed-in closure *
 * react {Integer a, String b ->
 *     ...
 * }
 * 
* The closures passed to the react() method can call reply() or replyIfExists(), which will send a message back to * the originator of the currently processed message. The replyIfExists() method unlike the reply() method will not fail * if the original message wasn't sent by an actor nor if the original sender actor is no longer running. * The reply() and replyIfExists() methods are also dynamically added to the processed messages. *
 * react {a ->
 *     react {b ->
 *         reply 'message'  //sent to senders of a as well as b
 *         a.reply 'private message'  //sent to the sender of a only
 *     }
 * }
 * 
*

* The react() method accepts timeout specified using the TimeCategory DSL. *

 * react(10.MINUTES) {
 *     println 'Received message: ' + it
 * }
 * 
* If no message arrives within the given timeout, the onTimeout() lifecycle handler is invoked, if exists, * and the actor terminates. * Each Actor has at any point in time at most one active instance of ActorAction associated, which abstracts * the current chunk of actor's work to perform. Once a thread is assigned to the ActorAction, it moves the actor forward * till loop() or react() is called. These methods schedule another ActorAction for processing and throw dedicated exception * to terminate the current ActorAction. *

* Each Actor can define lifecycle observing methods, which will be called by the Actor's background thread whenever a certain lifecycle event occurs. *

    *
  • afterStart() - called immediately after the Actor's background thread has been started, before the act() method is called the first time.
  • *
  • afterStop(List undeliveredMessages) - called right after the actor is stopped, passing in all the messages from the queue.
  • *
  • onInterrupt(InterruptedException e) - called when a react() method timeouts. The actor will be terminated. *
  • onTimeout() - called when the actor's thread gets interrupted. Thread interruption will result in the stopping the actor in any case.
  • *
  • onException(Throwable e) - called when an exception occurs in the actor's thread. Throwing an exception from this method will stop the actor.
  • *
* * @author Vaclav Pech, Alex Tkachman, Dierk Koenig * Date: Feb 7, 2009 */ @SuppressWarnings({"ThrowCaughtLocally", "UnqualifiedStaticUsage"}) public abstract class AbstractPooledActor extends SequentialProcessingActor { private volatile Closure onStop = null; private static final String THE_ACTOR_HAS_NOT_BEEN_STARTED = "The actor hasn't been started."; private static final String THE_ACTOR_HAS_BEEN_STOPPED = "The actor has been stopped."; private static final String RESPONDS_TO = "respondsTo"; private static final String ON_DELIVERY_ERROR = "onDeliveryError"; private static final Object[] EMPTY_ARGUMENTS = new Object[0]; private static final String AFTER_START = "afterStart"; /** * This method represents the body of the actor. It is called upon actor's start and can exit either normally * by return or due to actor being stopped through the stop() method, which cancels the current actor action. * Provides an extension point for subclasses to provide their custom Actor's message handling code. */ protected abstract void act(); /** * Adds reply() and replyIfExists() methods to the currentActor and the message. * These methods will call send() on the target actor (the sender of the original message). * The reply()/replyIfExists() methods invoked on the actor will be sent to all currently processed messages, * reply()/replyIfExists() invoked on a message will send a reply to the sender of that particular message only. * * @param messages List of ActorMessage wrapping the sender actor, who we need to be able to respond to, * plus the original message */ private void enhanceReplies(final Iterable messages) { final List senders = getSenders(); senders.clear(); for (final ActorMessage message : messages) { senders.add(message == null ? null : message.getSender()); if (message != null) { obj2Sender.put(message.getPayLoad(), message.getSender()); } } } /** * Retrieves a message from the message queue, waiting, if necessary, for a message to arrive. * * @return The message retrieved from the queue. * @throws InterruptedException If the thread is interrupted during the wait. Should propagate up to stop the thread. */ @Override protected final Object receiveImpl() throws InterruptedException { checkStoppedFlags(); final ActorMessage message = takeMessage(); return enhanceAndUnwrap(message); } /** * Retrieves a message from the message queue, waiting, if necessary, for a message to arrive. * * @param timeout how long to wait before giving up, in units of unit * @param units a TimeUnit determining how to interpret the timeout parameter * @return The message retrieved from the queue, or null, if the timeout expires. * @throws InterruptedException If the thread is interrupted during the wait. Should propagate up to stop the thread. */ @Override protected final Object receiveImpl(final long timeout, final TimeUnit units) throws InterruptedException { checkStoppedFlags(); final ActorMessage message = takeMessage(timeout, units); return enhanceAndUnwrap(message); } private Object enhanceAndUnwrap(final ActorMessage message) { enhanceReplies(Arrays.asList(message)); if (message == null) { return null; } return message.getPayLoad(); } private void checkStoppedFlags() { if (stopFlag == S_NOT_STARTED) throw new IllegalStateException(THE_ACTOR_HAS_NOT_BEEN_STARTED); if (stopFlag == S_STOPPED) throw new IllegalStateException(THE_ACTOR_HAS_BEEN_STOPPED); } /** * Retrieves a message from the message queue, waiting, if necessary, for a message to arrive. * The message retrieved from the queue is passed into the handler as the only parameter. * * @param handler A closure accepting the retrieved message as a parameter, which will be invoked after a message is received. * @throws InterruptedException If the thread is interrupted during the wait. Should propagate up to stop the thread. */ @SuppressWarnings({"MethodOverloadsMethodOfSuperclass"}) protected final void receive(final Closure handler) throws InterruptedException { handler.setResolveStrategy(Closure.DELEGATE_FIRST); handler.setDelegate(this); final List messages = new ArrayList(); final int maxNumberOfParameters = handler.getMaximumNumberOfParameters(); final int toReceive = maxNumberOfParameters == 0 ? 1 : maxNumberOfParameters; collectRequiredMessages(messages, toReceive); enhanceReplies(messages); try { if (maxNumberOfParameters == 0) { handler.call(); } else { final Object[] args = new Object[messages.size()]; for (int i = 0; i < args.length; i++) { args[i] = messages.get(i).getPayLoad(); } handler.call(args); } } finally { getSenders().clear(); } } private void collectRequiredMessages(final Collection messages, final int toReceive) throws InterruptedException { for (int i = 0; i != toReceive; ++i) { checkStopTerminate(); messages.add(takeMessage()); } } /** * Retrieves a message from the message queue, waiting, if necessary, for a message to arrive. * The message retrieved from the queue is passed into the handler as the only parameter. * A null value is passed into the handler, if the timeout expires * * @param timeout how long to wait before giving up, in units of unit * @param timeUnit a TimeUnit determining how to interpret the timeout parameter * @param handler A closure accepting the retrieved message as a parameter, which will be invoked after a message is received. * @throws InterruptedException If the thread is interrupted during the wait. Should propagate up to stop the thread. */ protected final void receive(final long timeout, final TimeUnit timeUnit, final Closure handler) throws InterruptedException { handler.setResolveStrategy(Closure.DELEGATE_FIRST); handler.setDelegate(this); final int maxNumberOfParameters = handler.getMaximumNumberOfParameters(); final int toReceive = maxNumberOfParameters == 0 ? 1 : maxNumberOfParameters; final long stopTime = timeUnit.toMillis(timeout) + System.currentTimeMillis(); boolean nullAppeared = false; //Ignore further potential messages once a null is retrieved (due to a timeout) final List messages = new ArrayList(); for (int i = 0; i != toReceive; ++i) { if (nullAppeared) { messages.add(null); } else { if (stopFlag != S_RUNNING) { throw new IllegalStateException(THE_ACTOR_HAS_NOT_BEEN_STARTED); } final ActorMessage message = takeMessage(Math.max(stopTime - System.currentTimeMillis(), 0L), TimeUnit.MILLISECONDS); nullAppeared = message == null; messages.add(message); } } try { enhanceReplies(messages); if (maxNumberOfParameters == 0) { handler.call(); } else { final Object[] args = retrievePayloadOfMessages(messages); handler.call(args); } } finally { getSenders().clear(); } } private static Object[] retrievePayloadOfMessages(final List messages) { final Object[] args = new Object[messages.size()]; for (int i = 0; i < args.length; i++) { final ActorMessage am = messages.get(i); args[i] = am == null ? am : am.getPayLoad(); } return args; } /** * Retrieves a message from the message queue, waiting, if necessary, for a message to arrive. * The message retrieved from the queue is passed into the handler as the only parameter. * A null value is passed into the handler, if the timeout expires * * @param duration how long to wait before giving up, in units of unit * @param handler A closure accepting the retrieved message as a parameter, which will be invoked after a message is received. * @throws InterruptedException If the thread is interrupted during the wait. Should propagate up to stop the thread. */ @SuppressWarnings({"MethodOverloadsMethodOfSuperclass", "TypeMayBeWeakened"}) protected final void receive(final Duration duration, final Closure handler) throws InterruptedException { receive(duration.toMilliseconds(), TimeUnit.MILLISECONDS, handler); } /** * Clears the message queue returning all the messages it held. * * @return The messages stored in the queue */ final List sweepQueue() { final List messages = new ArrayList(); ActorMessage message = pollMessage(); while (message != null) { final Object payloadList = InvokerHelper.invokeMethod(message.getPayLoad(), RESPONDS_TO, new Object[]{ON_DELIVERY_ERROR}); if (payloadList != null && !((Collection) payloadList).isEmpty()) { InvokerHelper.invokeMethod(message.getPayLoad(), ON_DELIVERY_ERROR, EMPTY_ARGUMENTS); } else { final Object senderList = InvokerHelper.invokeMethod(message.getSender(), RESPONDS_TO, new Object[]{ON_DELIVERY_ERROR}); if (senderList != null && !((Collection) senderList).isEmpty()) { InvokerHelper.invokeMethod(message.getSender(), ON_DELIVERY_ERROR, EMPTY_ARGUMENTS); } } messages.add(message); message = pollMessage(); } return messages; } /** * Set on stop handler for this actor * * @param onStop The code to invoke when stopping */ public final void onStop(final Closure onStop) { if (onStop != null) { this.onStop = (Closure) onStop.clone(); this.onStop.setDelegate(this); this.onStop.setResolveStrategy(Closure.DELEGATE_FIRST); } } @Override protected void doOnStart() { final Object list = InvokerHelper.invokeMethod(this, RESPONDS_TO, new Object[]{AFTER_START}); if (list != null && !((Collection) list).isEmpty()) { InvokerHelper.invokeMethod(this, AFTER_START, EMPTY_ARGUMENTS); } act(); } @Override protected void doOnTimeout() { callDynamic("onTimeout", EMPTY_ARGUMENTS); } @Override @SuppressWarnings({"FeatureEnvy"}) protected void doOnTermination() { final List queue = sweepQueue(); if (onStop != null) onStop.call(queue); callDynamic("afterStop", new Object[]{queue}); } @SuppressWarnings({"UseOfSystemOutOrSystemErr"}) @Override protected void doOnException(final Throwable exception) { if (!callDynamic("onException", new Object[]{exception})) { System.err.println("An exception occurred in the Actor thread " + Thread.currentThread().getName()); exception.printStackTrace(System.err); } } @SuppressWarnings({"UseOfSystemOutOrSystemErr"}) @Override protected void doOnInterrupt(final InterruptedException exception) { if (!callDynamic("onInterrupt", new Object[]{exception})) { if (stopFlag == S_RUNNING) { System.err.println("The actor processing thread has been interrupted " + Thread.currentThread().getName()); exception.printStackTrace(System.err); } } } private boolean callDynamic(final String method, final Object[] args) { final MetaClass metaClass = InvokerHelper.getMetaClass(this); final List list = metaClass.respondsTo(this, method); if (list != null && !list.isEmpty()) { InvokerHelper.invokeMethod(this, method, args); return true; } return false; } } libgpars-groovy-java-0.10.orig/groovyx/gpars/ThreadLocalPools.groovy0000644000000000000000000000262511365257450022640 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-10 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars /** * Holds a thread-local stack of pools to allow for nested calls to ForkJoinPool.withPool() or GParsExecutorsPool.withPool() * * @author Vaclav Pech * Date: Dec 15, 2009 */ final class ThreadLocalPools extends ThreadLocal { protected List initialValue() { new LinkedList() } /** * Adds a new element */ void leftShift(pool) { get() << pool } /** * Removes the top (last) element */ void pop() { assert !get().isEmpty() get().removeLast() } /** * Gives the current element */ def getCurrent() { final def stack = get() stack.size() > 0 ? stack.last : null } } libgpars-groovy-java-0.10.orig/groovyx/gpars/Parallel.groovy0000644000000000000000000004513711365257450021202 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-10 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars /** * The Parallel interface holds methods that ParallelEnhancer adds to classes or instances when they get enhanced. * * @author Vaclav Pech * Date: Nov 1, 2009 */ final class Parallel { /** * Iterates over a collection/object with the each() method using an asynchronous variant of the supplied closure * to evaluate each collection's element. * After this method returns, all the closures have been finished and all the potential shared resources have been updated * by the threads. * It's important to protect any shared resources used by the supplied closure from race conditions caused by multi-threaded access. * If any of the collection's elements causes the closure to throw an exception, the exception is re-thrown. */ public def eachParallel(Closure cl) { GParsPool.ensurePool(ParallelEnhancer.threadPool.forkJoinPool) { GParsPoolUtil.eachParallel(mixedIn[Object], cl) } } /** * Iterates over a collection/object with the eachWithIndex() method using an asynchronous variant of the supplied closure * to evaluate each collection's element. * After this method returns, all the closures have been finished and all the potential shared resources have been updated * by the threads. * It's important to protect any shared resources used by the supplied closure from race conditions caused by multi-threaded access. * If any of the collection's elements causes the closure to throw an exception, the exception is re-thrown. */ public def eachWithIndexParallel(Closure cl) { GParsPool.ensurePool(ParallelEnhancer.threadPool.forkJoinPool) { GParsPoolUtil.eachWithIndexParallel(mixedIn[Object], cl) } } /** * Iterates over a collection/object with the collect() method using an asynchronous variant of the supplied closure * to evaluate each collection's element. * After this method returns, all the closures have been finished and the caller can safely use the result. * It's important to protect any shared resources used by the supplied closure from race conditions caused by multi-threaded access. * If any of the collection's elements causes the closure to throw an exception, the exception is re-thrown. * */ public def collectParallel(Closure cl) { GParsPool.ensurePool(ParallelEnhancer.threadPool.forkJoinPool) { enhance(GParsPoolUtil.collectParallel(mixedIn[Object], cl)) } } /** * Performs the findAll() operation using an asynchronous variant of the supplied closure * to evaluate each collection's/object's element. * After this method returns, all the closures have been finished and the caller can safely use the result. * It's important to protect any shared resources used by the supplied closure from race conditions caused by multi-threaded access. * If any of the collection's elements causes the closure to throw an exception, the exception is re-thrown. */ public def findAllParallel(Closure cl) { GParsPool.ensurePool(ParallelEnhancer.threadPool.forkJoinPool) { enhance(GParsPoolUtil.findAllParallel(mixedIn[Object], cl)) } } /** * Performs the grep() operation using an asynchronous variant of the supplied closure * to evaluate each collection's/object's element. * After this method returns, all the closures have been finished and the caller can safely use the result. * It's important to protect any shared resources used by the supplied closure from race conditions caused by multi-threaded access. * If any of the collection's elements causes the closure to throw an exception, the exception is re-thrown. */ public def grepParallel(Object filter) { GParsPool.ensurePool(ParallelEnhancer.threadPool.forkJoinPool) { enhance(GParsPoolUtil.grepParallel(mixedIn[Object], filter)) } } /** * Performs the split() operation using an asynchronous variant of the supplied closure * to evaluate each collection's/object's element. * After this method returns, all the closures have been finished and the caller can safely use the result. * It's important to protect any shared resources used by the supplied closure from race conditions caused by multi-threaded access. * If any of the collection's elements causes the closure to throw an exception, the exception is re-thrown. */ public def splitParallel(Closure cl) { GParsPool.ensurePool(ParallelEnhancer.threadPool.forkJoinPool) { enhance(GParsPoolUtil.splitParallel(mixedIn[Object], cl)) } } /** * Performs the count() operation using an asynchronous variant of the supplied closure * to evaluate each collection's/object's element. * After this method returns, all the closures have been finished and the caller can safely use the result. * It's important to protect any shared resources used by the supplied closure from race conditions caused by multi-threaded access. * If any of the collection's elements causes the closure to throw an exception, the exception is re-thrown. */ public def countParallel(Object filter) { GParsPool.ensurePool(ParallelEnhancer.threadPool.forkJoinPool) { enhance(GParsPoolUtil.countParallel(mixedIn[Object], filter)) } } /** * Performs the find() operation using an asynchronous variant of the supplied closure * to evaluate each collection's/object's element. * After this method returns, all the closures have been finished and the caller can safely use the result. * It's important to protect any shared resources used by the supplied closure from race conditions caused by multi-threaded access. * If any of the collection's elements causes the closure to throw an exception, the exception is re-thrown. */ public def findParallel(Closure cl) { GParsPool.ensurePool(ParallelEnhancer.threadPool.forkJoinPool) { GParsPoolUtil.findParallel(mixedIn[Object], cl) } } /** * Performs the find() operation using an asynchronous variant of the supplied closure * to evaluate each collection's/object's element. * Unlike with the find method, findAnyParallel() does not guarantee * that the a matching element with the lowest index is returned. * The findAnyParallel() method evaluates elements lazily and stops processing further elements of the collection once a match has been found. * After this method returns, all the closures have been finished and the caller can safely use the result. * It's important to protect any shared resources used by the supplied closure from race conditions caused by multi-threaded access. * If any of the collection's elements causes the closure to throw an exception, the exception is re-thrown. */ public def findAnyParallel(Closure cl) { GParsPool.ensurePool(ParallelEnhancer.threadPool.forkJoinPool) { GParsPoolUtil.findAnyParallel(mixedIn[Object], cl) } } /** * Performs the all() operation using an asynchronous variant of the supplied closure * to evaluate each collection's/object's element. * After this method returns, all the closures have been finished and the caller can safely use the result. * It's important to protect any shared resources used by the supplied closure from race conditions caused by multi-threaded access. * If any of the collection's elements causes the closure to throw an exception, the exception is re-thrown. */ public boolean everyParallel(Closure cl) { GParsPool.ensurePool(ParallelEnhancer.threadPool.forkJoinPool) { GParsPoolUtil.everyParallel(mixedIn[Object], cl) } } /** * Performs the any() operation using an asynchronous variant of the supplied closure * to evaluate each collection's/object's element. * The anyParallel() method is lazy and once a positive answer has been given by at least one element, it avoids running * the supplied closure on subsequent elements. * After this method returns, all the closures have been finished and the caller can safely use the result. * It's important to protect any shared resources used by the supplied closure from race conditions caused by multi-threaded access. * If any of the collection's elements causes the closure to throw an exception, the exception is re-thrown. */ public boolean anyParallel(Closure cl) { GParsPool.ensurePool(ParallelEnhancer.threadPool.forkJoinPool) { GParsPoolUtil.anyParallel(mixedIn[Object], cl) } } /** * Performs the groupBy() operation using an asynchronous variant of the supplied closure * to evaluate each collection's/object's element. * After this method returns, all the closures have been finished and the caller can safely use the result. * It's important to protect any shared resources used by the supplied closure from race conditions caused by multi-threaded access. * If any of the collection's elements causes the closure to throw an exception, the exception is re-thrown. */ public def groupByParallel(Closure cl) { GParsPool.ensurePool(ParallelEnhancer.threadPool.forkJoinPool) { GParsPoolUtil.groupByParallel(mixedIn[Object], cl) } } /** * Creates a Parallel Array out of the supplied collection/object and invokes its min() method using the supplied * closure as the comparator. * The closure will be effectively invoked concurrently on the elements of the collection. * After all the elements have been processed, the method returns the minimum of the elements in the collection. * It's important to protect any shared resources used by the supplied closure from race conditions caused by multi-threaded access. * Alternatively a DSL can be used to simplify the code. All collections/objects within the withPool block * have a new min(Closure cl) method, which delegates to the GParsPoolUtil class. * If the supplied closure takes two arguments it is used directly as a comparator. * If the supplied closure takes one argument, the values returned by the supplied closure for individual elements are used for comparison by the implicit comparator. * @param cl A one or two-argument closure */ public def minParallel(Closure cl) { GParsPool.ensurePool(ParallelEnhancer.threadPool.forkJoinPool) { GParsPoolUtil.minParallel(mixedIn[Object], cl) } } /** * Creates a Parallel Array out of the supplied collection/object and invokes its min() method using the default comparator. * The closure will be effectively invoked concurrently on the elements of the collection. * After all the elements have been processed, the method returns the minimum of the elements in the collection. * Alternatively a DSL can be used to simplify the code. All collections/objects within the withPool block * have a new min(Closure cl) method, which delegates to the GParsPoolUtil class. */ public def minParallel() { GParsPool.ensurePool(ParallelEnhancer.threadPool.forkJoinPool) { GParsPoolUtil.minParallel(mixedIn[Object]) } } /** * Creates a Parallel Array out of the supplied collection/object and invokes its max() method using the supplied * closure as the comparator. * The closure will be effectively invoked concurrently on the elements of the collection. * After all the elements have been processed, the method returns the maximum of the elements in the collection. * It's important to protect any shared resources used by the supplied closure from race conditions caused by multi-threaded access. * Alternatively a DSL can be used to simplify the code. All collections/objects within the withPool block * have a new min(Closure cl) method, which delegates to the GParsPoolUtil class. * If the supplied closure takes two arguments it is used directly as a comparator. * If the supplied closure takes one argument, the values returned by the supplied closure for individual elements are used for comparison by the implicit comparator. * @param cl A one or two-argument closure */ public def maxParallel(Closure cl) { GParsPool.ensurePool(ParallelEnhancer.threadPool.forkJoinPool) { GParsPoolUtil.maxParallel(mixedIn[Object], cl) } } /** * Creates a Parallel Array out of the supplied collection/object and invokes its max() method using the default comparator. * The closure will be effectively invoked concurrently on the elements of the collection. * After all the elements have been processed, the method returns the maximum of the elements in the collection. * Alternatively a DSL can be used to simplify the code. All collections/objects within the withPool block * have a new min(Closure cl) method, which delegates to the GParsPoolUtil class. */ public def maxParallel() { GParsPool.ensurePool(ParallelEnhancer.threadPool.forkJoinPool) { GParsPoolUtil.maxParallel(mixedIn[Object]) } } /** * Creates a Parallel Array out of the supplied collection/object and summarizes its elements using the foldParallel() * method with the + operator and the reduction operation. * The closure will be effectively invoked concurrently on the elements of the collection. * After all the elements have been processed, the method returns the sum of the elements in the collection. * Alternatively a DSL can be used to simplify the code. All collections/objects within the withPool block * have a new min(Closure cl) method, which delegates to the GParsPoolUtil class. */ public def sumParallel() { GParsPool.ensurePool(ParallelEnhancer.threadPool.forkJoinPool) { GParsPoolUtil.sumParallel(mixedIn[Object]) } } /** * Creates a Parallel Array out of the supplied collection/object and invokes its reduce() method using the supplied * closure as the reduction operation. * The closure will be effectively invoked concurrently on the elements of the collection. * After all the elements have been processed, the method returns the reduction result of the elements in the collection. * It's important to protect any shared resources used by the supplied closure from race conditions caused by multi-threaded access. * Alternatively a DSL can be used to simplify the code. All collections/objects within the withPool block * have a new min(Closure cl) method, which delegates to the GParsPoolUtil class. */ public def foldParallel(Closure cl) { GParsPool.ensurePool(ParallelEnhancer.threadPool.forkJoinPool) { GParsPoolUtil.foldParallel(mixedIn[Object], cl) } } /** * Creates a Parallel Array out of the supplied collection/object and invokes its reduce() method using the supplied * closure as the reduction operation. * The closure will be effectively invoked concurrently on the elements of the collection. * After all the elements have been processed, the method returns the reduction result of the elements in the collection. * It's important to protect any shared resources used by the supplied closure from race conditions caused by multi-threaded access. * Alternatively a DSL can be used to simplify the code. All collections/objects within the withPool block * have a new min(Closure cl) method, which delegates to the GParsPoolUtil class. * @param seed A seed value to initialize the operation */ public def foldParallel(seed, Closure cl) { GParsPool.ensurePool(ParallelEnhancer.threadPool.forkJoinPool) { GParsPoolUtil.foldParallel(mixedIn[Object], seed, cl) } } /** * Creates a PAWrapper around a ParallelArray wrapping te elements of the original collection. * This allows further parallel processing operations on the collection to chain and so effectively leverage the underlying * ParallelArray implementation. */ public PAWrapper getParallel() { GParsPool.ensurePool(ParallelEnhancer.threadPool.forkJoinPool) { GParsPoolUtil.getParallel(mixedIn[Object]) } } /** * Indicates, whether the iterative methods like each() or collect() have been made parallel. */ public def boolean isTransparent() {return false} /** * Creates a TransparentParallel class instance and mixes it in the object it is invoked on. The TransparentParallel class * overrides the iterative methods like each(), collect() and such, so that they call their parallel variants from the GParsPoolUtil class * like eachParallel(), collectParallel() and such. * After mixing-in, the isTransparent() method will return true. * Delegates to GParsPoolUtil.makeTransparent(). * @param collection The object to make transparent * @return The instance of the TransparentParallel class wrapping the original object and overriding the iterative methods with new parallel behavior */ static Object makeTransparent(Object collection) { GParsPoolUtil.makeTransparent(collection) } /** * Enhances to resulting collection so that parallel methods can be chained. */ @SuppressWarnings("GroovyMultipleReturnPointsPerMethod") private static def enhance(Object collection) { ParallelEnhancer.enhanceInstance(collection) } }libgpars-groovy-java-0.10.orig/groovyx/gpars/GParsPoolUtil.groovy0000644000000000000000000015151311365257450022146 0ustar // GPars (formerly GParallelizer) // // Copyright © 2008-10 The original author or authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package groovyx.gpars import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.Future import jsr166y.forkjoin.ForkJoinExecutor import jsr166y.forkjoin.ForkJoinPool import jsr166y.forkjoin.Ops.Mapper import jsr166y.forkjoin.Ops.Predicate import jsr166y.forkjoin.Ops.Reducer import jsr166y.forkjoin.ParallelArray import jsr166y.forkjoin.RecursiveTask /** * This class forms the core of the DSL initialized by GParsPool. The static methods of GParsPoolUtil * get attached to their first arguments (the Groovy Category mechanism) and can be then invoked as if they were part of * the argument classes. * @see groovyx.gpars.GParsPool * * @author Vaclav Pech * @author Robert Fischer * Date: Mar 10, 2010 */ public class GParsPoolUtil { private static ForkJoinPool retrievePool() { final ForkJoinPool pool = groovyx.gpars.GParsPool.retrieveCurrentPool() if (pool == null) throw new IllegalStateException("No ForkJoinPool available for the current thread") return pool } /** * schedules the supplied closure for processing in the underlying thread pool. */ private static Future callParallel(Closure task) { final ForkJoinPool pool = groovyx.gpars.GParsPool.retrieveCurrentPool() if (!pool) throw new IllegalStateException("No ExecutorService available for the current thread.") return pool.submit([compute: task] as RecursiveTask) } /** * Calls a closure in a separate thread supplying the given arguments, returning a future for the potential return value, */ public static Future callAsync(final Closure cl, final Object... args) { callParallel {-> cl(* args)} } /** * Submits the task for asynchronous processing returning the Future received from the executor service. * Allows for the following syntax: *
     * executorService << {println 'Inside parallel task'}* 
*/ public static Future leftShift(ForkJoinPool pool, Closure task) { return pool.submit([compute: task] as RecursiveTask) } /** * Creates an asynchronous variant of the supplied closure, which, when invoked returns a future for the potential return value */ public static Closure async(Closure cl) { return {Object... args -> callAsync(cl, * args)} } private static ParallelArray createPA(Collection collection, ForkJoinExecutor pool) { return ParallelArray.createFromCopy(collection.toArray(new T[collection.size()]), pool) } static java.util.Collection createCollection(Object object) { def collection = [] for (element in object) collection << element return collection } /** * Creates a TransparentParallel class instance and mixes it in the object it is invoked on. The TransparentParallel class * overrides the iterative methods like each(), collect() and such, so that they call their parallel variants from the GParsPoolUtil class * like eachParallel(), collectParallel() and such. * After mixing-in, the isTransparent() method will return true. * @param collection The object to make transparent * @return The instance of the TransparentParallel class wrapping the original object and overriding the iterative methods with new parallel behavior */ public static Object makeTransparent(Object collection) { if (!(collection.respondsTo('isTransparent'))) throw new IllegalStateException("Cannot make the object transparently parallel. Apparently we're not inside a GParsPool.withPool() block nor the collection hasn't been enhanced with ParallelEnhancer.enhance().") if (!collection.isTransparent()) collection.metaClass.mixin(TransparentParallel) return collection } /** * Indicates whether the iterative methods like each() or collect() work have been altered to work concurrently. */ public static boolean isTransparent(Object collection) { false } /** * Creates a Parallel Array out of the supplied collection/object and invokes the withMapping() method using the supplied * closure as the transformation operation. * The closure will be effectively invoked concurrently on the elements of the collection. * After all the elements have been processed, the method returns. * It's important to protect any shared resources used by the supplied closure from race conditions caused by multi-threaded access. * Alternatively a DSL can be used to simplify the code. All collections/objects within the withPool block * have a new eachParallel(Closure cl) method, which delegates to the GParsPoolUtil class. * Example: * GParsPool.withPool {* def result = new ConcurrentSkipListSet() * [1, 2, 3, 4, 5].eachParallel {Number number -> result.add(number * 10)}* assertEquals(new HashSet([10, 20, 30, 40, 50]), result) *}* Note that the result variable is synchronized to prevent race conditions between multiple threads. */ public static Collection eachParallel(Collection collection, Closure cl) { createPA(collection, retrievePool()).withMapping({cl(it)} as Mapper).all() return collection } /** * Creates a Parallel Array out of the supplied collection/object and invokes the withMapping() method using the supplied * closure as the transformation operation. * The closure will be effectively invoked concurrently on the elements of the collection. * After all the elements have been processed, the method returns. * It's important to protect any shared resources used by the supplied closure from race conditions caused by multi-threaded access. * Alternatively a DSL can be used to simplify the code. All collections/objects within the withPool block * have a new eachParallel(Closure cl) method, which delegates to the GParsPoolUtil class. * Example: * GParsPool.withPool {* def result = new ConcurrentSkipListSet() * [1, 2, 3, 4, 5].eachParallel {Number number -> result.add(number * 10)}* assertEquals(new HashSet([10, 20, 30, 40, 50]), result) *}* Note that the result variable is synchronized to prevent race conditions between multiple threads. */ public static Object eachParallel(Object collection, Closure cl) { eachParallel(createCollection(collection), cl) return collection } /** * Creates a Parallel Array out of the supplied collection/object and invokes the withMapping() method using the supplied * closure as the transformation operation. * The closure will be effectively invoked concurrently on the elements of the collection. * After all the elements have been processed, the method returns. * It's important to protect any shared resources used by the supplied closure from race conditions caused by multi-threaded access. * Alternatively a DSL can be used to simplify the code. All collections/objects within the withPool block * have a new eachWithIndexParallel(Closure cl) method, which delegates to the GParsPoolUtil class. * Example: * GParsPool.withPool {* def result = new ConcurrentSkipListSet() * [1, 2, 3, 4, 5].eachWithIndexParallel {Number number, int index -> result.add(number * 10)}* assertEquals(new HashSet([10, 20, 30, 40, 50]), result) *}* Note that the result variable is synchronized to prevent race conditions between multiple threads. */ public static Collection eachWithIndexParallel(Collection collection, Closure cl) { def indexedCollection = [] int index = 0 for (element in collection) { indexedCollection << [element, index] index++ } createPA(indexedCollection, retrievePool()).withMapping({cl(it[0], it[1])} as Mapper).all() return collection } /** * Creates a Parallel Array out of the supplied collection/object and invokes the withMapping() method using the supplied * closure as the transformation operation. * The closure will be effectively invoked concurrently on the elements of the collection. * After all the elements have been processed, the method returns. * It's important to protect any shared resources used by the supplied closure from race conditions caused by multi-threaded access. * Alternatively a DSL can be used to simplify the code. All collections/objects within the withPool block * have a new eachWithIndexParallel(Closure cl) method, which delegates to the GParsPoolUtil class. * Example: * GParsPool.withPool {* def result = new ConcurrentSkipListSet() * [1, 2, 3, 4, 5].eachWithIndexParallel {Number number, int index -> result.add(number * 10)}* assertEquals(new HashSet([10, 20, 30, 40, 50]), result) *}* Note that the result variable is synchronized to prevent race conditions between multiple threads. */ public static Object eachWithIndexParallel(Object collection, Closure cl) { eachWithIndexParallel(createCollection(collection), cl) return collection } /** * Creates a Parallel Array out of the supplied collection/object and invokes the withMapping() method using the supplied * closure as the transformation operation. * The closure will be effectively invoked concurrently on the elements of the collection. * After all the elements have been processed, the method returns a collection of values from the resulting Parallel Array. * It's important to protect any shared resources used by the supplied closure from race conditions caused by multi-threaded access. * Alternatively a DSL can be used to simplify the code. All collections/objects within the withPool block * have a new collectParallel(Closure cl) method, which delegates to the GParsPoolUtil class. * Example: * GParsPool.withPool {* def result = [1, 2, 3, 4, 5].collectParallel {Number number -> number * 10}* assertEquals(new HashSet([10, 20, 30, 40, 50]), result) *}*/ public static Collection collectParallel(Collection collection, Closure cl) { createPA(collection, retrievePool()).withMapping({cl(it)} as Mapper).all().asList() } /** * Creates a Parallel Array out of the supplied collection/object and invokes the withMapping() method using the supplied * closure as the transformation operation. * The closure will be effectively invoked concurrently on the elements of the collection. * After all the elements have been processed, the method returns a collection of values from the resulting Parallel Array. * It's important to protect any shared resources used by the supplied closure from race conditions caused by multi-threaded access. * Alternatively a DSL can be used to simplify the code. All collections/objects within the withPool block * have a new collectParallel(Closure cl) method, which delegates to the GParsPoolUtil class. * Example: * GParsPool.withPool {* def result = [1, 2, 3, 4, 5].collectParallel {Number number -> number * 10}* assertEquals(new HashSet([10, 20, 30, 40, 50]), result) *}*/ public static Collection collectParallel(Object collection, Closure cl) { return collectParallel(createCollection(collection), cl) } /** * Creates a Parallel Array out of the supplied collection/object and invokes the withFilter() method using the supplied * closure as the filter predicate. * The closure will be effectively invoked concurrently on the elements of the collection. * After all the elements have been processed, the method returns a collection of values from the resulting Parallel Array. * It's important to protect any shared resources used by the supplied closure from race conditions caused by multi-threaded access. * Alternatively a DSL can be used to simplify the code. All collections/objects within the withPool block * have a new findAllParallel(Closure cl) method, which delegates to the GParsPoolUtil class. * Example: * GParsPool.withPool {* def result = [1, 2, 3, 4, 5].findAllParallel {Number number -> number > 3}* assertEquals(new HashSet([4, 5]), result) *}*/ public static Collection findAllParallel(Collection collection, Closure cl) { createPA(collection, retrievePool()).withFilter({cl(it) as Boolean} as Predicate).all().asList() } /** * Creates a Parallel Array out of the supplied collection/object and invokes the withFilter() method using the supplied * closure as the filter predicate. * The closure will be effectively invoked concurrently on the elements of the collection. * After all the elements have been processed, the method returns a collection of values from the resulting Parallel Array. * It's important to protect any shared resources used by the supplied closure from race conditions caused by multi-threaded access. * Alternatively a DSL can be used to simplify the code. All collections/objects within the withPool block * have a new findAllParallel(Closure cl) method, which delegates to the GParsPoolUtil class. * Example: * GParsPool.withPool {* def result = [1, 2, 3, 4, 5].findAllParallel {Number number -> number > 3}* assertEquals(new HashSet([4, 5]), result) *}*/ public static Collection findAllParallel(Object collection, Closure cl) { return findAllParallel(createCollection(collection), cl) } /** * Creates a Parallel Array out of the supplied collection/object and invokes the withFilter() method using the supplied * closure as the filter predicate. * The closure will be effectively invoked concurrently on the elements of the collection. * After all the elements have been processed, the method returns a value from the resulting Parallel Array with the minimum index. * It's important to protect any shared resources used by the supplied closure from race conditions caused by multi-threaded access. * Alternatively a DSL can be used to simplify the code. All collections/objects within the withPool block * have a new findParallel(Closure cl) method, which delegates to the GParsPoolUtil class. * Example: * GParsPool.withPool {* def result = [1, 2, 3, 4, 5].findParallel {Number number -> number > 3}* assert (result in [4, 5]) *}*/ public static Object findParallel(Collection collection, Closure cl) { final ParallelArray found = createPA(collection, retrievePool()).withFilter({cl(it) as Boolean} as Predicate).all() if (found.size() > 0) found.get(0) else return null } /** * Creates a Parallel Array out of the supplied collection/object and invokes the withFilter() method using the supplied * closure as the filter predicate. * The closure will be effectively invoked concurrently on the elements of the collection. * After all the elements have been processed, the method returns a value from the resulting Parallel Array with the minimum index. * It's important to protect any shared resources used by the supplied closure from race conditions caused by multi-threaded access. * Alternatively a DSL can be used to simplify the code. All collections/objects within the withPool block * have a new findParallel(Closure cl) method, which delegates to the GParsPoolUtil class. * Example: * GParsPool.withPool {* def result = [1, 2, 3, 4, 5].findParallel {Number number -> number > 3}* assert (result in [4, 5]) *}*/ public static Object findParallel(Object collection, Closure cl) { return findParallel(createCollection(collection), cl) } /** * Creates a Parallel Array out of the supplied collection/object and invokes the withFilter() method using the supplied * closure as the filter predicate. * Unlike with the find method, findAnyParallel() does not guarantee * that the a matching element with the lowest index is returned. * The findAnyParallel() method evaluates elements lazily and stops processing further elements of the collection once a match has been found. * The closure will be effectively invoked concurrently on the elements of the collection. * After all the elements have been processed, the method returns a random value from the resulting Parallel Array. * It's important to protect any shared resources used by the supplied closure from race conditions caused by multi-threaded access. * Alternatively a DSL can be used to simplify the code. All collections/objects within the withPool block * have a new findParallel(Closure cl) method, which delegates to the GParsPoolUtil class. * Example: * GParsPool.withPool {* def result = [1, 2, 3, 4, 5].findParallel {Number number -> number > 3}* assert (result in [4, 5]) *}*/ public static Object findAnyParallel(Collection collection, Closure cl) { createPA(collection, retrievePool()).withFilter({cl(it) as Boolean} as Predicate).any() } /** * Creates a Parallel Array out of the supplied collection/object and invokes the withFilter() method using the supplied * closure as the filter predicate. * Unlike with the find method, findAnyParallel() does not guarantee * that the a matching element with the lowest index is returned. * The findAnyParallel() method evaluates elements lazily and stops processing further elements of the collection once a match has been found. * The closure will be effectively invoked concurrently on the elements of the collection. * After all the elements have been processed, the method returns a random value from the resulting Parallel Array. * It's important to protect any shared resources used by the supplied closure from race conditions caused by multi-threaded access. * Alternatively a DSL can be used to simplify the code. All collections/objects within the withPool block * have a new findParallel(Closure cl) method, which delegates to the GParsPoolUtil class. * Example: * GParsPool.withPool {* def result = [1, 2, 3, 4, 5].findParallel {Number number -> number > 3}* assert (result in [4, 5]) *}*/ public static Object findAnyParallel(Object collection, Closure cl) { return findParallel(createCollection(collection), cl) } /** * Creates a Parallel Array out of the supplied collection/object and invokes the withFilter() method using the supplied * rule as the filter predicate. * The filter will be effectively used concurrently on the elements of the collection. * After all the elements have been processed, the method returns a collection of values from the resulting Parallel Array. * It's important to protect any shared resources used by the supplied closure from race conditions caused by multi-threaded access. * Alternatively a DSL can be used to simplify the code. All collections/objects within the withPool block * have a new grepParallel(Closure cl) method, which delegates to the GParsPoolUtil class. * Example: * GParsPool.withPool {* def result = [1, 2, 3, 4, 5].grepParallel(4..6) * assertEquals(new HashSet([4, 5]), result) *}*/ public static Collection grepParallel(Collection collection, filter) { createPA(collection, retrievePool()).withFilter({filter.isCase it} as Predicate).all().asList() } /** * Creates a Parallel Array out of the supplied collection/object and invokes the withFilter() method using the supplied * rule as the filter predicate. * The filter will be effectively used concurrently on the elements of the collection. * After all the elements have been processed, the method returns a collection of values from the resulting Parallel Array. * It's important to protect any shared resources used by the supplied closure from race conditions caused by multi-threaded access. * Alternatively a DSL can be used to simplify the code. All collections/objects within the withPool block * have a new grepParallel(Closure cl) method, which delegates to the GParsPoolUtil class. * Example: * GParsPool.withPool {* def result = [1, 2, 3, 4, 5].grepParallel(4..6) * assertEquals(new HashSet([4, 5]), result) *}*/ public static Object grepParallel(Object collection, filter) { return grepParallel(createCollection(collection), filter) } /** * Creates a Parallel Array out of the supplied collection/object and invokes the withFilter() method using the supplied * rule as the filter predicate. * The filter will be effectively used concurrently on the elements of the collection. * After all the elements have been processed, the method returns a collection of values from the resulting Parallel Array. * It's important to protect any shared resources used by the supplied closure from race conditions caused by multi-threaded access. * Alternatively a DSL can be used to simplify the code. All collections/objects within the withPool block * have a new grepParallel(Closure cl) method, which delegates to the GParsPoolUtil class. * Example: * GParsPool.withPool {* def result = [1, 2, 3, 4, 5].splitParallel(it > 3) * assert [3, 4, 5] as Set == result[0] as Set * assert [1, 2] as Set == result[1] as Set *}*/ public static Collection splitParallel(Collection collection, filter) { final def groups = groupByParallel(collection, filter) return [groups[true] ?: [], groups[false] ?: []] } /** * Creates a Parallel Array out of the supplied collection/object and invokes the withFilter() method using the supplied * rule as the filter predicate. * The filter will be effectively used concurrently on the elements of the collection. * After all the elements have been processed, the method returns a collection of values from the resulting Parallel Array. * It's important to protect any shared resources used by the supplied closure from race conditions caused by multi-threaded access. * Alternatively a DSL can be used to simplify the code. All collections/objects within the withPool block * have a new grepParallel(Closure cl) method, which delegates to the GParsPoolUtil class. * Example: * GParsPool.withPool {* def result = [1, 2, 3, 4, 5].splitParallel(4..6) * assert [3, 4, 5] as Set == result[0] as Set * assert [1, 2] as Set == result[1] as Set *}*/ public static Object splitParallel(Object collection, filter) { return splitParallel(createCollection(collection), filter) } /** * Creates a Parallel Array out of the supplied collection/object and invokes the withFilter() method using the supplied * rule as the filter predicate. * The filter will be effectively used concurrently on the elements of the collection. * After all the elements have been processed, the method returns a collection of values from the resulting Parallel Array. * It's important to protect any shared resources used by the supplied closure from race conditions caused by multi-threaded access. * Alternatively a DSL can be used to simplify the code. All collections/objects within the withPool block * have a new grepParallel(Closure cl) method, which delegates to the GParsPoolUtil class. * Example: * GParsPool.withPool {* def result = [1, 2, 3, 4, 5].countParallel(4) * assertEquals(1, result) *}*/ public static int countParallel(Collection collection, filter) { createPA(collection, retrievePool()).withFilter({filter == it} as Predicate).size() } /** * Creates a Parallel Array out of the supplied collection/object and invokes the withFilter() method using the supplied * rule as the filter predicate. * The filter will be effectively used concurrently on the elements of the collection. * After all the elements have been processed, the method returns a collection of values from the resulting Parallel Array. * It's important to protect any shared resources used by the supplied closure from race conditions caused by multi-threaded access. * Alternatively a DSL can be used to simplify the code. All collections/objects within the withPool block * have a new grepParallel(Closure cl) method, which delegates to the GParsPoolUtil class. * Example: * GParsPool.withPool {* def result = [1, 2, 3, 4, 5].countParallel(4) * assertEquals(1, result) *}*/ public static int countParallel(Object collection, filter) { return countParallel(createCollection(collection), filter) } /** * Creates a Parallel Array out of the supplied collection/object and invokes the withFilter() method using the supplied * closure as the filter predicate. * The closure will be effectively invoked concurrently on the elements of the collection. * The anyParallel() method is lazy and once a positive answer has been given by at least one element, it avoids running * the supplied closure on subsequent elements. * After all the elements have been processed, the method returns a boolean value indicating, whether at least * one element of the collection meets the predicate. * It's important to protect any shared resources used by the supplied closure from race conditions caused by multi-threaded access. * Alternatively a DSL can be used to simplify the code. All collections/objects within the withPool block * have a new anyParallel(Closure cl) method, which delegates to the GParsPoolUtil class. * Example: * GParsPool.withPool {* assert [1, 2, 3, 4, 5].anyParallel {Number number -> number > 3}* assert ![1, 2, 3].anyParallel {Number number -> number > 3}*}*/ public static boolean anyParallel(Collection collection, Closure cl) { createPA(collection, retrievePool()).withFilter({cl(it) as Boolean} as Predicate).any() != null } /** * Creates a Parallel Array out of the supplied collection/object and invokes the withFilter() method using the supplied * closure as the filter predicate. * The closure will be effectively invoked concurrently on the elements of the collection. * The anyParallel() method is lazy and once a positive answer has been given by at least one element, it avoids running * the supplied closure on subsequent elements. * After all the elements have been processed, the method returns a boolean value indicating, whether at least * one element of the collection meets the predicate. * It's important to protect any shared resources used by the supplied closure from race conditions caused by multi-threaded access. * Alternatively a DSL can be used to simplify the code. All collections/objects within the withPool block * have a new anyParallel(Closure cl) method, which delegates to the GParsPoolUtil class. * Example: * GParsPool.withPool {* assert [1, 2, 3, 4, 5].anyParallel {Number number -> number > 3}* assert ![1, 2, 3].anyParallel {Number number -> number > 3}*}*/ public static boolean anyParallel(Object collection, Closure cl) { return anyParallel(createCollection(collection), cl) } /** * Creates a Parallel Array out of the supplied collection/object and invokes the withFilter() method using the supplied * closure as the filter predicate. * The closure will be effectively invoked concurrently on the elements of the collection. * After all the elements have been processed, the method returns a boolean value indicating, whether all the elements * of the collection meet the predicate. * It's important to protect any shared resources used by the supplied closure from race conditions caused by multi-threaded access. * Alternatively a DSL can be used to simplify the code. All collections/objects within the withPool block * have a new everyParallel(Closure cl) method, which delegates to the GParsPoolUtil class. * Example: * GParsPool.withPool(5) {* assert ![1, 2, 3, 4, 5].everyParallel {Number number -> number > 3}* assert [1, 2, 3].everyParallel() {Number number -> number <= 3}*}*/ public static boolean everyParallel(Collection collection, Closure cl) { createPA(collection, retrievePool()).withFilter({cl(it) as Boolean} as Predicate).all().size() == collection.size() } /** * Creates a Parallel Array out of the supplied collection/object and invokes the withFilter() method using the supplied * closure as the filter predicate. * The closure will be effectively invoked concurrently on the elements of the collection. * After all the elements have been processed, the method returns a boolean value indicating, whether all the elements * of the collection meet the predicate. * It's important to protect any shared resources used by the supplied closure from race conditions caused by multi-threaded access. * Alternatively a DSL can be used to simplify the code. All collections/objects within the withPool block * have a new everyParallel(Closure cl) method, which delegates to the GParsPoolUtil class. * Example: * GParsPool.withPool(5) {* assert ![1, 2, 3, 4, 5].everyParallel {Number number -> number > 3}* assert [1, 2, 3].everyParallel() {Number number -> number <= 3}*}*/ public static boolean everyParallel(Object collection, Closure cl) { return everyParallel(createCollection(collection), cl) } /** * Creates a Parallel Array out of the supplied collection/object and invokes the withMapping() method using the supplied * closure as the mapping predicate. * The closure will be effectively invoked concurrently on the elements of the collection. * After all the elements have been processed, the method returns a list of groups of the original elements. * Elements in the same group gave identical results when the supplied closure was invoked on them. * It's important to protect any shared resources used by the supplied closure from race conditions caused by multi-threaded access. * Alternatively a DSL can be used to simplify the code. All collections/objects within the withPool block * have a new groupByParallel(Closure cl) method, which delegates to the GParsPoolUtil class. * Example: * GParsPool.withPool {* assert ([1, 2, 3, 4, 5].groupByParallel {Number number -> number % 2}).size() == 2 *}*/ public static Map groupByParallel(Collection collection, Closure cl) { final def map = new ConcurrentHashMap() eachParallel(collection, { def result = cl(it) final def myList = [it].asSynchronized() def list = map.putIfAbsent(result, myList) if (list != null) list.add(it) }) return map } /** * Creates a Parallel Array out of the supplied collection/object and invokes the withMapping() method using the supplied * closure as the mapping predicate. * The closure will be effectively invoked concurrently on the elements of the collection. * After all the elements have been processed, the method returns a list of groups of the original elements. * Elements in the same group gave identical results when the supplied closure was invoked on them. * It's important to protect any shared resources used by the supplied closure from race conditions caused by multi-threaded access. * Alternatively a DSL can be used to simplify the code. All collections/objects within the withPool block * have a new groupByParallel(Closure cl) method, which delegates to the GParsPoolUtil class. * Example: * GParsPool.withPool {* assert ([1, 2, 3, 4, 5].groupByParallel {Number number -> number % 2}).size() == 2 *}*/ public static Map groupByParallel(Object collection, Closure cl) { return groupByParallel(createCollection(collection), cl) } /** * Creates a Parallel Array out of the supplied collection/object and invokes its min() method using the supplied * closure as the comparator. * The closure will be effectively invoked concurrently on the elements of the collection. * After all the elements have been processed, the method returns the minimum of the elements in the collection. * It's important to protect any shared resources used by the supplied closure from race conditions caused by multi-threaded access. * Alternatively a DSL can be used to simplify the code. All collections/objects within the withPool block * have a new min(Closure cl) method, which delegates to the GParsPoolUtil class. * If the supplied closure takes two arguments it is used directly as a comparator. * If the supplied closure takes one argument, the values returned by the supplied closure for individual elements are used for comparison by the implicit comparator. * @param cl A one or two-argument closure */ public static T minParallel(Collection collection, Closure cl) { createPA(collection, retrievePool()).min(createComparator(cl) as Comparator) } /** * Creates a Parallel Array out of the supplied collection/object and invokes its min() method using the supplied * closure as the comparator. * The closure will be effectively invoked concurrently on the elements of the collection. * After all the elements have been processed, the method returns the minimum of the elements in the collection. * It's important to protect any shared resources used by the supplied closure from race conditions caused by multi-threaded access. * Alternatively a DSL can be used to simplify the code. All collections/objects within the withPool block * have a new min(Closure cl) method, which delegates to the GParsPoolUtil class. * If the supplied closure takes two arguments it is used directly as a comparator. * If the supplied closure takes one argument, the values returned by the supplied closure for individual elements are used for comparison by the implicit comparator. * @param cl A one or two-argument closure */ public static Object minParallel(Object collection, Closure cl) { return minParallel(createCollection(collection), cl) } /** * Creates a Parallel Array out of the supplied collection/object and invokes its min() method using the default comparator. * The closure will be effectively invoked concurrently on the elements of the collection. * After all the elements have been processed, the method returns the minimum of the elements in the collection. * Alternatively a DSL can be used to simplify the code. All collections/objects within the withPool block * have a new min(Closure cl) method, which delegates to the GParsPoolUtil class. */ public static T minParallel(Collection collection) { createPA(collection, retrievePool()).min() } /** * Creates a Parallel Array out of the supplied collection/object and invokes its min() method using the default comparator. * The closure will be effectively invoked concurrently on the elements of the collection. * After all the elements have been processed, the method returns the minimum of the elements in the collection. * Alternatively a DSL can be used to simplify the code. All collections/objects within the withPool block * have a new min(Closure cl) method, which delegates to the GParsPoolUtil class. */ public static Object minParallel(Object collection) { return minParallel(createCollection(collection)) } /** * Creates a Parallel Array out of the supplied collection/object and invokes its max() method using the supplied * closure as the comparator. * The closure will be effectively invoked concurrently on the elements of the collection. * After all the elements have been processed, the method returns the maximum of the elements in the collection. * It's important to protect any shared resources used by the supplied closure from race conditions caused by multi-threaded access. * Alternatively a DSL can be used to simplify the code. All collections/objects within the withPool block * have a new min(Closure cl) method, which delegates to the GParsPoolUtil class. * If the supplied closure takes two arguments it is used directly as a comparator. * If the supplied closure takes one argument, the values returned by the supplied closure for individual elements are used for comparison by the implicit comparator. * @param cl A one or two-argument closure */ public static T maxParallel(Collection collection, Closure cl) { createPA(collection, retrievePool()).max(createComparator(cl) as Comparator) } /** * Creates a Parallel Array out of the supplied collection/object and invokes its max() method using the supplied * closure as the comparator. * The closure will be effectively invoked concurrently on the elements of the collection. * After all the elements have been processed, the method returns the maximum of the elements in the collection. * It's important to protect any shared resources used by the supplied closure from race conditions caused by multi-threaded access. * Alternatively a DSL can be used to simplify the code. All collections/objects within the withPool block * have a new min(Closure cl) method, which delegates to the GParsPoolUtil class. * If the supplied closure takes two arguments it is used directly as a comparator. * If the supplied closure takes one argument, the values returned by the supplied closure for individual elements are used for comparison by the implicit comparator. * @param cl A one or two-argument closure */ public static Object maxParallel(Object collection, Closure cl) { return maxParallel(createCollection(collection), cl) } /** * Creates a Parallel Array out of the supplied collection/object and invokes its max() method using the default comparator. * The closure will be effectively invoked concurrently on the elements of the collection. * After all the elements have been processed, the method returns the maximum of the elements in the collection. * Alternatively a DSL can be used to simplify the code. All collections/objects within the withPool block * have a new min(Closure cl) method, which delegates to the GParsPoolUtil class. */ public static T maxParallel(Collection collection) { createPA(collection, retrievePool()).max() } /** * Creates a Parallel Array out of the supplied collection/object and invokes its max() method using the default comparator. * The closure will be effectively invoked concurrently on the elements of the collection. * After all the elements have been processed, the method returns the maximum of the elements in the collection. * Alternatively a DSL can be used to simplify the code. All collections/objects within the withPool block * have a new min(Closure cl) method, which delegates to the GParsPoolUtil class. */ public static Object maxParallel(Object collection) { return maxParallel(createCollection(collection)) } /** * Creates a Parallel Array out of the supplied collection/object and summarizes its elements using the foldParallel() * method with the + operator and the reduction operation. * The closure will be effectively invoked concurrently on the elements of the collection. * After all the elements have been processed, the method returns the sum of the elements in the collection. * Alternatively a DSL can be used to simplify the code. All collections/objects within the withPool block * have a new min(Closure cl) method, which delegates to the GParsPoolUtil class. */ public static T sumParallel(Collection collection) { foldParallel(collection) {a, b -> a + b} } /** * Creates a Parallel Array out of the supplied collection/object and summarizes its elements using the foldParallel() * method with the + operator and the reduction operation. * The closure will be effectively invoked concurrently on the elements of the collection. * After all the elements have been processed, the method returns the sum of the elements in the collection. * Alternatively a DSL can be used to simplify the code. All collections/objects within the withPool block * have a new min(Closure cl) method, which delegates to the GParsPoolUtil class. */ public static Object sumParallel(Object collection) { return sumParallel(createCollection(collection)) } /** * Creates a Parallel Array out of the supplied collection/object and invokes its reduce() method using the supplied * closure as the reduction operation. * The closure will be effectively invoked concurrently on the elements of the collection. * After all the elements have been processed, the method returns the reduction result of the elements in the collection. * It's important to protect any shared resources used by the supplied closure from race conditions caused by multi-threaded access. * Alternatively a DSL can be used to simplify the code. All collections/objects within the withPool block * have a new min(Closure cl) method, which delegates to the GParsPoolUtil class. */ public static T foldParallel(Collection collection, Closure cl) { createPA(collection, retrievePool()).reduce(cl as Reducer, null) } /** * Creates a Parallel Array out of the supplied collection/object and invokes its reduce() method using the supplied * closure as the reduction operation. * The closure will be effectively invoked concurrently on the elements of the collection. * After all the elements have been processed, the method returns the reduction result of the elements in the collection. * It's important to protect any shared resources used by the supplied closure from race conditions caused by multi-threaded access. * Alternatively a DSL can be used to simplify the code. All collections/objects within the withPool block * have a new min(Closure cl) method, which delegates to the GParsPoolUtil class. */ public static Object foldParallel(Object collection, Closure cl) { return foldParallel(createCollection(collection), cl) } /** * Creates a Parallel Array out of the supplied collection/object and invokes its reduce() method using the supplied * closure as the reduction operation. * The closure will be effectively invoked concurrently on the elements of the collection. * After all the elements have been processed, the method returns the reduction result of the elements in the collection. * It's important to protect any shared resources used by the supplied closure from race conditions caused by multi-threaded access. * Alternatively a DSL can be used to simplify the code. All collections/objects within the withPool block * have a new min(Closure cl) method, which delegates to the GParsPoolUtil class. * @param seed A seed value to initialize the operation */ public static T foldParallel(Collection collection, seed, Closure cl) { createPA(collection.plus(seed), retrievePool()).reduce(cl as Reducer, null) } /** * Creates a Parallel Array out of the supplied collection/object and invokes its reduce() method using the supplied * closure as the reduction operation. * The closure will be effectively invoked concurrently on the elements of the collection. * After all the elements have been processed, the method returns the reduction result of the elements in the collection. * It's important to protect any shared resources used by the supplied closure from race conditions caused by multi-threaded access. * Alternatively a DSL can be used to simplify the code. All collections/objects within the withPool block * have a new min(Closure cl) method, which delegates to the GParsPoolUtil class. * @param seed A seed value to initialize the operation */ public static Object foldParallel(Object collection, seed, Closure cl) { return foldParallel(createCollection(collection), seed, cl) } /** * Creates a PAWrapper around a ParallelArray wrapping te elements of the original collection. * This allows further parallel processing operations on the collection to chain and so effectively leverage the underlying * ParallelArray implementation. */ public static PAWrapper getParallel(Collection collection) { new PAWrapper(createPA(collection, retrievePool())) } /** * Creates a PAWrapper around a ParallelArray wrapping te elements of the original collection. * This allows further parallel processing operations on the collection to chain and so effectively leverage the underlying * ParallelArray implementation. */ public static Object getParallel(Object collection) { return getParallel(createCollection(collection)) } /** * Builds a comparator depending on the number of arguments accepted by the supplied closure. */ @SuppressWarnings("GroovyMultipleReturnPointsPerMethod") static Closure createComparator(final Closure handler) { if (handler.maximumNumberOfParameters == 2) return handler else return {a, b -> handler(a).compareTo(handler(b))} } } /** * Wraps a ParallelArray instance in map/reduce operation chains. */ abstract class AbstractPAWrapper { /** * The wrapper ParallelArray instance */ final def pa /** * Creates an instance wrapping the supplied instance of ParallelArray */ def AbstractPAWrapper(final pa) { this.pa = pa } /** * Reconstructs a collection from the wrapped ParallelArray instance * @return A collection containing all elements of the wrapped ParallelArray */ public final Object getCollection() { this.pa.all().asList() as ArrayList } /** * Performs a parallel reduce operation. It will use the supplied two-argument closure to gradually reduce two elements into one. * @param cl A two-argument closure merging two elements into one. The return value of the closure will replace the original two elements. * @return The product of reduction */ public final T reduce(Closure cl) { pa.reduce(cl as Reducer, null) } /** * Performs a parallel reduce operation. It will use the supplied two-argument closure to gradually reduce two elements into one. * @param cl A two-argument closure merging two elements into one. The return value of the closure will replace the original two elements. * @return The product of reduction */ public final T reduce(seed, Closure cl) { final def newPA = pa.all() newPA.appendElement(seed) newPA.reduce(cl as Reducer, null) } /** * Summarizes all elements of the collection in parallel using the "plus()" operator of the elements * @return The summary od all elements in the collection */ public final T sum() { reduce {a, b -> a + b} } /** * Size of the collection * @return The number of elements in the collection */ public final int size() { pa.size() } /** * Finds in parallel the minimum of all values in the collection. The implicit comparator is used. * @return The minimum element of the collection */ public final T min() { pa.min() } /** * Finds in parallel the minimum of all values in the collection. The supplied comparator is used. * If the supplied closure takes two arguments it is used directly as a comparator. * If the supplied closure takes one argument, the values returned by the supplied closure for individual elements are used for comparison by the implicit comparator. * @param cl A one or two-argument closure * @return The minimum element of the collection */ public final T min(Closure cl) { return pa.min(GParsPoolUtil.createComparator(cl) as Comparator) } /** * Finds in parallel the maximum of all values in the collection. The implicit comparator is used. * @return The maximum element of the collection */ public final T max() { pa.max() } /** * Finds in parallel the maximum of all values in the collection. The supplied comparator is used. * If the supplied closure takes two arguments it is used directly as a comparator. * If the supplied closure takes one argument, the values returned by the supplied closure for individual elements are used for comparison by the implicit comparator. * @param cl A one or two-argument closure * @return The maximum element of the collection */ public final T max(Closure cl) { pa.max(GParsPoolUtil.createComparator(cl) as Comparator) } /** * Applies concurrently the supplied function to all elements in the collection, returning a collection containing * the transformed values. * @param A closure calculating a transformed value from the original one * @return A collection holding the new values */ public final AbstractPAWrapper map(Closure cl) { new MappedPAWrapper(pa.withMapping({cl(it)} as Mapper)) } /** * Filters concurrently elements in the collection based on the outcome of the supplied function on each of the elements. * @param A closure indicating whether to propagate the given element into the filtered collection * @return A collection holding the allowed values */ public abstract AbstractPAWrapper filter(Closure cl) } /** * The default ParallelArray wrapper class */ final class PAWrapper extends AbstractPAWrapper { def PAWrapper(final pa) { super(pa) } /** * Filters concurrently elements in the collection based on the outcome of the supplied function on each of the elements. * @param A closure indicating whether to propagate the given element into the filtered collection * @return A collection holding the allowed values */ public PAWrapper filter(Closure cl) { new PAWrapper(pa.withFilter({cl(it)} as Predicate).all()) } } /** * The ParallelArray wrapper used after the map() operation */ final class MappedPAWrapper extends AbstractPAWrapper { def MappedPAWrapper(final ParallelArray.WithMapping pa) { super(pa) } /** * Filters concurrently elements in the collection based on the outcome of the supplied function on each of the elements. * @param A closure indicating whether to propagate the given element into the filtered collection * @return A collection holding the allowed values */ public PAWrapper filter(Closure cl) { new PAWrapper(pa.all().withFilter({cl(it)} as Predicate).all()) } } libgpars-groovy-java-0.10.orig/META-INF/0000755000000000000000000000000011347765306014500 5ustar libgpars-groovy-java-0.10.orig/META-INF/LICENSE.txt0000644000000000000000000000146711347765306016333 0ustar /*** * GPars (formerly GParallelizer): a groovy concurrency library. * It provides support for configuring parallel system using Groovy * The project resides at http://gpars.codehaus.org */ /* * Copyright (c) 2008, 2009 Vaclav Pech, vaclav.pech@seznam.cz * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ libgpars-groovy-java-0.10.orig/META-INF/LICENSE_JUnit.txt0000644000000000000000000000271211347765306017436 0ustar BSD License Copyright (c) 2000-2006, www.hamcrest.org All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of Hamcrest nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. libgpars-groovy-java-0.10.orig/META-INF/ReleaseNotest.txt0000644000000000000000000001505011374457760020021 0ustar GPars (formerly GParallelizer) 0.10 Check out the JIRA release notes at http://jira.codehaus.org/secure/ReleaseNote.jspa?projectId=12030&version=15793 Project changes See http://gpars.codehaus.org/Breaking+Changes for the list of breaking changes. Parallel collections * Renamed the Parallelizer and Asynchronizer classes to more appropriate GParsPool and GParsExecutorsPool as well as their methods * Enabled asynchronous closures inside the GParsPool.withPool() methods * Reorganized the asynchronous closure invocation functionality * Unified the GParsPool and GParsExecutorsPool functionality to eliminate the need to combine uses of the two classes * Improved the map/reduce performance by eliminating unnecessary conversions * Seed values are now allowed for fold() and reduce() methods * Added findAnyParallel() and countParallel() methods Fork / Join * Simplified API to define Fork/Join calculation without the need to create explicit subclasses Actors * Restructured actor grouping in order to unify it with agent and dataflow task grouping * The implicit _call()_ method can be used to send messages GroovyCSP * Added a JCSP-wrapping CSP implementation Dataflow * A _maxForks_ flag has been added to allow Dataflow operators to internally work concurrently * Added support for grouping operators and tasks around shared thread pools Safe * Reimplemented to increase performance * Added support for grouping Safe instances around shared thread pools * Added agent error handling capabilities * Renamed to *Agent* * The implicit _call()_ method can be used to update the agent Other * Dependency on Jetty has been made optional * Automated upload of downloadable artifacts * OSGi support for the GPars jar 0.9 Check out the JIRA release notes at http://jira.codehaus.org/secure/ReleaseNote.jspa?projectId=12030&version=15702 Project changes * Moved to Codehaus - http://gpars.codehaus.org * Provided a User Guide - http://www.gpars.org/guide/index.html * Changed the package structure * Fully built using Gradle * Continually built on JetBrains public TeamCity site (http://teamcity.jetbrains.com/) and on Codehaus Bamboo (http://bamboo.ci.codehaus.org/browse/GPARS-DEF) * Experimental OSGi support Parallel collections * Map/Reduce * Transparently parallel methods added allowing to change the sequential semantics of the usual each(), collect() and such methods to a concurrent one * Parallel methods renamed from xxxAsync to xxxParallel to better capture the nature of the methods. E. g. eachAsync() is now eachParallel(). * New parallel methods added - groupByParallel(), minParallel(), maxParallel(), sumParallel(), foldParallel(), grepParallel() * The allParallel() method renamed to everyParallel() * The withParallelizer() and withAsynchronizer() methods have been renamed to doParallel() Actors * No need to start actors explicitly after calling the _actor()_ factory method * Enabled receive() for blocking message read in event-driven actors * Removed thread-bound actors * Created a DSL to add message handlers to DynamicDispatchActor at construction time * The sendAndContinue() method * Performance improvements * Reorganized daemon and non-daemon actor groups * Resizeable thread-pool used by the default actor group * Modified the reply mechanism * The message sender property has been added to messages Dataflow * Lightweight Dataflow Tasks added * Full-blown Dataflow Operators created * The DataFlows class added to provide a convenient container for dataflow variables indexed by either a name or a number * Bound handlers through the >> operator - register closures, which will get invoked once the dataflow variable gets bound to a value Safe * An await() method added to allow callers to synchronize with the agent * Higher reader priority supported Other * Levering GroovyDSL API in IntelliJ IDEA to get IDE support for GPars DSLs * Added Fork / Join convenience abstraction for hierarchical (divide and conquer) tasks 0.8.4 DataFlows Improved Gradle build Maintenance 0.8.3 Enabled Gradle builds Uploaded into a maven repository 0.8.2 Updated for groovy 1.6.4 Added the await() method to the SafeVariable class Added the instantVal property to the SafeVariable class to prioritize read requests 0.8.1 Added SafeVariable Migrated DataFlowStream to Java Fixed problem with nested actor creation closures Added short-hand methods for concurrent collection processing to Asynchronizer and Parallelizer 0.8 Added DataFlow concurrency support Added sendAndWait() methods to actors to block the caller until a reply arrives Added an experimental option to use the JSR-166y ForkJoin pool for actors Enabled thread-bound actors to reuse threads from a resizeable common pool Added AsyncEnhancer and ParallelEnhancer classes enabling asynchronous collection processing through meta-class enhancements Restructured actor groups with respect to the thread-bound actor thread reuse and Fork/Join pool support Supported @Immutable for messages Ability to join actors to await their termination Ability to suspend actor and message enhancements for replies, which has impact on message delivery speed Restructured actor classes to increase code reuse Removed the beforeStop() lifecycle method from actors Fixed the event-driven actor's loop, when no react is called DynamicDispatchActor added to allow for an alternative message handling syntax - dynamic method dispatch to multiple onMessage() methods Added a Reactor implementation - a special purpose actor, which after receiving a message runs its body with the message as a parameter and the result of the code is send in reply. Several performance benchmarks included Minor performance optimizations Bugfixing 0.7 Reply methods for thread-bound actors Reply methods available on received messages Ability to send replies between thread-bound and event-driven actors in both directions Documented structuring actors code and implementing event-driven loops Overloaded the << operator to perform send Handling multiple messages in single receive/react Actor groups, multiple independent configurable thread pools Gradle build script 0.6 Event-driven (pooled) actors 0.5 Mixin support The act() method wrapped with TimeCategory to allow for time DSL in receive() calls 0.4 Actors added 0.3 Set default pool size to Ncpu + 1, where Ncpu is the number of CPU in the system. Made pool threads to be non-daemon. Updated documentation. 0.2 Enabled calling withParallelizer() and withAsynchronizer() methods on any object. 0.1 Initial release of the core functionality for both Parallelizer, which uses JSR-166y Parallel Arrays, and Asynchronizer, which uses Java's executor services. libgpars-groovy-java-0.10.orig/META-INF/README0000644000000000000000000000041411347765306015357 0ustar *GPars* (formerly *GParallelizer*) allows Groovy code to easily handle tasks concurrently and asynchronously, leveraging either the JSR-166y _Parallel Arrays_ or Java's executor services. Please visit the project site for more information - http://gpars.codehaus.org libgpars-groovy-java-0.10.orig/META-INF/NOTICE.txt0000644000000000000000000000227611347765306016231 0ustar GPars (formerly GParallelizer) Copyright 2008 - 2009 Vaclav Pech and the original author or authors This product includes software developed by Vaclav Pech (http://www.linkedin.com/in/vaclavpech) This product is licensed to you under the Apache License, version 2.0 (the "License"); you may not use this product except in compliance with the License. You may obtain a copy of the License at: http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. This product optionally depends on the works by JSR-166 EG, Doug Lea, and Jason T. Greene: * LICENSE: * licenses/LICENSE.jsr166y.txt (Public Domain) * HOMEPAGE: * http://gee.cs.oswego.edu/cgi-bin/viewcvs.cgi/jsr166/ This product optionally depends on The Netty Project by Red Hat, Inc. * LICENSE: * licenses/LICENSE-netty.txt (Apache 2 license) * DEPENDENCIES: * licenses/NOTICE-netty.txt * HOMEPAGE: * http://www.jboss.org/netty/