Skip to content

Commit a3bed9f

Browse files
committed
Make barcodes.dmcode.Placement thread safe
DEVSIX-1848
1 parent ff2608f commit a3bed9f

File tree

2 files changed

+54
-18
lines changed

2 files changed

+54
-18
lines changed

barcodes/src/main/java/com/itextpdf/barcodes/dmcode/Placement.java

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -44,21 +44,25 @@ This file is part of the iText (R) project.
4444
package com.itextpdf.barcodes.dmcode;
4545

4646
import java.util.Arrays;
47-
import java.util.HashMap;
4847
import java.util.Map;
48+
import java.util.concurrent.ConcurrentHashMap;
4949

5050
public class Placement {
51-
private int nrow;
52-
private int ncol;
53-
private short[] array;
54-
private static final Map<Integer, short[]> cache = new HashMap<>();
55-
56-
private Placement() {
51+
private final int nrow;
52+
private final int ncol;
53+
private final short[] array;
54+
private static final Map<Integer, short[]> cache = new ConcurrentHashMap<>();
55+
56+
private Placement(int nrow, int ncol) {
57+
this.nrow = nrow;
58+
this.ncol = ncol;
59+
array = new short[nrow * ncol];
5760
}
5861

5962

6063
/**
6164
* Execute the placement
65+
*
6266
* @param nrow number of rows
6367
* @param ncol number of columns
6468
* @return array containing appropriate values for ECC200
@@ -68,10 +72,7 @@ public static short[] doPlacement(int nrow, int ncol) {
6872
short[] pc = cache.get(key);
6973
if (pc != null)
7074
return pc;
71-
Placement p = new Placement();
72-
p.nrow = nrow;
73-
p.ncol = ncol;
74-
p.array = new short[nrow * ncol];
75+
Placement p = new Placement(nrow, ncol);
7576
p.ecc200();
7677
cache.put(key, p.array);
7778
return p.array;
@@ -150,19 +151,19 @@ private void corner4(int chr) {
150151
/* "ECC200" fills an nrow x ncol array with appropriate values for ECC200 */
151152
private void ecc200() {
152153
int row, col, chr;
153-
/* First, fill the array[] with invalid entries */
154+
/* First, fill the array[] with invalid entries */
154155
Arrays.fill(array, (short) 0);
155-
/* Starting in the correct location for character #1, bit 8,... */
156+
/* Starting in the correct location for character #1, bit 8,... */
156157
chr = 1;
157158
row = 4;
158159
col = 0;
159160
do {
160-
/* repeatedly first check for one of the special corner cases, then... */
161+
/* repeatedly first check for one of the special corner cases, then... */
161162
if (row == nrow && col == 0) corner1(chr++);
162163
if (row == nrow - 2 && col == 0 && ncol % 4 != 0) corner2(chr++);
163164
if (row == nrow - 2 && col == 0 && ncol % 8 == 4) corner3(chr++);
164165
if (row == nrow + 4 && col == 2 && ncol % 8 == 0) corner4(chr++);
165-
/* sweep upward diagonally, inserting successive characters,... */
166+
/* sweep upward diagonally, inserting successive characters,... */
166167
do {
167168
if (row < nrow && col >= 0 && array[row * ncol + col] == 0)
168169
utah(row, col, chr++);
@@ -171,7 +172,7 @@ private void ecc200() {
171172
} while (row >= 0 && col < ncol);
172173
row += 1;
173174
col += 3;
174-
/* & then sweep downward diagonally, inserting successive characters,... */
175+
/* & then sweep downward diagonally, inserting successive characters,... */
175176

176177
do {
177178
if (row >= 0 && col < ncol && array[row * ncol + col] == 0)
@@ -181,9 +182,9 @@ private void ecc200() {
181182
} while (row < nrow && col >= 0);
182183
row += 3;
183184
col += 1;
184-
/* ... until the entire array is scanned */
185+
/* ... until the entire array is scanned */
185186
} while (row < nrow || col < ncol);
186-
/* Lastly, if the lower righthand corner is untouched, fill in fixed pattern */
187+
/* Lastly, if the lower righthand corner is untouched, fill in fixed pattern */
187188
if (array[nrow * ncol - 1] == 0) {
188189
array[nrow * ncol - 1] = array[nrow * ncol - ncol - 2] = 1;
189190
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package com.itextpdf.barcodes;
2+
3+
import com.itextpdf.test.annotations.type.UnitTest;
4+
import org.junit.Assert;
5+
import org.junit.Test;
6+
import org.junit.experimental.categories.Category;
7+
8+
@Category(UnitTest.class)
9+
public class BarcodeMultiThreadingTest {
10+
11+
private static class DataMatrixThread extends Thread {
12+
@Override
13+
public void run() {
14+
BarcodeDataMatrix bc = new BarcodeDataMatrix();
15+
bc.setOptions(BarcodeDataMatrix.DM_AUTO);
16+
bc.setWidth(10);
17+
bc.setHeight(10);
18+
int result = bc.setCode("AB01");
19+
20+
Assert.assertEquals(BarcodeDataMatrix.DM_NO_ERROR, result);
21+
}
22+
}
23+
24+
@Test(timeout = 10000)
25+
public void test() throws InterruptedException {
26+
Thread[] threads = new DataMatrixThread[20];
27+
for (int i = 0; i < threads.length; i++) {
28+
threads[i] = new DataMatrixThread();
29+
threads[i].start();
30+
}
31+
for (Thread thread : threads) {
32+
thread.join();
33+
}
34+
}
35+
}

0 commit comments

Comments
 (0)