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 }