Quantcast

Var not thread safe?

classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Var not thread safe?

slow
Am I missing something?

A failing test case using parboiled-java v1.1.4:

public class ThreadSafetyOfVarsTest {
  static class NonThreadSafe extends BaseParser {
    Rule createAVar() {
      Var notEvenUsing = new Var();
      return toRule("");
    }
  }

  private static final int A_LARGE_NUM_CALLS = 100;

  @Test
  public void canCallFromMultipleThreads() throws Exception {
    NonThreadSafe toTest = Parboiled.createParser(NonThreadSafe.class);
    final Rule sameInstance = toTest.createAVar();

    final AtomicReference<Exception> problem = new AtomicReference<Exception>();

    Callable<Void> useSameRule = new Callable<Void>() {
      @Override
      public Void call() {
        try {
          new BasicParseRunner(sameInstance).run("ANYTHING");
        } catch (Exception e) {
          problem.compareAndSet(null, e);
        }
        return null;
      }
    };

    List<Callable<Void>> toCall = new ArrayList<Callable<Void>>();
    for (int i = 0; i < A_LARGE_NUM_CALLS; i++) {
      toCall.add(useSameRule);
    }

    for (Future<Void> next : Executors.newCachedThreadPool().invokeAll(toCall)) {
      next.get();
    }

    Assert.assertNull(problem.get());
  }
}

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Var not thread safe?

slow
I know it works if you create a create a new parser instance, but I read: https://github.com/sirthias/parboiled/wiki/Thread-Safety
as saying the Rule instance should be usable across multiple threads.
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Var not thread safe?

mathias
Administrator
If a rule does not hold any mutable state itself its thread-safe since it does all its work either on the (JVM-)stack or the parsers value stack.
However, `Var<…>` constructs introduce mutable state on the heap and break thread safety.

Cheers,
Mathias

---
[hidden email]
http://www.parboiled.org

On 16.02.2013, at 03:50, slow [via parboiled users] <[hidden email]> wrote:

>
>
> I know it works if you create a create a new parser instance, but I read:
> https://github.com/sirthias/parboiled/wiki/Thread-Safety
> as saying the Rule instance should be usable across multiple threads.
>
>
>
> _______________________________________________
> If you reply to this email, your message will be added to the discussion below:
> http://users.parboiled.org/Var-not-thread-safe-tp4024146p4024147.html
> To start a new topic under parboiled users, email [hidden email]
> To unsubscribe from parboiled users, visit
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Var not thread safe?

slow
What do you mean by the parser's value stack being thread safe?

Because this doesn't work either:
  public static class NonThreadSafe2 extends BaseParser {
    public Rule test() {
      return Sequence("", push("foo"));
    }
  }
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Var not thread safe?

mathias
Administrator
Yes you are right, apologies!
Since the value stack is a construct that actually lives on the heap, as a member of the parser class all operations on it happen as side effects from the executed rules.
It can therefore not be used from several parsing runs at the same time.

Generally you should not share parser instances between threads.

Cheers,
Mathias

---
[hidden email]
http://www.parboiled.org

On 21.02.2013, at 01:51, slow [via parboiled users] <[hidden email]> wrote:

>
>
> What do you mean by the parser's value stack being thread safe?
>
> Because this doesn't work either:
>  public static class NonThreadSafe2 extends BaseParser {
>    public Rule test() {
>      return Sequence("", push(match()));
>    }
>  }
>
>
>
> _______________________________________________
> If you reply to this email, your message will be added to the discussion below:
> http://users.parboiled.org/Var-not-thread-safe-tp4024146p4024149.html
> To start a new topic under parboiled users, email [hidden email]
> To unsubscribe from parboiled users, visit
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Var not thread safe?

slow
For anyone having the same problem I ended up doing this:

ParserA singleInstance = ParserA.create(ParserB.create(), ParserC.create());

// each thread
new BasicParseRunner<>(singleInstance.threadSafeCopy().rule()).run(input);

public abstract class ParserA extends BaseParser {
  public static ParserA create(ParserB b, ParserC c) {
    return Parboiled.createParser(ParserA.class, b, c);
  }

  ParserB b;
  ParserC c;

  ParserA(ParserB b, ParserC c) {
    this.b = b;
    this.c = c;
  }

  ParserA() {}

  ParserA threadSafeCopy() {
    // dependencies might just return this if not touching heap
    // return this;
    ParserA copy = newInstance();
    copy.b = b.threadSafeCopy();
    copy.c = c.threadSafeCopy();
    return copy;
  }

  Rule rule() {
    return FirstOf(b.rule(), c.rule());
  }
}
Loading...