package Samples; /*Generated by MPS */ import java.util.List; import jetbrains.mps.internal.collections.runtime.ListSequence; import java.util.ArrayList; import java.util.concurrent.CountDownLatch; import java.util.concurrent.CopyOnWriteArrayList; import utils.ParallelLoopException; public class ThreadSafeSample { private static final String fixedFieldValue = "Fixed value for ever"; public ThreadSafeSample() { } public static void main(String[] args) throws InterruptedException { // This sample shows that classes marked thread-safe will not be reported // as inproperly used from within parallel for loops // This is a thread safe class to exchange a single value between a producer and a consumer // Open the DropBox class definition and notice the "@thread safe" annotation for the class final DropBox<String> box = new DropBox<String>(); // A consumer thread reading and printing values exchanged through the drop box Thread thread = new Thread(new Runnable() { @Override public void run() { try { while (true) { System.out.println("Received: " + box.retrieve()); } } catch (InterruptedException e) { System.out.println("Interrupted"); } } }); thread.start(); final List<String> names = ListSequence.fromListAndArray(new ArrayList<String>(), "Joe", "Dave", "Alice"); { final CountDownLatch latch_n0c = new CountDownLatch(ListSequence.fromList(names).count()); final List<Exception> exceptions_n0c = new CopyOnWriteArrayList<Exception>(); for (final String name : names) { final String localA = name; final Runnable runnable = new Runnable() { public void run() { try { try { // Notice no warning nor error reported box.store(localA); // If the DropBox class was annotated as "@non thread safe", we would get an error reported // No annotation on the class would result in a warning } catch (InterruptedException e) { throw new RuntimeException(e); } } catch (RuntimeException e) { ListSequence.fromList(exceptions_n0c).addElement(e); } finally { latch_n0c.countDown(); } } }; new Thread(runnable).start(); } try { latch_n0c.await(); } catch (InterruptedException e) { ListSequence.fromList(exceptions_n0c).addElement(e); } if (ListSequence.fromList(exceptions_n0c).isNotEmpty()) { throw new ParallelLoopException("Some parallel calculations failed", exceptions_n0c); } } // By annotating a local variable, field or parameter declaration as thread safe you indicate that calling methods // on the object is thread-safe // Alt + Enter on variable declarations will let you mark and unmark them as thread-safe final String fixedValue = " fixed value "; { final CountDownLatch latch_u0c = new CountDownLatch(ListSequence.fromList(names).count()); final List<Exception> exceptions_u0c = new CopyOnWriteArrayList<Exception>(); for (final String name : names) { final String localA = name; final Runnable runnable = new Runnable() { public void run() { try { String finalString = localA + fixedValue.toUpperCase() + fixedFieldValue; log("Result: " + finalString); } catch (RuntimeException e) { ListSequence.fromList(exceptions_u0c).addElement(e); } finally { latch_u0c.countDown(); } } }; new Thread(runnable).start(); } try { latch_u0c.await(); } catch (InterruptedException e) { ListSequence.fromList(exceptions_u0c).addElement(e); } if (ListSequence.fromList(exceptions_u0c).isNotEmpty()) { throw new ParallelLoopException("Some parallel calculations failed", exceptions_u0c); } } thread.interrupt(); } private static void log(String message) { System.out.println(message); } }