1 package org.eclipse.aether.util.concurrency;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import static java.util.Objects.requireNonNull;
23
24 import java.util.concurrent.atomic.AtomicInteger;
25 import java.util.concurrent.atomic.AtomicReference;
26 import java.util.concurrent.locks.LockSupport;
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41 public final class RunnableErrorForwarder
42 {
43
44 private final Thread thread = Thread.currentThread();
45
46 private final AtomicInteger counter = new AtomicInteger();
47
48 private final AtomicReference<Throwable> error = new AtomicReference<>();
49
50
51
52
53 public RunnableErrorForwarder()
54 {
55 }
56
57
58
59
60
61
62
63 public Runnable wrap( final Runnable runnable )
64 {
65 requireNonNull( runnable, "runnable cannot be null" );
66
67 counter.incrementAndGet();
68
69 return new Runnable()
70 {
71 public void run()
72 {
73 try
74 {
75 runnable.run();
76 }
77 catch ( RuntimeException | Error e )
78 {
79 error.compareAndSet( null, e );
80 throw e;
81 }
82 finally
83 {
84 counter.decrementAndGet();
85 LockSupport.unpark( thread );
86 }
87 }
88 };
89 }
90
91
92
93
94
95
96
97 public void await()
98 {
99 awaitTerminationOfAllRunnables();
100
101 Throwable error = this.error.get();
102 if ( error != null )
103 {
104 if ( error instanceof RuntimeException )
105 {
106 throw (RuntimeException) error;
107 }
108 else if ( error instanceof ThreadDeath )
109 {
110 throw new IllegalStateException( error );
111 }
112 else if ( error instanceof Error )
113 {
114 throw (Error) error;
115 }
116 throw new IllegalStateException( error );
117 }
118 }
119
120 private void awaitTerminationOfAllRunnables()
121 {
122 if ( !thread.equals( Thread.currentThread() ) )
123 {
124 throw new IllegalStateException( "wrong caller thread, expected " + thread + " and not "
125 + Thread.currentThread() );
126 }
127
128 boolean interrupted = false;
129
130 while ( counter.get() > 0 )
131 {
132 LockSupport.park();
133
134 if ( Thread.interrupted() )
135 {
136 interrupted = true;
137 }
138 }
139
140 if ( interrupted )
141 {
142 Thread.currentThread().interrupt();
143 }
144 }
145
146 }