1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty5.buffer.api.internal;
17
18 import io.netty5.buffer.api.Drop;
19
20 import java.lang.invoke.MethodHandles;
21 import java.lang.invoke.VarHandle;
22
23 public final class ArcDrop<T> implements Drop<T> {
24 private static final VarHandle COUNT;
25 static {
26 try {
27 COUNT = MethodHandles.lookup().findVarHandle(ArcDrop.class, "count", int.class);
28 } catch (Exception e) {
29 throw new ExceptionInInitializerError(e);
30 }
31 }
32
33 private final Drop<T> delegate;
34 @SuppressWarnings("FieldMayBeFinal")
35 private volatile int count;
36
37 public ArcDrop(Drop<T> delegate) {
38 this.delegate = delegate;
39 }
40
41 public static <X> Drop<X> wrap(Drop<X> drop) {
42 if (drop.getClass() == ArcDrop.class) {
43 return drop;
44 }
45 return new ArcDrop<>(drop);
46 }
47
48 public static <X> Drop<X> acquire(Drop<X> drop) {
49 if (drop.getClass() == ArcDrop.class) {
50 ((ArcDrop<X>) drop).increment();
51 return drop;
52 }
53 return new ArcDrop<>(drop);
54 }
55
56 public ArcDrop<T> increment() {
57 int c;
58 do {
59 c = count;
60 checkValidState(c);
61 } while (!COUNT.compareAndSet(this, c, c + 1));
62 return this;
63 }
64
65 @Override
66 public void drop(T obj) {
67 int c;
68 int n;
69 do {
70 c = count;
71 n = c - 1;
72 checkValidState(c);
73 } while (!COUNT.compareAndSet(this, c, n));
74 if (n == -1) {
75 delegate.drop(obj);
76 }
77 }
78
79 @Override
80 public Drop<T> fork() {
81 return increment();
82 }
83
84 @Override
85 public void attach(T obj) {
86 delegate.attach(obj);
87 }
88
89 public Drop<T> unwrap() {
90 return delegate;
91 }
92
93 @Override
94 public String toString() {
95 StringBuilder builder = new StringBuilder()
96 .append("ArcDrop@")
97 .append(Integer.toHexString(System.identityHashCode(this)))
98 .append('(').append(count).append(", ");
99 Drop<T> drop = this;
100 while ((drop = ((ArcDrop<T>) drop).unwrap()) instanceof ArcDrop) {
101 builder.append(((ArcDrop<T>) drop).count).append(", ");
102 }
103 return builder.append(drop).append(')').toString();
104 }
105
106 private static void checkValidState(int count) {
107 if (count == -1) {
108 throw new IllegalStateException("Underlying resources have already been freed.");
109 }
110 }
111 }