1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty.util;
17
18 import java.util.concurrent.atomic.AtomicReference;
19 import java.util.concurrent.atomic.AtomicReferenceArray;
20 import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
21
22
23
24
25
26 public class DefaultAttributeMap implements AttributeMap {
27
28 @SuppressWarnings("rawtypes")
29 private static final AtomicReferenceFieldUpdater<DefaultAttributeMap, AtomicReferenceArray> updater =
30 AtomicReferenceFieldUpdater.newUpdater(DefaultAttributeMap.class, AtomicReferenceArray.class, "attributes");
31
32 private static final int BUCKET_SIZE = 4;
33 private static final int MASK = BUCKET_SIZE - 1;
34
35
36 @SuppressWarnings("UnusedDeclaration")
37 private volatile AtomicReferenceArray<DefaultAttribute<?>> attributes;
38
39 @SuppressWarnings("unchecked")
40 @Override
41 public <T> Attribute<T> attr(AttributeKey<T> key) {
42 if (key == null) {
43 throw new NullPointerException("key");
44 }
45 AtomicReferenceArray<DefaultAttribute<?>> attributes = this.attributes;
46 if (attributes == null) {
47
48 attributes = new AtomicReferenceArray<DefaultAttribute<?>>(BUCKET_SIZE);
49
50 if (!updater.compareAndSet(this, null, attributes)) {
51 attributes = this.attributes;
52 }
53 }
54
55 int i = index(key);
56 DefaultAttribute<?> head = attributes.get(i);
57 if (head == null) {
58
59
60 head = new DefaultAttribute();
61 DefaultAttribute<T> attr = new DefaultAttribute<T>(head, key);
62 head.next = attr;
63 attr.prev = head;
64 if (attributes.compareAndSet(i, null, head)) {
65
66 return attr;
67 } else {
68 head = attributes.get(i);
69 }
70 }
71
72 synchronized (head) {
73 DefaultAttribute<?> curr = head;
74 for (;;) {
75 DefaultAttribute<?> next = curr.next;
76 if (next == null) {
77 DefaultAttribute<T> attr = new DefaultAttribute<T>(head, key);
78 curr.next = attr;
79 attr.prev = curr;
80 return attr;
81 }
82
83 if (next.key == key && !next.removed) {
84 return (Attribute<T>) next;
85 }
86 curr = next;
87 }
88 }
89 }
90
91 private static int index(AttributeKey<?> key) {
92 return key.id() & MASK;
93 }
94
95 @SuppressWarnings("serial")
96 private static final class DefaultAttribute<T> extends AtomicReference<T> implements Attribute<T> {
97
98 private static final long serialVersionUID = -2661411462200283011L;
99
100
101 private final DefaultAttribute<?> head;
102 private final AttributeKey<T> key;
103
104
105 private DefaultAttribute<?> prev;
106 private DefaultAttribute<?> next;
107
108
109 private volatile boolean removed;
110
111 DefaultAttribute(DefaultAttribute<?> head, AttributeKey<T> key) {
112 this.head = head;
113 this.key = key;
114 }
115
116
117 DefaultAttribute() {
118 head = this;
119 key = null;
120 }
121
122 @Override
123 public AttributeKey<T> key() {
124 return key;
125 }
126
127 @Override
128 public T setIfAbsent(T value) {
129 while (!compareAndSet(null, value)) {
130 T old = get();
131 if (old != null) {
132 return old;
133 }
134 }
135 return null;
136 }
137
138 @Override
139 public T getAndRemove() {
140 removed = true;
141 T oldValue = getAndSet(null);
142 remove0();
143 return oldValue;
144 }
145
146 @Override
147 public void remove() {
148 removed = true;
149 set(null);
150 remove0();
151 }
152
153 private void remove0() {
154 synchronized (head) {
155 if (prev == null) {
156
157 return;
158 }
159
160 prev.next = next;
161
162 if (next != null) {
163 next.prev = prev;
164 }
165
166
167
168 prev = null;
169 next = null;
170 }
171 }
172 }
173 }