1 |
/* |
2 |
* Written by Martin Buchholz with assistance from members of JCP |
3 |
* JSR-166 Expert Group and released to the public domain, as |
4 |
* explained at http://creativecommons.org/publicdomain/zero/1.0/ |
5 |
*/ |
6 |
|
7 |
package java.util.concurrent; |
8 |
|
9 |
import java.util.Collection; |
10 |
|
11 |
/** Shared implementation code for java.util.concurrent. */ |
12 |
class Helpers { |
13 |
/** |
14 |
* An implementation of Collection.toString() suitable for classes |
15 |
* with locks. Instead of holding a lock for the entire duration of |
16 |
* toString(), or acquiring a lock for each call to Iterator.next(), |
17 |
* we hold the lock only during the call to toArray() (less |
18 |
* disruptive to other threads accessing the collection) and follows |
19 |
* the maxim "Never call foreign code while holding a lock". |
20 |
*/ |
21 |
static String collectionToString(Collection<?> c) { |
22 |
final Object[] a = c.toArray(); |
23 |
final int size = a.length; |
24 |
if (size == 0) |
25 |
return "[]"; |
26 |
int charLength = 0; |
27 |
|
28 |
// Replace every array element with its string representation |
29 |
for (int i = 0; i < size; i++) { |
30 |
Object e = a[i]; |
31 |
// Extreme compatibility with AbstractCollection.toString() |
32 |
String s = (e == c) ? "(this Collection)" : objectToString(e); |
33 |
a[i] = s; |
34 |
charLength += s.length(); |
35 |
} |
36 |
|
37 |
return toString(a, size, charLength); |
38 |
} |
39 |
|
40 |
/** |
41 |
* Like Arrays.toString(), but caller guarantees that size > 0, |
42 |
* each element with index 0 <= i < size is a non-null String, |
43 |
* and charLength is the sum of the lengths of the input Strings. |
44 |
*/ |
45 |
static String toString(Object[] a, int size, int charLength) { |
46 |
// assert a != null; |
47 |
// assert size > 0; |
48 |
|
49 |
// Copy each string into a perfectly sized char[] |
50 |
// Length of [ , , , ] == 2 * size |
51 |
final char[] chars = new char[charLength + 2 * size]; |
52 |
chars[0] = '['; |
53 |
int j = 1; |
54 |
for (int i = 0; i < size; i++) { |
55 |
if (i > 0) { |
56 |
chars[j++] = ','; |
57 |
chars[j++] = ' '; |
58 |
} |
59 |
String s = (String) a[i]; |
60 |
int len = s.length(); |
61 |
s.getChars(0, len, chars, j); |
62 |
j += len; |
63 |
} |
64 |
chars[j] = ']'; |
65 |
// assert j == chars.length - 1; |
66 |
return newStringUnsafe(chars); |
67 |
} |
68 |
|
69 |
/** Optimized form of: key + "=" + val */ |
70 |
static String mapEntryToString(Object key, Object val) { |
71 |
final String k, v; |
72 |
final int klen, vlen; |
73 |
final char[] chars = |
74 |
new char[(klen = (k = objectToString(key)).length()) + |
75 |
(vlen = (v = objectToString(val)).length()) + 1]; |
76 |
k.getChars(0, klen, chars, 0); |
77 |
chars[klen] = '='; |
78 |
v.getChars(0, vlen, chars, klen + 1); |
79 |
return newStringUnsafe(chars); |
80 |
} |
81 |
|
82 |
private static String objectToString(Object x) { |
83 |
// Extreme compatibility with StringBuilder.append(null) |
84 |
String s; |
85 |
return (x == null || (s = x.toString()) == null) ? "null" : s; |
86 |
} |
87 |
|
88 |
/** |
89 |
* Returns a String containing the contents of chars, which caller |
90 |
* promises will never be modified. |
91 |
*/ |
92 |
private static String newStringUnsafe(char[] chars) { |
93 |
// If porting to a JDK where sun.misc.SharedSecrets is not |
94 |
// available, modify the code below to simply: |
95 |
// return new String(chars); |
96 |
// TODO: Can we do this more portably? |
97 |
return sun.misc.SharedSecrets.getJavaLangAccess().newStringUnsafe(chars); |
98 |
} |
99 |
|
100 |
} |