Skip to content

Commit

Permalink
Throw ApfloatInterruptedException if the executing thread is interrupted
Browse files Browse the repository at this point in the history
  • Loading branch information
mtommila committed Mar 28, 2024
1 parent a4a5064 commit 5f60a87
Show file tree
Hide file tree
Showing 13 changed files with 301 additions and 96 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* MIT License
*
* Copyright (c) 2002-2023 Mikko Tommila
* Copyright (c) 2002-2024 Mikko Tommila
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
Expand All @@ -23,9 +23,9 @@
*/
package org.apfloat.samples;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;
import java.util.concurrent.ExecutionException;

import org.apfloat.ApfloatContext;
Expand All @@ -35,7 +35,7 @@
* The operation is executed using the ExecutorService retrieved from
* {@link ApfloatContext#getExecutorService()}.
*
* @version 1.9.0
* @version 1.14.0
* @author Mikko Tommila
*/

Expand All @@ -52,9 +52,10 @@ public BackgroundOperation(Operation<T> operation)
{
ApfloatContext ctx = ApfloatContext.getContext();
ExecutorService executorService = ctx.getExecutorService();
Callable<T> callable = () -> operation.execute();
FutureTask<T> futureTask = new FutureTask<>(operation::execute);
executorService.execute(futureTask);

this.future = executorService.submit(callable);
this.future = futureTask;
}

/**
Expand All @@ -68,6 +69,17 @@ public boolean isFinished()
return this.future.isDone();
}

/**
* Cancel the operation by interrupting the thread executing it.
*
* @since 1.14.0
*/

public void cancel()
{
this.future.cancel(true);
}

/**
* Get the result of the operation.
* This method blocks until the operation has been completed.
Expand Down
54 changes: 2 additions & 52 deletions apfloat-samples/src/main/java/org/apfloat/samples/Pi.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* MIT License
*
* Copyright (c) 2002-2023 Mikko Tommila
* Copyright (c) 2002-2024 Mikko Tommila
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
Expand Down Expand Up @@ -36,7 +36,7 @@
/**
* Calculates pi using four different algorithms.
*
* @version 1.8.2
* @version 1.14.0
* @author Mikko Tommila
*/

Expand Down Expand Up @@ -330,8 +330,6 @@ public BinarySplittingPiCalculator(BinarySplittingSeries series)
public void r(long n1, long n2, ApfloatHolder T, ApfloatHolder Q, ApfloatHolder P, BinarySplittingProgressIndicator progressIndicator)
throws ApfloatRuntimeException
{
checkAlive();

assert (n1 != n2);
long length = n2 - n1;

Expand Down Expand Up @@ -449,9 +447,7 @@ public Apfloat execute()
time = System.currentTimeMillis();
Apfloat t = T.getApfloat(),
q = Q.getApfloat();
checkAlive();
Apfloat factor = ApfloatMath.inverseRoot(new Apfloat(1823176476672000L, this.precision, this.radix), 2);
checkAlive();
Apfloat pi = ApfloatMath.inverseRoot(factor.multiply(t), 1).multiply(q);
time = System.currentTimeMillis() - time;

Expand Down Expand Up @@ -529,9 +525,7 @@ public Apfloat execute()
time = System.currentTimeMillis();
Apfloat t = T.getApfloat(),
q = Q.getApfloat();
checkAlive();
Apfloat factor = ApfloatMath.inverseRoot(new Apfloat(8, this.precision, this.radix), 2);
checkAlive();
Apfloat pi = ApfloatMath.inverseRoot(t, 1).multiply(factor).multiply(new Apfloat(9801, Apfloat.INFINITE, this.radix)).multiply(q);
time = System.currentTimeMillis() - time;

Expand Down Expand Up @@ -691,29 +685,22 @@ public Apfloat execute()

for (int i = 0; i < iterations; i++)
{
checkAlive();

Pi.err.printf("Iteration " + (i + 1) + " ");

time = System.currentTimeMillis();

Apfloat tmp = a;
a = a.add(b).divide(two);
checkAlive();
b = tmp.multiply(b);
checkAlive();
b = ApfloatMath.sqrt(b);

checkAlive();
t = t.subtract(new Apfloat(1L << i, this.precision, this.radix).multiply(ApfloatMath.pow(tmp.subtract(a), 2)));

time = System.currentTimeMillis() - time;

Pi.err.println("took " + time / 1000.0 + " seconds");
}

checkAlive();

Pi.err.printf("Final value ");

time = System.currentTimeMillis();
Expand Down Expand Up @@ -791,34 +778,25 @@ public Apfloat execute()

for (int i = 0; i < iterations; i++)
{
checkAlive();

Pi.err.printf("Iteration " + (i + 1) + " ");

time = System.currentTimeMillis();

Apfloat tmp = ApfloatMath.pow(y, 4);
y = one.subtract(tmp);
checkAlive();
y = ApfloatMath.inverseRoot(y, 4);
checkAlive();
y = y.subtract(one).divide(y.add(one));

checkAlive();
tmp = ApfloatMath.pow(y.add(one), 2);
checkAlive();
a = a.multiply(tmp).multiply(tmp);

checkAlive();
a = a.subtract(new Apfloat(1L << (2 * i + 3), this.precision, this.radix).multiply(y).multiply(tmp.subtract(y)));

time = System.currentTimeMillis() - time;

Pi.err.println("took " + time / 1000.0 + " seconds");
}

checkAlive();

Pi.err.printf("Final value ");

time = System.currentTimeMillis();
Expand Down Expand Up @@ -1004,17 +982,6 @@ public static PrintWriter getErr()
return Pi.err;
}

/**
* Set whether the program should stop executing.
*
* @param isAlive <code>true</code> to keep running the program, <code>false</code> to stop.
*/

public static void setAlive(boolean isAlive)
{
Pi.isAlive = isAlive;
}

Pi()
{
}
Expand Down Expand Up @@ -1069,20 +1036,6 @@ public static void main(String[] args)
run(precision, radix, operation);
}

/**
* Check whether the program should stop executing.
*
* @exception ThreadDeath in case {@link #setAlive(boolean)} has been set to <code>false</code>.
*/

protected static void checkAlive()
{
if (!Pi.isAlive)
{
throw new ThreadDeath();
}
}

/**
* Output stream for the result printout.
*/
Expand All @@ -1094,7 +1047,4 @@ protected static void checkAlive()
*/

protected static PrintWriter err;

// Interactive execution stop check
private static volatile boolean isAlive = true;
}
10 changes: 5 additions & 5 deletions apfloat-samples/src/main/java/org/apfloat/samples/PiAWT.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* MIT License
*
* Copyright (c) 2002-2023 Mikko Tommila
* Copyright (c) 2002-2024 Mikko Tommila
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
Expand Down Expand Up @@ -45,13 +45,14 @@

import org.apfloat.Apfloat;
import org.apfloat.ApfloatContext;
import org.apfloat.ApfloatInterruptedException;
import org.apfloat.ApfloatRuntimeException;
import org.apfloat.spi.BuilderFactory;

/**
* Graphical AWT elements for calculating pi using four different algorithms.
*
* @version 1.9.1
* @version 1.14.0
* @author Mikko Tommila
*/

Expand Down Expand Up @@ -384,7 +385,7 @@ public void run()
{
Pi.run(precision, radix, operation);
}
catch (ThreadDeath td)
catch (ApfloatInterruptedException aie)
{
aborted();
}
Expand All @@ -403,14 +404,13 @@ public void run()
}
};

Pi.setAlive(true);
this.calculatorThread.start();
this.abortButton.setEnabled(true);
}

private void stopThread()
{
Pi.setAlive(false);
this.calculatorThread.interrupt();
}

private void aborted()
Expand Down
22 changes: 14 additions & 8 deletions apfloat-samples/src/main/java/org/apfloat/samples/PiParallel.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* MIT License
*
* Copyright (c) 2002-2023 Mikko Tommila
* Copyright (c) 2002-2024 Mikko Tommila
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
Expand All @@ -28,6 +28,7 @@

import org.apfloat.Apfloat;
import org.apfloat.ApfloatContext;
import org.apfloat.ApfloatInterruptedException;
import org.apfloat.ApfloatRuntimeException;

/**
Expand All @@ -40,7 +41,7 @@
* execute just one thread and divide its time to multiple
* simulated threads.
*
* @version 1.9.0
* @version 1.14.0
* @author Mikko Tommila
*/

Expand Down Expand Up @@ -71,8 +72,6 @@ public ParallelBinarySplittingPiCalculator(BinarySplittingSeries series)
public void r(long n1, long n2, ApfloatHolder T, ApfloatHolder Q, ApfloatHolder P, BinarySplittingProgressIndicator progressIndicator)
throws ApfloatRuntimeException
{
checkAlive();

ApfloatContext ctx = ApfloatContext.getContext();
int numberOfProcessors = ctx.getNumberOfProcessors();

Expand Down Expand Up @@ -123,8 +122,17 @@ else if (numberOfProcessors == 1)
};

BackgroundOperation<?> backgroundOperation = new BackgroundOperation<>(new ThreadLimitedOperation<>(operation1, numberOfProcessors1));
Operation<?> directOperation = () -> {
operation2.execute();
Operation<?> directOperation = () ->
{
try
{
operation2.execute();
}
catch (ApfloatInterruptedException aie)
{
backgroundOperation.cancel();
throw aie;
}
return backgroundOperation.getResult(); // Waits for the background operation to complete, must be run within the thread-limited context
};
new ThreadLimitedOperation<>(directOperation, numberOfProcessors2).execute();
Expand Down Expand Up @@ -301,8 +309,6 @@ public ThreadLimitedOperation(Operation<T> operation, int numberOfProcessors)
@Override
public T execute()
{
checkAlive();

ApfloatContext threadCtx = ApfloatContext.getThreadContext();
ApfloatContext ctx = (ApfloatContext) ApfloatContext.getContext().clone();
ctx.setNumberOfProcessors(this.numberOfProcessors);
Expand Down
25 changes: 23 additions & 2 deletions apfloat/src/main/java/org/apfloat/ApfloatContext.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* MIT License
*
* Copyright (c) 2002-2023 Mikko Tommila
* Copyright (c) 2002-2024 Mikko Tommila
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
Expand Down Expand Up @@ -192,7 +192,7 @@
* If these features are added to the Java platform in the future, they
* may be added to the <code>ApfloatContext</code> API as well.
*
* @version 1.9.1
* @version 1.14.0
* @author Mikko Tommila
*/

Expand Down Expand Up @@ -345,6 +345,8 @@ public ApfloatContext(Properties properties)

public static ApfloatContext getContext()
{
checkInterrupted();

ApfloatContext ctx = getThreadContext();

if (ctx == null)
Expand Down Expand Up @@ -1136,6 +1138,25 @@ public void wait(Future<?> future)
getBuilderFactory().getExecutionBuilder().createExecution().wait(future);
}

/**
* Checks if the current thread was interrupted. If yes, throws an
* {@link ApfloatInterruptedException}.<p>
*
* This method calls {@link Thread#interrupted()} so if the thread was
* interrupted, it clears the interrupted status.
*
* @throws ApfloatInterruptedException If the current thread was interrupted.
*/

public static void checkInterrupted()
throws ApfloatInterruptedException
{
if (Thread.interrupted())
{
throw new ApfloatInterruptedException();
}
}

/**
* Get an arbitrary object as an attribute for this ApfloatContext.
*
Expand Down
Loading

0 comments on commit 5f60a87

Please sign in to comment.