diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRContext.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRContext.java index c59f4dbc43c325a0046106d0e04140d1123b77f4..3594b6ceaaeb548248103ca47531d29805e995b6 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRContext.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRContext.java @@ -98,7 +98,7 @@ public class FastRContext { private static void handleSharedContexts(ContextKind contextKind) { if (contextKind == ContextKind.SHARE_ALL) { RContext current = RContext.getInstance(); - if (EvalThread.threads.size() == 0 && (current.isInitial() || current.getKind() == ContextKind.SHARE_PARENT_RW)) { + if (EvalThread.threadCnt.get() == 0 && (current.isInitial() || current.getKind() == ContextKind.SHARE_PARENT_RW)) { ContextInfo.resetMultiSlotIndexGenerator(); } else { throw RError.error(RError.NO_CALLER, RError.Message.GENERIC, "Shared contexts can be created only if no other child contexts exist"); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/parallel/R/forkcluster_overrides.R b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/parallel/R/forkcluster_overrides.R index 2d3ebf6b49a58ea052b43953b3c3e1c47aaaad39..02940b6a2aa6d27bf3fc7b34d79558e58f26a8c3 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/parallel/R/forkcluster_overrides.R +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/parallel/R/forkcluster_overrides.R @@ -111,4 +111,10 @@ stopCluster.SHAREDcluster <- function(cl) { } } +## manually register S3 generic methods +registerS3method("closeNode", "SHAREDnode", closeNode.SHAREDnode) +registerS3method("sendData", "SHAREDnode", sendData.SHAREDnode) +registerS3method("recvData", "SHAREDnode", recvData.SHAREDnode) +registerS3method("recvOneData", "SHAREDcluster", recvOneData.SHAREDcluster) +registerS3method("stopCluster", "SHAREDcluster", stopCluster.SHAREDcluster) }), asNamespace("parallel")) diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RContext.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RContext.java index 6db41563e21d115917b36d7547b5d516fac846df..e49f250dae488b0679e9becaf528227aef5af405 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RContext.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RContext.java @@ -31,6 +31,7 @@ import java.util.TimeZone; import java.util.WeakHashMap; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Semaphore; +import java.util.concurrent.atomic.AtomicInteger; import com.oracle.truffle.api.Assumption; import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; @@ -228,10 +229,14 @@ public final class RContext extends com.oracle.truffle.api.ExecutionContext impl public static final Map<Integer, Thread> threads = new ConcurrentHashMap<>(); + /** We use a separate counter for threads since ConcurrentHashMap.size() is not reliable. */ + public static final AtomicInteger threadCnt = new AtomicInteger(0); + public EvalThread(ContextInfo info, Source source) { super(null); this.info = info; this.source = source; + threadCnt.incrementAndGet(); threads.put(info.getId(), this); } @@ -249,6 +254,7 @@ public final class RContext extends com.oracle.truffle.api.ExecutionContext impl } finally { vm.dispose(); threads.remove(info.getId()); + threadCnt.decrementAndGet(); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test index 2f07a8789035dd04cf68d29ec1a29afd61c1e621..c03ce21ab0cb9070e7d00e468c82274b27f1c870 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test @@ -79135,6 +79135,42 @@ Error in get("x") : object 'x' not found #{ pi/180; pi } [1] 3.141593 +##com.oracle.truffle.r.test.library.base.TestSharedCluster.testSharedCluster# +#fun <- function(data) { cl <- makeCluster(1, 'SHARED'); parLapply(cl, data, function(x) x+1); stopCluster(cl) }; fun(1:100) +Error in fun(1:100) : could not find function "makeCluster" + +##com.oracle.truffle.r.test.library.base.TestSharedCluster.testSharedCluster# +#fun <- function(data) { cl <- makeCluster(2, 'SHARED'); parLapply(cl, data, function(x) x+1); stopCluster(cl) }; fun(1:100) +Error in fun(1:100) : could not find function "makeCluster" + +##com.oracle.truffle.r.test.library.base.TestSharedCluster.testSharedCluster# +#fun <- function(data) { cl <- makeCluster(3, 'SHARED'); parLapply(cl, data, function(x) x+1); stopCluster(cl) }; fun(1:100) +Error in fun(1:100) : could not find function "makeCluster" + +##com.oracle.truffle.r.test.library.base.TestSharedCluster.testSharedCluster# +#fun <- function(data) { cl <- makeCluster(4, 'SHARED'); parLapply(cl, data, function(x) x+1); stopCluster(cl) }; fun(1:100) +Error in fun(1:100) : could not find function "makeCluster" + +##com.oracle.truffle.r.test.library.base.TestSharedCluster.testSharedCluster# +#fun <- function(data) { cl <- makeCluster(5, 'SHARED'); parLapply(cl, data, function(x) x+1); stopCluster(cl) }; fun(1:100) +Error in fun(1:100) : could not find function "makeCluster" + +##com.oracle.truffle.r.test.library.base.TestSharedCluster.testSharedCluster# +#fun <- function(data) { cl <- makeCluster(6, 'SHARED'); parLapply(cl, data, function(x) x+1); stopCluster(cl) }; fun(1:100) +Error in fun(1:100) : could not find function "makeCluster" + +##com.oracle.truffle.r.test.library.base.TestSharedCluster.testSharedCluster# +#fun <- function(data) { cl <- makeCluster(7, 'SHARED'); parLapply(cl, data, function(x) x+1); stopCluster(cl) }; fun(1:100) +Error in fun(1:100) : could not find function "makeCluster" + +##com.oracle.truffle.r.test.library.base.TestSharedCluster.testSharedCluster# +#fun <- function(data) { cl <- makeCluster(8, 'SHARED'); parLapply(cl, data, function(x) x+1); stopCluster(cl) }; fun(1:100) +Error in fun(1:100) : could not find function "makeCluster" + +##com.oracle.truffle.r.test.library.base.TestSharedCluster.testSharedCluster# +#fun <- function(data) { cl <- makeCluster(9, 'SHARED'); parLapply(cl, data, function(x) x+1); stopCluster(cl) }; fun(1:100) +Error in fun(1:100) : could not find function "makeCluster" + ##com.oracle.truffle.r.test.library.base.TestSimpleArithmetic.testArithmeticUpdate# #{ x <- 3 ; f <- function(z) { if (z) { x <- 1 } ; x <- 1L + x ; x } ; f(FALSE) } [1] 4 diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSharedCluster.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSharedCluster.java new file mode 100644 index 0000000000000000000000000000000000000000..22c14a3b209d3193f91d206d4f692c246a569823 --- /dev/null +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSharedCluster.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.r.test.library.base; + +import org.junit.Test; + +import com.oracle.truffle.r.test.TestBase; + +// Checkstyle: stop line length check +public class TestSharedCluster extends TestBase { + + @Test + public void testSharedCluster() { + assertEval(TestBase.template("fun <- function(data) { cl <- makeCluster(%0, 'SHARED'); parLapply(cl, data, function(x) x+1); stopCluster(cl) }; fun(1:100)", "123456789".split(""))); + } + +}