test/compiler/6865031/Test.java

Tue, 08 Aug 2017 15:57:29 +0800

author
aoqi
date
Tue, 08 Aug 2017 15:57:29 +0800
changeset 6876
710a3c8b516e
parent 1907
c18cbe5936b8
parent 0
f90c822e73f8
permissions
-rw-r--r--

merge

aoqi@0 1 /*
aoqi@0 2 * Copyright 2009 Goldman Sachs International. All Rights Reserved.
aoqi@0 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
aoqi@0 4 *
aoqi@0 5 * This code is free software; you can redistribute it and/or modify it
aoqi@0 6 * under the terms of the GNU General Public License version 2 only, as
aoqi@0 7 * published by the Free Software Foundation.
aoqi@0 8 *
aoqi@0 9 * This code is distributed in the hope that it will be useful, but WITHOUT
aoqi@0 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
aoqi@0 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
aoqi@0 12 * version 2 for more details (a copy is included in the LICENSE file that
aoqi@0 13 * accompanied this code).
aoqi@0 14 *
aoqi@0 15 * You should have received a copy of the GNU General Public License version
aoqi@0 16 * 2 along with this work; if not, write to the Free Software Foundation,
aoqi@0 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
aoqi@0 18 *
aoqi@0 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
aoqi@0 20 * or visit www.oracle.com if you need additional information or have any
aoqi@0 21 * questions.
aoqi@0 22 *
aoqi@0 23 */
aoqi@0 24
aoqi@0 25 /*
aoqi@0 26 * @test
aoqi@0 27 * @bug 6865031
aoqi@0 28 * @summary Application gives bad result (throws bad exception) with compressed oops
aoqi@0 29 * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+UseCompressedOops -XX:HeapBaseMinAddress=32g -XX:-LoopUnswitching -XX:CompileCommand=inline,AbstractMemoryEfficientList.equals Test hello goodbye
aoqi@0 30 */
aoqi@0 31
aoqi@0 32 import java.lang.ref.ReferenceQueue;
aoqi@0 33 import java.lang.ref.WeakReference;
aoqi@0 34 import java.util.ArrayList;
aoqi@0 35 import java.util.Arrays;
aoqi@0 36 import java.util.List;
aoqi@0 37
aoqi@0 38 interface MyList {
aoqi@0 39 public int size();
aoqi@0 40 public Object set(final int index, final Object element);
aoqi@0 41 public Object get(final int index);
aoqi@0 42 }
aoqi@0 43
aoqi@0 44 abstract class AbstractMemoryEfficientList implements MyList {
aoqi@0 45 abstract public int size();
aoqi@0 46 abstract public Object get(final int index);
aoqi@0 47 abstract public Object set(final int index, final Object element);
aoqi@0 48
aoqi@0 49 public boolean equals(Object o) {
aoqi@0 50 if (o == this) {
aoqi@0 51 return true;
aoqi@0 52 }
aoqi@0 53
aoqi@0 54 if (!(o instanceof MyList)) {
aoqi@0 55 return false;
aoqi@0 56 }
aoqi@0 57
aoqi@0 58 final MyList that = (MyList) o;
aoqi@0 59 if (this.size() != that.size()) {
aoqi@0 60 return false;
aoqi@0 61 }
aoqi@0 62
aoqi@0 63 for (int i = 0; i < this.size(); i++) {
aoqi@0 64 try {
aoqi@0 65 if (!((this.get(i)).equals(that.get(i)))) {
aoqi@0 66 return false;
aoqi@0 67 }
aoqi@0 68 } catch (IndexOutOfBoundsException e) {
aoqi@0 69 System.out.println("THROWING RT EXC");
aoqi@0 70 System.out.println("concurrent modification of this:" + this.getClass() + ":" + System.identityHashCode(this) + "; that:" + that.getClass() + ":" + System.identityHashCode(that) + "; i:" + i);
aoqi@0 71 e.printStackTrace();
aoqi@0 72 System.exit(97);
aoqi@0 73 throw new RuntimeException("concurrent modification of this:" + this.getClass() + ":" + System.identityHashCode(this) + "; that:" + that.getClass() + ":" + System.identityHashCode(that) + "; i:" + i, e);
aoqi@0 74 }
aoqi@0 75 }
aoqi@0 76 return true;
aoqi@0 77 }
aoqi@0 78
aoqi@0 79 public int hashCode() {
aoqi@0 80 int hashCode = 1;
aoqi@0 81 for (int i = 0; i < this.size(); i++) {
aoqi@0 82 Object obj = this.get(i);
aoqi@0 83 hashCode = 31 * hashCode + (obj == null ? 0 : obj.hashCode());
aoqi@0 84 }
aoqi@0 85 return hashCode;
aoqi@0 86 }
aoqi@0 87 }
aoqi@0 88
aoqi@0 89 final class SingletonList extends AbstractMemoryEfficientList {
aoqi@0 90 private Object element1;
aoqi@0 91
aoqi@0 92 SingletonList(final Object obj1) {
aoqi@0 93 super();
aoqi@0 94 this.element1 = obj1;
aoqi@0 95 }
aoqi@0 96
aoqi@0 97 public int size() {
aoqi@0 98 return 1;
aoqi@0 99 }
aoqi@0 100
aoqi@0 101 public Object get(final int index) {
aoqi@0 102 if (index == 0) {
aoqi@0 103 return this.element1;
aoqi@0 104 } else {
aoqi@0 105 throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + this.size());
aoqi@0 106 }
aoqi@0 107 }
aoqi@0 108
aoqi@0 109 public Object set(final int index, final Object element) {
aoqi@0 110 if (index == 0) {
aoqi@0 111 final Object previousElement = this.element1;
aoqi@0 112 this.element1 = element;
aoqi@0 113 return previousElement;
aoqi@0 114 } else {
aoqi@0 115 throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + this.size());
aoqi@0 116 }
aoqi@0 117 }
aoqi@0 118 }
aoqi@0 119
aoqi@0 120 final class DoubletonList extends AbstractMemoryEfficientList {
aoqi@0 121 private Object element1;
aoqi@0 122 private Object element2;
aoqi@0 123
aoqi@0 124 DoubletonList(final Object obj1, final Object obj2) {
aoqi@0 125 this.element1 = obj1;
aoqi@0 126 this.element2 = obj2;
aoqi@0 127 }
aoqi@0 128
aoqi@0 129 public int size() {
aoqi@0 130 return 2;
aoqi@0 131 }
aoqi@0 132
aoqi@0 133 public Object get(final int index) {
aoqi@0 134 switch (index) {
aoqi@0 135 case 0 : return this.element1;
aoqi@0 136 case 1 : return this.element2;
aoqi@0 137 default: throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + this.size());
aoqi@0 138 }
aoqi@0 139 }
aoqi@0 140
aoqi@0 141 public Object set(final int index, final Object element) {
aoqi@0 142 switch (index) {
aoqi@0 143 case 0 :
aoqi@0 144 {
aoqi@0 145 final Object previousElement = this.element1;
aoqi@0 146 this.element1 = element;
aoqi@0 147 return previousElement;
aoqi@0 148 }
aoqi@0 149 case 1 :
aoqi@0 150 {
aoqi@0 151 final Object previousElement = this.element2;
aoqi@0 152 this.element2 = element;
aoqi@0 153 return previousElement;
aoqi@0 154 }
aoqi@0 155 default : throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + this.size());
aoqi@0 156 }
aoqi@0 157 }
aoqi@0 158 }
aoqi@0 159
aoqi@0 160 class WeakPool<V> {
aoqi@0 161 protected static final int DEFAULT_INITIAL_CAPACITY = 16;
aoqi@0 162 private static final int MAXIMUM_CAPACITY = 1 << 30;
aoqi@0 163 private static final float DEFAULT_LOAD_FACTOR = 0.75f;
aoqi@0 164
aoqi@0 165 protected Entry<V>[] table;
aoqi@0 166
aoqi@0 167 private int size;
aoqi@0 168 protected int threshold;
aoqi@0 169 private final float loadFactor;
aoqi@0 170 private final ReferenceQueue<V> queue = new ReferenceQueue<V>();
aoqi@0 171
aoqi@0 172 public WeakPool()
aoqi@0 173 {
aoqi@0 174 this.loadFactor = DEFAULT_LOAD_FACTOR;
aoqi@0 175 threshold = DEFAULT_INITIAL_CAPACITY;
aoqi@0 176 table = new Entry[DEFAULT_INITIAL_CAPACITY];
aoqi@0 177 }
aoqi@0 178
aoqi@0 179 /**
aoqi@0 180 * Check for equality of non-null reference x and possibly-null y. By
aoqi@0 181 * default uses Object.equals.
aoqi@0 182 */
aoqi@0 183 private boolean eq(Object x, Object y)
aoqi@0 184 {
aoqi@0 185 return x == y || x.equals(y);
aoqi@0 186 }
aoqi@0 187
aoqi@0 188 /**
aoqi@0 189 * Return index for hash code h.
aoqi@0 190 */
aoqi@0 191 private int indexFor(int h, int length)
aoqi@0 192 {
aoqi@0 193 return h & length - 1;
aoqi@0 194 }
aoqi@0 195
aoqi@0 196 /**
aoqi@0 197 * Expunge stale entries from the table.
aoqi@0 198 */
aoqi@0 199 private void expungeStaleEntries()
aoqi@0 200 {
aoqi@0 201 Object r;
aoqi@0 202 while ((r = queue.poll()) != null)
aoqi@0 203 {
aoqi@0 204 Entry e = (Entry) r;
aoqi@0 205 int h = e.hash;
aoqi@0 206 int i = indexFor(h, table.length);
aoqi@0 207
aoqi@0 208 // System.out.println("EXPUNGING " + h);
aoqi@0 209 Entry<V> prev = table[i];
aoqi@0 210 Entry<V> p = prev;
aoqi@0 211 while (p != null)
aoqi@0 212 {
aoqi@0 213 Entry<V> next = p.next;
aoqi@0 214 if (p == e)
aoqi@0 215 {
aoqi@0 216 if (prev == e)
aoqi@0 217 {
aoqi@0 218 table[i] = next;
aoqi@0 219 }
aoqi@0 220 else
aoqi@0 221 {
aoqi@0 222 prev.next = next;
aoqi@0 223 }
aoqi@0 224 e.next = null; // Help GC
aoqi@0 225 size--;
aoqi@0 226 break;
aoqi@0 227 }
aoqi@0 228 prev = p;
aoqi@0 229 p = next;
aoqi@0 230 }
aoqi@0 231 }
aoqi@0 232 }
aoqi@0 233
aoqi@0 234 /**
aoqi@0 235 * Return the table after first expunging stale entries
aoqi@0 236 */
aoqi@0 237 private Entry<V>[] getTable()
aoqi@0 238 {
aoqi@0 239 expungeStaleEntries();
aoqi@0 240 return table;
aoqi@0 241 }
aoqi@0 242
aoqi@0 243 /**
aoqi@0 244 * Returns the number of key-value mappings in this map.
aoqi@0 245 * This result is a snapshot, and may not reflect unprocessed
aoqi@0 246 * entries that will be removed before next attempted access
aoqi@0 247 * because they are no longer referenced.
aoqi@0 248 */
aoqi@0 249 public int size()
aoqi@0 250 {
aoqi@0 251 if (size == 0)
aoqi@0 252 {
aoqi@0 253 return 0;
aoqi@0 254 }
aoqi@0 255 expungeStaleEntries();
aoqi@0 256 return size;
aoqi@0 257 }
aoqi@0 258
aoqi@0 259 /**
aoqi@0 260 * Returns <tt>true</tt> if this map contains no key-value mappings.
aoqi@0 261 * This result is a snapshot, and may not reflect unprocessed
aoqi@0 262 * entries that will be removed before next attempted access
aoqi@0 263 * because they are no longer referenced.
aoqi@0 264 */
aoqi@0 265 public boolean isEmpty()
aoqi@0 266 {
aoqi@0 267 return size() == 0;
aoqi@0 268 }
aoqi@0 269
aoqi@0 270 /**
aoqi@0 271 * Returns the value stored in the pool that equals the requested key
aoqi@0 272 * or <tt>null</tt> if the map contains no mapping for
aoqi@0 273 * this key (or the key is null)
aoqi@0 274 *
aoqi@0 275 * @param key the key whose equals value is to be returned.
aoqi@0 276 * @return the object that is equal the specified key, or
aoqi@0 277 * <tt>null</tt> if key is null or no object in the pool equals the key.
aoqi@0 278 */
aoqi@0 279 public V get(V key)
aoqi@0 280 {
aoqi@0 281 if (key == null)
aoqi@0 282 {
aoqi@0 283 return null;
aoqi@0 284 }
aoqi@0 285 int h = key.hashCode();
aoqi@0 286 Entry<V>[] tab = getTable();
aoqi@0 287 int index = indexFor(h, tab.length);
aoqi@0 288 Entry<V> e = tab[index];
aoqi@0 289 while (e != null)
aoqi@0 290 {
aoqi@0 291 V candidate = e.get();
aoqi@0 292 if (e.hash == h && eq(key, candidate))
aoqi@0 293 {
aoqi@0 294 return candidate;
aoqi@0 295 }
aoqi@0 296 e = e.next;
aoqi@0 297 }
aoqi@0 298 return null;
aoqi@0 299 }
aoqi@0 300
aoqi@0 301 /**
aoqi@0 302 * Returns the entry associated with the specified key in the HashMap.
aoqi@0 303 * Returns null if the HashMap contains no mapping for this key.
aoqi@0 304 */
aoqi@0 305 Entry getEntry(Object key)
aoqi@0 306 {
aoqi@0 307 int h = key.hashCode();
aoqi@0 308 Entry[] tab = getTable();
aoqi@0 309 int index = indexFor(h, tab.length);
aoqi@0 310 Entry e = tab[index];
aoqi@0 311 while (e != null && !(e.hash == h && eq(key, e.get())))
aoqi@0 312 {
aoqi@0 313 e = e.next;
aoqi@0 314 }
aoqi@0 315 return e;
aoqi@0 316 }
aoqi@0 317
aoqi@0 318 /**
aoqi@0 319 * Places the object into the pool. If the object is null, nothing happens.
aoqi@0 320 * If an equal object already exists, it is not replaced.
aoqi@0 321 *
aoqi@0 322 * @param key the object to put into the pool. key may be null.
aoqi@0 323 * @return the object in the pool that is equal to the key, or the newly placed key if no such object existed when put was called
aoqi@0 324 */
aoqi@0 325 public V put(V key)
aoqi@0 326 {
aoqi@0 327 if (key == null)
aoqi@0 328 {
aoqi@0 329 return null;
aoqi@0 330 }
aoqi@0 331 int h = key.hashCode();
aoqi@0 332 Entry<V>[] tab = getTable();
aoqi@0 333 int i = indexFor(h, tab.length);
aoqi@0 334
aoqi@0 335 for (Entry<V> e = tab[i]; e != null; e = e.next)
aoqi@0 336 {
aoqi@0 337 V candidate = e.get();
aoqi@0 338 if (h == e.hash && eq(key, candidate))
aoqi@0 339 {
aoqi@0 340 return candidate;
aoqi@0 341 }
aoqi@0 342 }
aoqi@0 343
aoqi@0 344 tab[i] = new Entry<V>(key, queue, h, tab[i]);
aoqi@0 345
aoqi@0 346 if (++size >= threshold)
aoqi@0 347 {
aoqi@0 348 resize(tab.length * 2);
aoqi@0 349 }
aoqi@0 350
aoqi@0 351 // System.out.println("Added " + key + " to pool");
aoqi@0 352 return key;
aoqi@0 353 }
aoqi@0 354
aoqi@0 355 /**
aoqi@0 356 * Rehashes the contents of this map into a new array with a
aoqi@0 357 * larger capacity. This method is called automatically when the
aoqi@0 358 * number of keys in this map reaches its threshold.
aoqi@0 359 * <p/>
aoqi@0 360 * If current capacity is MAXIMUM_CAPACITY, this method does not
aoqi@0 361 * resize the map, but but sets threshold to Integer.MAX_VALUE.
aoqi@0 362 * This has the effect of preventing future calls.
aoqi@0 363 *
aoqi@0 364 * @param newCapacity the new capacity, MUST be a power of two;
aoqi@0 365 * must be greater than current capacity unless current
aoqi@0 366 * capacity is MAXIMUM_CAPACITY (in which case value
aoqi@0 367 * is irrelevant).
aoqi@0 368 */
aoqi@0 369 void resize(int newCapacity)
aoqi@0 370 {
aoqi@0 371 Entry<V>[] oldTable = getTable();
aoqi@0 372 int oldCapacity = oldTable.length;
aoqi@0 373 if (oldCapacity == MAXIMUM_CAPACITY)
aoqi@0 374 {
aoqi@0 375 threshold = Integer.MAX_VALUE;
aoqi@0 376 return;
aoqi@0 377 }
aoqi@0 378
aoqi@0 379 Entry<V>[] newTable = new Entry[newCapacity];
aoqi@0 380 transfer(oldTable, newTable);
aoqi@0 381 table = newTable;
aoqi@0 382
aoqi@0 383 /*
aoqi@0 384 * If ignoring null elements and processing ref queue caused massive
aoqi@0 385 * shrinkage, then restore old table. This should be rare, but avoids
aoqi@0 386 * unbounded expansion of garbage-filled tables.
aoqi@0 387 */
aoqi@0 388 if (size >= threshold / 2)
aoqi@0 389 {
aoqi@0 390 threshold = (int) (newCapacity * loadFactor);
aoqi@0 391 }
aoqi@0 392 else
aoqi@0 393 {
aoqi@0 394 expungeStaleEntries();
aoqi@0 395 transfer(newTable, oldTable);
aoqi@0 396 table = oldTable;
aoqi@0 397 }
aoqi@0 398 }
aoqi@0 399
aoqi@0 400 /**
aoqi@0 401 * Transfer all entries from src to dest tables
aoqi@0 402 */
aoqi@0 403 private void transfer(Entry[] src, Entry[] dest)
aoqi@0 404 {
aoqi@0 405 for (int j = 0; j < src.length; ++j)
aoqi@0 406 {
aoqi@0 407 Entry e = src[j];
aoqi@0 408 src[j] = null;
aoqi@0 409 while (e != null)
aoqi@0 410 {
aoqi@0 411 Entry next = e.next;
aoqi@0 412 Object key = e.get();
aoqi@0 413 if (key == null)
aoqi@0 414 {
aoqi@0 415 e.next = null; // Help GC
aoqi@0 416 size--;
aoqi@0 417 }
aoqi@0 418 else
aoqi@0 419 {
aoqi@0 420 int i = indexFor(e.hash, dest.length);
aoqi@0 421 e.next = dest[i];
aoqi@0 422 dest[i] = e;
aoqi@0 423 }
aoqi@0 424 e = next;
aoqi@0 425 }
aoqi@0 426 }
aoqi@0 427 }
aoqi@0 428
aoqi@0 429 /**
aoqi@0 430 * Removes the object in the pool that equals the key.
aoqi@0 431 *
aoqi@0 432 * @param key
aoqi@0 433 * @return previous value associated with specified key, or <tt>null</tt>
aoqi@0 434 * if there was no mapping for key or the key is null.
aoqi@0 435 */
aoqi@0 436 public V removeFromPool(V key)
aoqi@0 437 {
aoqi@0 438 if (key == null)
aoqi@0 439 {
aoqi@0 440 return null;
aoqi@0 441 }
aoqi@0 442 int h = key.hashCode();
aoqi@0 443 Entry<V>[] tab = getTable();
aoqi@0 444 int i = indexFor(h, tab.length);
aoqi@0 445 Entry<V> prev = tab[i];
aoqi@0 446 Entry<V> e = prev;
aoqi@0 447
aoqi@0 448 while (e != null)
aoqi@0 449 {
aoqi@0 450 Entry<V> next = e.next;
aoqi@0 451 V candidate = e.get();
aoqi@0 452 if (h == e.hash && eq(key, candidate))
aoqi@0 453 {
aoqi@0 454 size--;
aoqi@0 455 if (prev == e)
aoqi@0 456 {
aoqi@0 457 tab[i] = next;
aoqi@0 458 }
aoqi@0 459 else
aoqi@0 460 {
aoqi@0 461 prev.next = next;
aoqi@0 462 }
aoqi@0 463 return candidate;
aoqi@0 464 }
aoqi@0 465 prev = e;
aoqi@0 466 e = next;
aoqi@0 467 }
aoqi@0 468
aoqi@0 469 return null;
aoqi@0 470 }
aoqi@0 471
aoqi@0 472 /**
aoqi@0 473 * Removes all mappings from this map.
aoqi@0 474 */
aoqi@0 475 public void clear()
aoqi@0 476 {
aoqi@0 477 // clear out ref queue. We don't need to expunge entries
aoqi@0 478 // since table is getting cleared.
aoqi@0 479 while (queue.poll() != null)
aoqi@0 480 {
aoqi@0 481 // nop
aoqi@0 482 }
aoqi@0 483
aoqi@0 484 table = new Entry[DEFAULT_INITIAL_CAPACITY];
aoqi@0 485 threshold = DEFAULT_INITIAL_CAPACITY;
aoqi@0 486 size = 0;
aoqi@0 487
aoqi@0 488 // Allocation of array may have caused GC, which may have caused
aoqi@0 489 // additional entries to go stale. Removing these entries from the
aoqi@0 490 // reference queue will make them eligible for reclamation.
aoqi@0 491 while (queue.poll() != null)
aoqi@0 492 {
aoqi@0 493 // nop
aoqi@0 494 }
aoqi@0 495 }
aoqi@0 496
aoqi@0 497 /**
aoqi@0 498 * The entries in this hash table extend WeakReference, using its main ref
aoqi@0 499 * field as the key.
aoqi@0 500 */
aoqi@0 501 protected static class Entry<V>
aoqi@0 502 extends WeakReference<V>
aoqi@0 503 {
aoqi@0 504 private final int hash;
aoqi@0 505 private Entry<V> next;
aoqi@0 506
aoqi@0 507 /**
aoqi@0 508 * Create new entry.
aoqi@0 509 */
aoqi@0 510 Entry(final V key, final ReferenceQueue<V> queue, final int hash, final Entry<V> next)
aoqi@0 511 {
aoqi@0 512 super(key, queue);
aoqi@0 513 this.hash = hash;
aoqi@0 514 this.next = next;
aoqi@0 515 }
aoqi@0 516
aoqi@0 517 public V getKey()
aoqi@0 518 {
aoqi@0 519 return super.get();
aoqi@0 520 }
aoqi@0 521
aoqi@0 522 public boolean equals(Object o)
aoqi@0 523 {
aoqi@0 524 if (!(o instanceof WeakPool.Entry))
aoqi@0 525 {
aoqi@0 526 return false;
aoqi@0 527 }
aoqi@0 528 WeakPool.Entry<V> that = (WeakPool.Entry<V>) o;
aoqi@0 529 V k1 = this.getKey();
aoqi@0 530 V k2 = that.getKey();
aoqi@0 531 return (k1==k2 || k1.equals(k2));
aoqi@0 532 }
aoqi@0 533
aoqi@0 534 public int hashCode()
aoqi@0 535 {
aoqi@0 536 return this.hash;
aoqi@0 537 }
aoqi@0 538
aoqi@0 539 public String toString()
aoqi@0 540 {
aoqi@0 541 return String.valueOf(this.getKey());
aoqi@0 542 }
aoqi@0 543 }
aoqi@0 544 }
aoqi@0 545
aoqi@0 546 final class MultiSynonymKey {
aoqi@0 547 private List<MyList> keys;
aoqi@0 548
aoqi@0 549 public MultiSynonymKey() {
aoqi@0 550 keys = new ArrayList<MyList>();
aoqi@0 551 }
aoqi@0 552
aoqi@0 553 public MultiSynonymKey(MyList... arg) {
aoqi@0 554 keys = Arrays.asList(arg);
aoqi@0 555 }
aoqi@0 556
aoqi@0 557 public List<MyList> getKeys() {
aoqi@0 558 return keys;
aoqi@0 559 }
aoqi@0 560
aoqi@0 561 public int hashCode() {
aoqi@0 562 return this.getKeys().hashCode();
aoqi@0 563 }
aoqi@0 564
aoqi@0 565 public boolean equals(Object obj) {
aoqi@0 566 if (this == obj) {
aoqi@0 567 return true;
aoqi@0 568 }
aoqi@0 569
aoqi@0 570 if (!(obj instanceof MultiSynonymKey)) {
aoqi@0 571 return false;
aoqi@0 572 }
aoqi@0 573
aoqi@0 574 MultiSynonymKey that = (MultiSynonymKey) obj;
aoqi@0 575 return this.getKeys().equals(that.getKeys());
aoqi@0 576 }
aoqi@0 577
aoqi@0 578 public String toString() {
aoqi@0 579 return this.getClass().getName() + this.getKeys().toString();
aoqi@0 580 }
aoqi@0 581 }
aoqi@0 582
aoqi@0 583 public class Test extends Thread {
aoqi@0 584 static public Test test;
aoqi@0 585 static private byte[] arg1;
aoqi@0 586 static private byte[] arg2;
aoqi@0 587 static public WeakPool<MultiSynonymKey> wp;
aoqi@0 588 public volatile MultiSynonymKey ml1;
aoqi@0 589 public volatile MultiSynonymKey ml2;
aoqi@0 590 private volatile MultiSynonymKey ml3;
aoqi@0 591
aoqi@0 592 public void run() {
aoqi@0 593 int count=0;
aoqi@0 594 while (true) {
aoqi@0 595 try {
aoqi@0 596 Thread.sleep(10);
aoqi@0 597 } catch (Exception e) {}
aoqi@0 598 synchronized (wp) {
aoqi@0 599 ml2 = new MultiSynonymKey(new DoubletonList(new String(arg1), new String(arg2)));
aoqi@0 600 wp.put(ml2);
aoqi@0 601 ml3 = new MultiSynonymKey(new DoubletonList(new String(arg1), new String(arg2)));
aoqi@0 602 }
aoqi@0 603 try {
aoqi@0 604 Thread.sleep(10);
aoqi@0 605 } catch (Exception e) {}
aoqi@0 606 synchronized (wp) {
aoqi@0 607 ml1 = new MultiSynonymKey(new SingletonList(new String(arg1)));
aoqi@0 608 wp.put(ml1);
aoqi@0 609 ml3 = new MultiSynonymKey(new SingletonList(new String(arg1)));
aoqi@0 610 }
aoqi@0 611 if (count++==100)
aoqi@0 612 System.exit(95);
aoqi@0 613 }
aoqi@0 614 }
aoqi@0 615
aoqi@0 616 public static void main(String[] args) throws Exception {
aoqi@0 617 wp = new WeakPool<MultiSynonymKey>();
aoqi@0 618 test = new Test();
aoqi@0 619
aoqi@0 620 test.arg1 = args[0].getBytes();
aoqi@0 621 test.arg2 = args[1].getBytes();
aoqi@0 622
aoqi@0 623 test.ml1 = new MultiSynonymKey(new SingletonList(new String(test.arg1)));
aoqi@0 624 test.ml2 = new MultiSynonymKey(new DoubletonList(new String(test.arg1), new String(test.arg2)));
aoqi@0 625 test.ml3 = new MultiSynonymKey(new DoubletonList(new String(test.arg1), new String(test.arg2)));
aoqi@0 626
aoqi@0 627 wp.put(test.ml1);
aoqi@0 628 wp.put(test.ml2);
aoqi@0 629
aoqi@0 630 test.setDaemon(true);
aoqi@0 631 test.start();
aoqi@0 632
aoqi@0 633 int counter = 0;
aoqi@0 634 while (true) {
aoqi@0 635 synchronized (wp) {
aoqi@0 636 MultiSynonymKey foo = test.ml3;
aoqi@0 637
aoqi@0 638 if (wp.put(foo) == foo) {
aoqi@0 639 // System.out.println("foo " + counter);
aoqi@0 640 // System.out.println(foo);
aoqi@0 641 }
aoqi@0 642 }
aoqi@0 643 counter++;
aoqi@0 644 }
aoqi@0 645 }
aoqi@0 646
aoqi@0 647 private boolean eq(Object x, Object y) {
aoqi@0 648 return x == y || x.equals(y);
aoqi@0 649 }
aoqi@0 650 }

mercurial