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 }