Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2467d47f authored by Hans Boehm's avatar Hans Boehm Committed by Android Git Automerger
Browse files

am 52572f4e: am 2a3b06bd: am 51f5acc6: am 82e5a2f6: Avoid starting long...

am 52572f4e: am 2a3b06bd: am 51f5acc6: am 82e5a2f6: Avoid starting long uninterruptible computations

* commit '52572f4e':
  Avoid starting long uninterruptible computations
parents 24a929d7 52572f4e
Loading
Loading
Loading
Loading
+11 −0
Original line number Original line Diff line number Diff line
@@ -87,6 +87,11 @@ public class BoundedRational {
        return CR.valueOf(mNum).divide(CR.valueOf(mDen));
        return CR.valueOf(mNum).divide(CR.valueOf(mDen));
    }
    }


    // Approximate number of bits to left of binary point.
    public int wholeNumberBits() {
        return mNum.bitLength() - mDen.bitLength();
    }

    private boolean tooBig() {
    private boolean tooBig() {
        if (mDen.equals(BigInteger.ONE)) return false;
        if (mDen.equals(BigInteger.ONE)) return false;
        return (mNum.bitLength() + mDen.bitLength() > MAX_SIZE);
        return (mNum.bitLength() + mDen.bitLength() > MAX_SIZE);
@@ -418,6 +423,9 @@ public class BoundedRational {
        // This algorithm is very naive, but we doubt it matters.
        // This algorithm is very naive, but we doubt it matters.
        long count = 0;
        long count = 0;
        while (n.mod(BigInteger.TEN).equals(BigInteger.ZERO)) {
        while (n.mod(BigInteger.TEN).equals(BigInteger.ZERO)) {
            if (Thread.interrupted()) {
                throw new CR.AbortedException();
            }
            n = n.divide(BigInteger.TEN);
            n = n.divide(BigInteger.TEN);
            ++count;
            ++count;
        }
        }
@@ -502,6 +510,9 @@ public class BoundedRational {
        if (r.mDen.equals(BigInteger.ONE)) return 0;
        if (r.mDen.equals(BigInteger.ONE)) return 0;
        r = r.reduce();
        r = r.reduce();
        BigInteger den = r.mDen;
        BigInteger den = r.mDen;
        if (den.bitLength() > MAX_SIZE) {
            return Integer.MAX_VALUE;
        }
        while (!den.testBit(0)) {
        while (!den.testBit(0)) {
            ++powers_of_two;
            ++powers_of_two;
            den = den.shiftRight(1);
            den = den.shiftRight(1);
+35 −14
Original line number Original line Diff line number Diff line
@@ -302,7 +302,7 @@ class Evaluator {
            .show();
            .show();
    }
    }


    private final long MAX_TIMEOUT = 60000;
    private final long MAX_TIMEOUT = 15000;
                                   // Milliseconds.
                                   // Milliseconds.
                                   // Longer is unlikely to help unless
                                   // Longer is unlikely to help unless
                                   // we get more heap space.
                                   // we get more heap space.
@@ -314,11 +314,12 @@ class Evaluator {
                                   // calculator is restarted.
                                   // calculator is restarted.
                                   // We'll call that a feature; others
                                   // We'll call that a feature; others
                                   // might argue it's a bug.
                                   // might argue it's a bug.
    private final long mQuickTimeout = 1500;
    private final long QUICK_TIMEOUT = 1000;
                                   // Timeout for unrequested, speculative
                                   // Timeout for unrequested, speculative
                                   // evaluations, in milliseconds.
                                   // evaluations, in milliseconds.
                                   // Could be shorter with a faster asin()
    private int mMaxResultBits = 120000;             // Don't try to display a larger result.
                                   // implementation.
    private final int MAX_MAX_RESULT_BITS = 350000;  // Long timeout version.
    private final int QUICK_MAX_RESULT_BITS = 50000; // Instant result version.


    private void displayTimeoutMessage() {
    private void displayTimeoutMessage() {
        final AlertDialog.Builder builder = new AlertDialog.Builder(mCalculator)
        final AlertDialog.Builder builder = new AlertDialog.Builder(mCalculator)
@@ -329,6 +330,7 @@ class Evaluator {
                    new DialogInterface.OnClickListener() {
                    new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface d, int which) {
                        public void onClick(DialogInterface d, int which) {
                            mTimeout = MAX_TIMEOUT;
                            mTimeout = MAX_TIMEOUT;
                            mMaxResultBits = MAX_MAX_RESULT_BITS;
                        }
                        }
                    });
                    });
        }
        }
@@ -368,8 +370,7 @@ class Evaluator {
        }
        }
        @Override
        @Override
        protected void onPreExecute() {
        protected void onPreExecute() {
            long timeout = mRequired ? mTimeout : mQuickTimeout;
            long timeout = mRequired ? mTimeout : QUICK_TIMEOUT;
            if (timeout != 0) {
            mTimeoutRunnable = new Runnable() {
            mTimeoutRunnable = new Runnable() {
                @Override
                @Override
                public void run() {
                public void run() {
@@ -378,11 +379,22 @@ class Evaluator {
            };
            };
            mTimeoutHandler.postDelayed(mTimeoutRunnable, timeout);
            mTimeoutHandler.postDelayed(mTimeoutRunnable, timeout);
        }
        }
        private boolean isTooBig(CalculatorExpr.EvalResult res) {
            int maxBits = mRequired ? mMaxResultBits : QUICK_MAX_RESULT_BITS;
            if (res.mRatVal != null) {
                return res.mRatVal.wholeNumberBits() > maxBits;
            } else {
                return res.mVal.get_appr(maxBits).bitLength() > 2;
            }
        }
        }
        @Override
        @Override
        protected InitialResult doInBackground(Void... nothing) {
        protected InitialResult doInBackground(Void... nothing) {
            try {
            try {
                CalculatorExpr.EvalResult res = mExpr.eval(mDm);
                CalculatorExpr.EvalResult res = mExpr.eval(mDm);
                if (isTooBig(res)) {
                    // Avoid starting a long uninterruptible decimal conversion.
                    return new InitialResult(R.string.timeout);
                }
                int prec = INIT_PREC;
                int prec = INIT_PREC;
                String initCache = res.mVal.toString(prec);
                String initCache = res.mVal.toString(prec);
                int msd = getMsdPos(initCache);
                int msd = getMsdPos(initCache);
@@ -422,7 +434,14 @@ class Evaluator {
            mEvaluator = null;
            mEvaluator = null;
            mTimeoutHandler.removeCallbacks(mTimeoutRunnable);
            mTimeoutHandler.removeCallbacks(mTimeoutRunnable);
            if (result.isError()) {
            if (result.isError()) {
                if (result.mErrorResourceId == R.string.timeout) {
                    if (mRequired) {
                        displayTimeoutMessage();
                    }
                    mCalculator.onCancelled();
                } else {
                    mCalculator.onError(result.mErrorResourceId);
                    mCalculator.onError(result.mErrorResourceId);
                }
                return;
                return;
            }
            }
            mVal = result.mVal;
            mVal = result.mVal;
@@ -453,6 +472,8 @@ class Evaluator {
        }
        }
        @Override
        @Override
        protected void onCancelled(InitialResult result) {
        protected void onCancelled(InitialResult result) {
            // Invoker resets mEvaluator.
            mTimeoutHandler.removeCallbacks(mTimeoutRunnable);
            if (mRequired && !mQuiet) {
            if (mRequired && !mQuiet) {
                displayCancelledMessage();
                displayCancelledMessage();
            } // Otherwise timeout processing displayed message.
            } // Otherwise timeout processing displayed message.