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.util;
17  
18  import io.netty5.util.internal.SendFromSupplier;
19  
20  import java.util.function.Function;
21  import java.util.function.Supplier;
22  
23  /**
24   * A temporary holder of a {@link Resource}, used for transferring the ownership of the
25   * resource from one thread to another.
26   * <p>
27   * Prior to the {@code Send} being created, the originating resource is invalidated, to prevent access while it is being
28   * sent. This means it cannot be accessed, closed, or disposed of, while it is in-flight. Once the resource is
29   * {@linkplain #receive() received}, the new ownership is established.
30   * <p>
31   * Care must be taken to ensure that the resource is always received by some thread.
32   * Failure to do so can result in a resource leak.
33   *
34   * @param <T>
35   */
36  public interface Send<T extends Resource<T>> extends SafeCloseable {
37      /**
38       * Construct a {@link Send} based on the given {@link Supplier}. The supplier will be called only once, in the
39       * receiving thread.
40       *
41       * @param concreteObjectType The concrete type of the object being sent. Specifically, the object returned from the
42       *                           {@link Supplier#get()} method must be an instance of this class.
43       * @param supplier           The supplier of the object being sent, which will be called when the object is ready to
44       *                           be received.
45       * @param <T>                The type of object being sent.
46       * @return A {@link Send} which will deliver an object of the given type, from the supplier.
47       */
48      static <T extends Resource<T>> Send<T> sending(Class<T> concreteObjectType, Supplier<? extends T> supplier) {
49          return new SendFromSupplier<>(concreteObjectType, supplier);
50      }
51  
52      /**
53       * Determine if the given candidate object is an instance of a {@link Send} from which an object of the given type
54       * can be received.
55       *
56       * @param type      The type of object we wish to receive.
57       * @param candidate The candidate object that might be a {@link Send} of an object of the given type.
58       * @return {@code true} if the candidate object is a {@link Send} that would deliver an object of the given type,
59       * otherwise {@code false}.
60       */
61      static boolean isSendOf(Class<?> type, Object candidate) {
62          return candidate instanceof Send && ((Send<?>) candidate).referentIsInstanceOf(type);
63      }
64  
65      /**
66       * Receive the {@link Resource} instance being sent, and bind its ownership to the calling thread.
67       * The invalidation of the sent resource in the sending thread happens-before the return of this method.
68       * <p>
69       * This method can only be called once, and will throw otherwise.
70       *
71       * @return The sent resource instance, never {@code null}.
72       * @throws IllegalStateException If this method is called more than once.
73       */
74      T receive();
75  
76      /**
77       * Apply a mapping function to the object being sent. The mapping will occur when the object is received.
78       *
79       * @param type   The result type of the mapping function.
80       * @param mapper The mapping function to apply to the object being sent.
81       * @param <R>    The result type of the mapping function.
82       * @return A new {@link Send} instance that will deliver an object that is the result of the mapping.
83       */
84      default <R extends Resource<R>> Send<R> map(Class<R> type, Function<T, R> mapper) {
85          return sending(type, () -> mapper.apply(receive()));
86      }
87  
88      /**
89       * Discard this {@link Send} and the object it contains.
90       * This has no effect if the send-object has already been received.
91       */
92      @Override
93      void close();
94  
95      /**
96       * Determine if the object received from this {@code Send} is an instance of the given class.
97       *
98       * @param cls The type to check.
99       * @return {@code true} if the object received from this {@code Send} can be assigned fields or variables of the
100      * given type, otherwise false.
101      */
102     boolean referentIsInstanceOf(Class<?> cls);
103 }