View Javadoc
1   /*
2    * Copyright 2021 The Netty Project
3    *
4    * The Netty Project licenses this file to you under the Apache License,
5    * version 2.0 (the "License"); you may not use this file except in compliance
6    * with the License. You may obtain a copy of the License at:
7    *
8    *   https://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13   * License for the specific language governing permissions and limitations
14   * under the License.
15   */
16  package io.netty5.buffer.api.internal;
17  
18  import io.netty5.buffer.api.Drop;
19  import io.netty5.buffer.api.Owned;
20  import io.netty5.util.Resource;
21  import io.netty5.util.Send;
22  
23  import java.lang.invoke.VarHandle;
24  
25  import static io.netty5.buffer.api.internal.Statics.findVarHandle;
26  import static java.lang.invoke.MethodHandles.lookup;
27  
28  public class SendFromOwned<I extends Resource<I>, T extends ResourceSupport<I, T>> implements Send<I> {
29      private static final VarHandle RECEIVED = findVarHandle(lookup(), SendFromOwned.class, "received", boolean.class);
30      private final Owned<T> outgoing;
31      private final Drop<T> drop;
32      private final Class<?> concreteType;
33      @SuppressWarnings("unused")
34      private volatile boolean received; // Accessed via VarHandle
35  
36      public SendFromOwned(Owned<T> outgoing, Drop<T> drop, Class<?> concreteType) {
37          this.outgoing = outgoing;
38          this.drop = drop;
39          this.concreteType = concreteType;
40      }
41  
42      @SuppressWarnings("unchecked")
43      @Override
44      public I receive() {
45          gateReception();
46          var copy = outgoing.transferOwnership(drop);
47          drop.attach(copy);
48          return (I) copy;
49      }
50  
51      private void gateReception() {
52          if ((boolean) RECEIVED.getAndSet(this, true)) {
53              throw new IllegalStateException("This object has already been received.");
54          }
55      }
56  
57      @Override
58      public boolean referentIsInstanceOf(Class<?> cls) {
59          return cls.isAssignableFrom(concreteType);
60      }
61  
62      @Override
63      public void close() {
64          if (!(boolean) RECEIVED.getAndSet(this, true)) {
65              var copy = outgoing.transferOwnership(drop);
66              drop.attach(copy);
67              copy.close();
68          }
69      }
70  }