Skip to content

nf/nfc do not seem to be threadsafe and throw NullPointerException #984

Open
@multiburst

Description

@multiburst

Most appropriate sub-area of Processing 4?

Core/Environment/Rendering

Processing version

3 to current

Operating system

Linux

Steps to reproduce this

"1. Create a method calling nf(float, int, int), nf(int, int), nfc(float, int)

  1. Run this method within a thread thread("myFunction").

  2. Let it run for a longer time"

This is a little bit harder to reproduce and I only got it first with a complex project.

After a while you will end up with either a Stackoverflow or NullPointerException like this.

java.lang.NullPointerException: Cannot assign field "fastPathContainer" because "this.fastPathData" is null
    at java.base/java.text.DecimalFormat.resetFastPathData(DecimalFormat.java:1157)
    at java.base/java.text.DecimalFormat.checkAndSetFastPathStatus(DecimalFormat.java:1081)
    at java.base/java.text.DecimalFormat.fastFormat(DecimalFormat.java:1659)
    at java.base/java.text.NumberFormat.format(NumberFormat.java:327)
    at processing.core.PApplet.nf(PApplet.java:10108)
    at core3.app.gui.GUIInfo.pre(GUIInfo.java:413)
    at jdk.internal.reflect.GeneratedMethodAccessor24.invoke(Unknown Source)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:569)
    at processing.core.PApplet$RegisteredMethods.handle(PApplet.java:1436)
    at processing.core.PApplet$RegisteredMethods.handle(PApplet.java:1429)
    at processing.core.PApplet.handleMethods(PApplet.java:1628)
    at processing.core.PApplet.handleDraw(PApplet.java:2473)
    at processing.opengl.PSurfaceJOGL$DrawListener.display(PSurfaceJOGL.java:866)
    at jogamp.opengl.GLDrawableHelper.displayImpl(GLDrawableHelper.java:692)
    at jogamp.opengl.GLDrawableHelper.display(GLDrawableHelper.java:674)
    at jogamp.opengl.GLAutoDrawableBase$2.run(GLAutoDrawableBase.java:443)
    at jogamp.opengl.GLDrawableHelper.invokeGLImpl(GLDrawableHelper.java:1293)
    at jogamp.opengl.GLDrawableHelper.invokeGL(GLDrawableHelper.java:1147)
    at com.jogamp.newt.opengl.GLWindow.display(GLWindow.java:759)
    at com.jogamp.opengl.util.AWTAnimatorImpl.display(AWTAnimatorImpl.java:81)
    at com.jogamp.opengl.util.AnimatorBase.display(AnimatorBase.java:452)
    at com.jogamp.opengl.util.FPSAnimator$MainTask.run(FPSAnimator.java:178)
    at java.base/java.util.TimerThread.mainLoop(Timer.java:566)
    at java.base/java.util.TimerThread.run(Timer.java:516) 

snippet

Additional context

Doing a little bit research, the NumberFormat in nf/nfc seems not to be thread safe. General consent on this seems to be to use a ThreadLocal. So modifying PApplet like this, seems to fix it.


private static final ThreadLocal<NumberFormat> threadLocalIntNf = ThreadLocal.withInitial(() -> {
  NumberFormat nf = NumberFormat.getInstance();
  nf.setGroupingUsed(false); // no commas
  nf.setMinimumFractionDigits(0);
  nf.setMaximumFractionDigits(0);
  return nf;
});


  static public String nf(float num, int left, int right) {
//    if ((float_nf != null) &&
//        (float_nf_left == left) &&
//        (float_nf_right == right) &&
//        !float_nf_commas) {
//      return float_nf.format(num);
//    }

    float_nf = threadLocalIntNf.get();
    float_nf.setGroupingUsed(false);
    float_nf_commas = false;

    float_nf.setMinimumIntegerDigits(left);
    float_nf.setMinimumFractionDigits(right);
    float_nf.setMaximumFractionDigits(right);

    return float_nf.format(num);
  }

Would you like to work on the issue?

I can provide my fix, but it needs some optimisation/cleanup.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workinghelp wantedExtra attention is needed

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions