ICU-13606 Fixing race condition in MeasureFormat.
X-SVN-Rev: 41025
This commit is contained in:
parent
c589ea8b5d
commit
33709da06a
@ -1062,9 +1062,13 @@ UnicodeString &MeasureFormat::formatNumeric(
|
||||
}
|
||||
|
||||
// Format time. draft becomes something like '5:30:45'
|
||||
// #13606: DateFormat is not thread-safe, but MeasureFormat advertises itself as thread-safe.
|
||||
FieldPosition smallestFieldPosition(smallestField);
|
||||
UnicodeString draft;
|
||||
static UMutex dateFmtMutex = U_MUTEX_INITIALIZER;
|
||||
umtx_lock(&dateFmtMutex);
|
||||
dateFmt.format(date, draft, smallestFieldPosition, status);
|
||||
umtx_unlock(&dateFmtMutex);
|
||||
|
||||
// If we find field for smallest amount replace it with the formatted
|
||||
// smallest amount from above taking care to replace the integer part
|
||||
|
@ -933,10 +933,15 @@ public class MeasureFormat extends UFormat {
|
||||
if (intFieldPosition.getBeginIndex() == 0 && intFieldPosition.getEndIndex() == 0) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
// Format our duration as a date, but keep track of where the smallest field is
|
||||
// so that we can use it to replace the integer portion of the smallest value.
|
||||
// #13606: DateFormat is not thread-safe, but MeasureFormat advertises itself as thread-safe.
|
||||
FieldPosition smallestFieldPosition = new FieldPosition(smallestField);
|
||||
String draft = formatter.format(duration, new StringBuffer(), smallestFieldPosition).toString();
|
||||
String draft;
|
||||
synchronized (formatter) {
|
||||
draft = formatter.format(duration, new StringBuffer(), smallestFieldPosition).toString();
|
||||
}
|
||||
|
||||
try {
|
||||
// If we find the smallest field
|
||||
|
@ -8,7 +8,10 @@ import org.junit.runner.RunWith;
|
||||
import org.junit.runners.JUnit4;
|
||||
|
||||
import com.ibm.icu.dev.test.TestFmwk;
|
||||
import com.ibm.icu.impl.DontCareFieldPosition;
|
||||
import com.ibm.icu.text.MeasureFormat;
|
||||
import com.ibm.icu.util.Currency;
|
||||
import com.ibm.icu.util.Measure;
|
||||
import com.ibm.icu.util.MeasureUnit;
|
||||
import com.ibm.icu.util.ULocale;
|
||||
|
||||
@ -30,5 +33,61 @@ public class MeasureUnitThreadTest extends TestFmwk {
|
||||
Currency.getInstance(ULocale.ENGLISH);
|
||||
try {thread.join();} catch(InterruptedException e) {};
|
||||
}
|
||||
|
||||
static class NumericMeasureThread extends Thread {
|
||||
final MeasureFormat mf;
|
||||
final Measure[] arg;
|
||||
final String expected;
|
||||
volatile boolean running = true;
|
||||
AssertionError error;
|
||||
|
||||
NumericMeasureThread(Measure[] arg, String expected) {
|
||||
this.mf = MeasureFormat.getInstance(ULocale.ENGLISH, MeasureFormat.FormatWidth.NUMERIC);
|
||||
this.arg = arg;
|
||||
this.expected = expected;
|
||||
this.error = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
while (running) {
|
||||
try {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
mf.formatMeasures(sb, DontCareFieldPosition.INSTANCE, arg);
|
||||
org.junit.Assert.assertEquals(expected, sb.toString());
|
||||
} catch (AssertionError e) {
|
||||
error = e;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Race in formatMeasures with width NUMERIC:
|
||||
// http://bugs.icu-project.org/trac/ticket/13606
|
||||
@Test
|
||||
public void NumericRaceTest() throws InterruptedException {
|
||||
NumericMeasureThread t1 = new NumericMeasureThread(new Measure[] {
|
||||
new Measure(3, MeasureUnit.MINUTE),
|
||||
new Measure(4, MeasureUnit.SECOND)
|
||||
}, "3:04");
|
||||
NumericMeasureThread t2 = new NumericMeasureThread(new Measure[] {
|
||||
new Measure(5, MeasureUnit.MINUTE),
|
||||
new Measure(6, MeasureUnit.SECOND)
|
||||
}, "5:06");
|
||||
t1.start();
|
||||
t2.start();
|
||||
Thread.sleep(5);
|
||||
t1.running = false;
|
||||
t2.running = false;
|
||||
t1.join();
|
||||
t2.join();
|
||||
if (t1.error != null) {
|
||||
throw new AssertionError("Failure in thread 1", t1.error);
|
||||
}
|
||||
if (t2.error != null) {
|
||||
throw new AssertionError("Failure in thread 2", t2.error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user