[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