|
19 | 19 |
|
20 | 20 | package org.jboss.logmanager; |
21 | 21 |
|
| 22 | +import org.wildfly.common.Assert; |
22 | 23 | import org.wildfly.common.ref.PhantomReference; |
23 | 24 | import org.wildfly.common.ref.Reaper; |
24 | 25 | import org.wildfly.common.ref.Reference; |
25 | 26 |
|
26 | 27 | import java.util.Collection; |
27 | | -import java.util.Collections; |
28 | 28 | import java.util.Enumeration; |
29 | | -import java.util.HashMap; |
30 | 29 | import java.util.Iterator; |
31 | | -import java.util.Map; |
32 | 30 | import java.util.Set; |
33 | 31 | import java.util.concurrent.ConcurrentHashMap; |
34 | 32 | import java.util.concurrent.ConcurrentMap; |
@@ -95,19 +93,29 @@ public void reap(Reference<Logger, LoggerNode> reference) { |
95 | 93 | private final Set<Reference<Logger, LoggerNode>> activeLoggers = ConcurrentHashMap.newKeySet(); |
96 | 94 |
|
97 | 95 | /** |
98 | | - * The attachments map. |
| 96 | + * The first attachment key. |
99 | 97 | */ |
100 | | - private volatile Map<Logger.AttachmentKey, Object> attachments = Collections.emptyMap(); |
| 98 | + private Logger.AttachmentKey<?> attachmentKey1; |
101 | 99 |
|
102 | 100 | /** |
103 | | - * The atomic updater for the {@link #handlers} field. |
| 101 | + * The first attachment value. |
104 | 102 | */ |
105 | | - private static final AtomicArray<LoggerNode, Handler> handlersUpdater = AtomicArray.create(AtomicReferenceFieldUpdater.newUpdater(LoggerNode.class, Handler[].class, "handlers"), Handler.class); |
| 103 | + private Object attachmentValue1; |
| 104 | + |
| 105 | + /** |
| 106 | + * The second attachment key. |
| 107 | + */ |
| 108 | + private Logger.AttachmentKey<?> attachmentKey2; |
| 109 | + |
| 110 | + /** |
| 111 | + * The second attachment value. |
| 112 | + */ |
| 113 | + private Object attachmentValue2; |
106 | 114 |
|
107 | 115 | /** |
108 | | - * The atomic updater for the {@link #attachments} field. |
| 116 | + * The atomic updater for the {@link #handlers} field. |
109 | 117 | */ |
110 | | - private static final AtomicReferenceFieldUpdater<LoggerNode, Map> attachmentsUpdater = AtomicReferenceFieldUpdater.newUpdater(LoggerNode.class, Map.class, "attachments"); |
| 118 | + private static final AtomicArray<LoggerNode, Handler> handlersUpdater = AtomicArray.create(AtomicReferenceFieldUpdater.newUpdater(LoggerNode.class, Handler[].class, "handlers"), Handler.class); |
111 | 119 |
|
112 | 120 | /** |
113 | 121 | * The actual level. May only be modified when the context's level change lock is held; in addition, changing |
@@ -176,7 +184,10 @@ public void close() { |
176 | 184 | handlersUpdater.clear(this); |
177 | 185 | useParentFilter = false; |
178 | 186 | useParentHandlers = true; |
179 | | - attachmentsUpdater.get(this).clear(); |
| 187 | + attachmentKey1 = null; |
| 188 | + attachmentValue1 = null; |
| 189 | + attachmentKey2 = null; |
| 190 | + attachmentValue2 = null; |
180 | 191 | children.clear(); |
181 | 192 | } |
182 | 193 | } |
@@ -379,76 +390,82 @@ Level getLevel() { |
379 | 390 |
|
380 | 391 | @SuppressWarnings({ "unchecked" }) |
381 | 392 | <V> V getAttachment(final Logger.AttachmentKey<V> key) { |
382 | | - if (key == null) { |
383 | | - throw new NullPointerException("key is null"); |
| 393 | + Assert.checkNotNullParam("key", key); |
| 394 | + synchronized (this) { |
| 395 | + if (key == attachmentKey1) return (V) attachmentValue1; |
| 396 | + if (key == attachmentKey2) return (V) attachmentValue2; |
384 | 397 | } |
385 | | - final Map<Logger.AttachmentKey, Object> attachments = this.attachments; |
386 | | - return (V) attachments.get(key); |
| 398 | + return null; |
387 | 399 | } |
388 | 400 |
|
389 | 401 | @SuppressWarnings({ "unchecked" }) |
390 | 402 | <V> V attach(final Logger.AttachmentKey<V> key, final V value) { |
391 | | - if (key == null) { |
392 | | - throw new NullPointerException("key is null"); |
393 | | - } |
394 | | - if (value == null) { |
395 | | - throw new NullPointerException("value is null"); |
396 | | - } |
397 | | - Map<Logger.AttachmentKey, Object> oldAttachments; |
398 | | - Map<Logger.AttachmentKey, Object> newAttachments; |
| 403 | + Assert.checkNotNullParam("key", key); |
| 404 | + Assert.checkNotNullParam("value", value); |
399 | 405 | V old; |
400 | | - do { |
401 | | - oldAttachments = attachments; |
402 | | - newAttachments = new HashMap<>(oldAttachments); |
403 | | - old = (V) newAttachments.put(key, value); |
404 | | - } while (! attachmentsUpdater.compareAndSet(this, oldAttachments, newAttachments)); |
| 406 | + synchronized (this) { |
| 407 | + if (key == attachmentKey1) { |
| 408 | + old = (V) attachmentValue1; |
| 409 | + attachmentValue1 = value; |
| 410 | + } else if (key == attachmentKey2) { |
| 411 | + old = (V) attachmentValue2; |
| 412 | + attachmentValue2 = value; |
| 413 | + } else if (attachmentKey1 == null) { |
| 414 | + old = null; |
| 415 | + attachmentKey1 = key; |
| 416 | + attachmentValue1 = value; |
| 417 | + } else if (attachmentKey2 == null) { |
| 418 | + old = null; |
| 419 | + attachmentKey2 = key; |
| 420 | + attachmentValue2 = value; |
| 421 | + } else { |
| 422 | + throw attachmentsFull(); |
| 423 | + } |
| 424 | + } |
405 | 425 | return old; |
406 | 426 | } |
407 | 427 |
|
408 | 428 | @SuppressWarnings({ "unchecked" }) |
409 | 429 | <V> V attachIfAbsent(final Logger.AttachmentKey<V> key, final V value) { |
410 | | - if (key == null) { |
411 | | - throw new NullPointerException("key is null"); |
412 | | - } |
413 | | - if (value == null) { |
414 | | - throw new NullPointerException("value is null"); |
415 | | - } |
416 | | - Map<Logger.AttachmentKey, Object> oldAttachments; |
417 | | - Map<Logger.AttachmentKey, Object> newAttachments; |
418 | | - do { |
419 | | - oldAttachments = attachments; |
420 | | - if (oldAttachments.containsKey(key)) { |
421 | | - return (V) oldAttachments.get(key); |
| 430 | + Assert.checkNotNullParam("key", key); |
| 431 | + Assert.checkNotNullParam("value", value); |
| 432 | + V old; |
| 433 | + synchronized (this) { |
| 434 | + if (key == attachmentKey1) { |
| 435 | + old = (V) attachmentValue1; |
| 436 | + } else if (key == attachmentKey2) { |
| 437 | + old = (V) attachmentValue2; |
| 438 | + } else if (attachmentKey1 == null) { |
| 439 | + old = null; |
| 440 | + attachmentKey1 = key; |
| 441 | + attachmentValue1 = value; |
| 442 | + } else if (attachmentKey2 == null) { |
| 443 | + old = null; |
| 444 | + attachmentKey2 = key; |
| 445 | + attachmentValue2 = value; |
| 446 | + } else { |
| 447 | + throw attachmentsFull(); |
422 | 448 | } |
423 | | - newAttachments = new HashMap<>(oldAttachments); |
424 | | - newAttachments.put(key, value); |
425 | | - } while (! attachmentsUpdater.compareAndSet(this, oldAttachments, newAttachments)); |
426 | | - return null; |
| 449 | + } |
| 450 | + return old; |
427 | 451 | } |
428 | 452 |
|
429 | 453 | @SuppressWarnings({ "unchecked" }) |
430 | 454 | public <V> V detach(final Logger.AttachmentKey<V> key) { |
431 | | - if (key == null) { |
432 | | - throw new NullPointerException("key is null"); |
433 | | - } |
434 | | - Map<Logger.AttachmentKey, Object> oldAttachments; |
435 | | - Map<Logger.AttachmentKey, Object> newAttachments; |
436 | | - V result; |
437 | | - do { |
438 | | - oldAttachments = attachments; |
439 | | - result = (V) oldAttachments.get(key); |
440 | | - if (result == null) { |
441 | | - return null; |
442 | | - } |
443 | | - final int size = oldAttachments.size(); |
444 | | - if (size == 1) { |
445 | | - // special case - the new map is empty |
446 | | - newAttachments = Collections.emptyMap(); |
| 455 | + Assert.checkNotNullParam("key", key); |
| 456 | + V old; |
| 457 | + synchronized (this) { |
| 458 | + if (key == attachmentKey1) { |
| 459 | + old = (V) attachmentValue1; |
| 460 | + attachmentValue1 = null; |
| 461 | + } else if (key == attachmentKey2) { |
| 462 | + old = (V) attachmentValue2; |
| 463 | + attachmentValue2 = null; |
447 | 464 | } else { |
448 | | - newAttachments = new HashMap<Logger.AttachmentKey, Object>(oldAttachments); |
| 465 | + old = null; |
449 | 466 | } |
450 | | - } while (! attachmentsUpdater.compareAndSet(this, oldAttachments, newAttachments)); |
451 | | - return result; |
| 467 | + } |
| 468 | + return old; |
452 | 469 | } |
453 | 470 |
|
454 | 471 | String getFullName() { |
@@ -524,4 +541,8 @@ public String nextElement() { |
524 | 541 | } |
525 | 542 | }; |
526 | 543 | } |
| 544 | + |
| 545 | + static IllegalArgumentException attachmentsFull() { |
| 546 | + return new IllegalArgumentException("Attachments map is full"); |
| 547 | + } |
527 | 548 | } |
0 commit comments