[ https://issues.apache.org/jira/browse/JENA-1090?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15369638#comment-15369638 ]
ASF GitHub Bot commented on JENA-1090: -------------------------------------- Github user ajs6f commented on a diff in the pull request: https://github.com/apache/jena/pull/153#discussion_r70181662 --- Diff: jena-arq/src/main/java/org/apache/jena/system/ThreadTxn.java --- @@ -0,0 +1,148 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.jena.system; + +import java.util.Objects ; +import java.util.concurrent.Executor ; +import java.util.concurrent.Executors ; +import java.util.concurrent.Semaphore ; +import java.util.concurrent.atomic.AtomicReference ; + +import org.apache.jena.query.ReadWrite ; +import org.apache.jena.sparql.core.Transactional ; + +/** + * An action that will happen on a different thread later when {@link #run} is + * called. A thread is created and the transaction started during a call to the + * creation operations {@link #threadTxnRead} or {@link #threadTxnWrite}. + * The associated Runnable is called and the transaction completed when + * {@link #run} is called. Being on a thread, the state of the world the + * forked transaction sees is outside the creating thread which may itself be in a + * transaction. Warning: creating a write transaction inside a write transaction + * will cause deadlock. + */ +public class ThreadTxn { + // ---- Thread + + /** Create a thread-backed delayed READ transaction action. + * Call {@link ThreadTxn#run} to perform the read transaction. + */ + public static ThreadTxn threadTxnRead(Transactional trans, Runnable action) { + return ThreadTxn.create(trans, ReadWrite.READ, action, false) ; + } + + /** Create a thread-backed delayed WRITE action. + * Call {@link ThreadTxn#run} to perform the write transaction. + * (If called from inside a write transaction on the {@code trans}, + * this will deadlock.) + */ + public static ThreadTxn threadTxnWrite(Transactional trans, Runnable action) { + return ThreadTxn.create(trans, ReadWrite.WRITE, action, true) ; + } + + /** Create a thread-backed delayed WRITE-abort action (mainly for testing). */ + public static ThreadTxn threadTxnWriteAbort(Transactional trans, Runnable action) { + return ThreadTxn.create(trans, ReadWrite.WRITE, action, false) ; + } + + private final Semaphore semaStart ; + private final Semaphore semaFinish ; + private final AtomicReference<RuntimeException> thrownRuntimeException = new AtomicReference<>(null) ; + private final AtomicReference<Error> thrownError = new AtomicReference<>(null) ; + private final Runnable action ; + + private ThreadTxn(Runnable action) { + this.action = action ; + this.semaStart = new Semaphore(0, true) ; --- End diff -- I'm a little confused about the way these semaphores work. E.g. how do they function with 0 permits? Below, in `::run()` you release the start semaphore, but I can't see where you acquire it… on the theory (possibly a bad one) that other newbies will also find this opaque, can you comment this up a bit to explain the concurrency control at work here? > Add transaction handling convenience code > ----------------------------------------- > > Key: JENA-1090 > URL: https://issues.apache.org/jira/browse/JENA-1090 > Project: Apache Jena > Issue Type: Improvement > Components: ARQ > Reporter: Andy Seaborne > > The code > [Txn|https://github.com/afs/jena-rdfconnection/blob/master/src/main/java/rdfconnection/Txn.java] > provides a convenient way to write common patterns of transaction usage > including > {noformat} > Txn.executeWrite(conn, () ->{ > ... write transaction code ... > }) ; > {noformat} > which provides the pattern: > {noformat} > txn.begin(ReadWrite.WRITE) ; > try { > ... write transaction code ... > txn.commit() ; > } > finally { txn.end() ; } > {noformat} > {{Txn}} also checks for being in a transaction already. > There are forms to return a value from the code inside the transaction block > as well. -- This message was sent by Atlassian JIRA (v6.3.4#6332)