[m-rev.] for review: Make MercuryThreadPool notice when a thread blocks on a sempahore.
Peter Wang
novalazy at gmail.com
Fri Aug 1 16:14:02 AEST 2014
Hi Paul,
On Thu, 17 Jul 2014 13:52:56 +1000, Paul Bone <paul at bone.id.au> wrote:
>
> Make MercuryThreadPool notice when a thread blocks on a sempahore.
>
semaphore
> diff --git a/java/runtime/Semaphore.java b/java/runtime/Semaphore.java
> new file mode 100644
> index 0000000..823a919
> --- /dev/null
> +++ b/java/runtime/Semaphore.java
> @@ -0,0 +1,150 @@
> +//
> +// Copyright (C) 2014 The Mercury Team
> +// This file may only be copied under the terms of the GNU Library General
> +// Public License - see the file COPYING.LIB in the Mercury distribution.
> +//
> +
> +package jmercury.runtime;
> +
> +import java.util.concurrent.TimeUnit;
> +
> +
> +public class Semaphore
> + extends java.util.concurrent.Semaphore
> +{
> + public Semaphore(int permits, boolean fair)
> + {
> + super(permits, fair);
> + }
> +
> + public Semaphore(int permits)
> + {
> + super(permits);
> + }
> +
> + public void aquire()
> + throws InterruptedException
> + {
> + aquire(1);
> + }
"acquire" (multiple instances in this file)
> +
> + public void aquire(int permits)
> + throws InterruptedException
> + {
> + boolean blocked = false;
> +
> + try {
> + if (tryAcquire(permits, 0, TimeUnit.SECONDS)) {
> + return;
> + } else {
> + // This thread will (probably) block.
> + blocked();
> + blocked = true;
> + super.acquire(permits);
> + }
> + } finally {
> + if (blocked) {
> + running();
> + // The thread isn't blocked anymore.
> + }
> + }
> + }
> +
> + public void aquireUninterruptably()
> + {
> + aquireUninterruptably(1);
> + }
> +
> + public void aquireUninterruptably(int permits)
> + {
> + boolean blocked = false;
> + boolean interrupted_once = false;
> + boolean not_interrupted_once = false;
> + boolean success;
Why both interrupted_once and not_interrupted_once?
> +
> + // Avoid a warning with the loop below
> + success = false;
> +
> + /*
> + * tryAcquire is interruptable so we keep trying until we've
> + * executed it at least once and it was not interrupted. We also
> + * track if we were interrupted so we can raise this condition
> + * again.
> + */
> + do {
> + try {
> + success = tryAcquire(permits, 0, TimeUnit.SECONDS);
> + not_interrupted_once = true;
> + } catch (InterruptedException e) {
> + interrupted_once = true;
> + }
> + } while (not_interrupted_once);
> +
> + if (!success) {
> + // This thread will (probably) block because tryAcquire failed.
> + blocked();
> + blocked = true;
> + super.acquireUninterruptibly(permits);
> + }
> + if (blocked) {
> + running();
> + // The thread isn't blocked anymore.
> + }
> +
> + if (interrupted_once) {
> + // Raise the interrupted condition.
> + Thread.currentThread().interrupt();
> + }
> + }
> +
> + public boolean tryAcquire(long timeout, TimeUnit unit)
> + throws InterruptedException
> + {
> + return tryAcquire(1, timeout, unit);
> + }
> +
> + public boolean tryAcquire(int permits, long timeout, TimeUnit unit)
> + throws InterruptedException
> + {
> + if (timeout < 1) {
> + return super.tryAcquire(permits, timeout, unit);
> + } else {
> + boolean result;
> +
> + result = tryAcquire(permits, 0, unit);
> + if (result) {
> + // Blocking wasn't necessary
> + return true;
> + } else {
> + // Block.
> + blocked();
The comment should be something like "Blocking required; notify thread."
or something.
Otherwise, looks fine.
Peter
More information about the reviews
mailing list