From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Martijn Muijsers Date: Sun, 4 Dec 2022 14:42:26 +0100 Subject: [PATCH] Thread-safety annotations License: AGPL-3.0 (https://www.gnu.org/licenses/agpl-3.0.html) Gale - https://galemc.org diff --git a/src/main/java/org/galemc/gale/executor/annotation/Access.java b/src/main/java/org/galemc/gale/executor/annotation/Access.java new file mode 100644 index 0000000000000000000000000000000000000000..d07f68ff73a368c8f0da56152021a95474a601ca --- /dev/null +++ b/src/main/java/org/galemc/gale/executor/annotation/Access.java @@ -0,0 +1,39 @@ +// Gale - thread-safety annotations + +package org.galemc.gale.executor.annotation; + +/** + * An enum to distinguish the type of field access that a thread-safety annotation describes. + * + * @author Martijn Muijsers under AGPL-3.0 + */ +public enum Access { + + /** + * If the annotation is applied to a field, it holds for access to the field's value. + *
+ * This may or may not extend to conceptual access rather than field value access: for instance, if the field is + * a list, accessing elements of the list, or if the field is an object reference, + * accessing field of that reference. + */ + READ, + /** + * If the annotation is applied to a field, it holds for modifications made to the field. + *
+ * This may or may not extend to conceptual modifications rather than setting the field value: for instance, + * if the field is a list, adding elements to the list, or if the field is an object reference, + * setting fields of that reference. + */ + WRITE, + /** + * Both {@link #READ} and {@link #WRITE}: if the annotation is applied to a field, it holds for both access to + * the field's value, as well as modifications made to the field. + *
+ * This may or may not extend to conceptual access and/or modifications. + * + * @see #READ + * @see #WRITE + */ + READ_WRITE; + +} diff --git a/src/main/java/org/galemc/gale/executor/annotation/Guarded.java b/src/main/java/org/galemc/gale/executor/annotation/Guarded.java new file mode 100644 index 0000000000000000000000000000000000000000..37365e1fd6042dc721d875021b4092410f095ca5 --- /dev/null +++ b/src/main/java/org/galemc/gale/executor/annotation/Guarded.java @@ -0,0 +1,45 @@ +// Gale - thread-safety annotations + +package org.galemc.gale.executor.annotation; + +import org.galemc.gale.executor.annotation.thread.ThreadRestricted; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Target; + +/** + * An annotation primarily for fields, identifying fields that can only be accessed and/or modified when the + * described lock is acquired by the current thread. + *
+ * When applied to a method, this annotation indicates that calls to the method must happen only when the described + * lock is acquired by the current thread. This annotation does NOT mean that the method will acquire the lock + * in its method body. + *
+ * When applied to a class, this annotation indicates it holds for all methods and fields, both instance and static, + * belonging to the class, or any superclass thereof, or any inner or statically nested class of the class or + * any superclass thereof, except for any cases where a conflicting annotation with a smaller scope is also present. + * + * @author Martijn Muijsers under AGPL-3.0 + */ +@Documented +@Target({ElementType.FIELD, ElementType.METHOD, ElementType.TYPE}) +public @interface Guarded { + + /** + * @return A description of the lock that the annotated element is guarded by: typically a Javadoc reference + * to a field, e.g. "#statusLock". + */ + String value(); + + /** + * @see ThreadRestricted#fieldAccess() + */ + Access fieldAccess() default Access.READ_WRITE; + + /** + * @return A description of in what scenario the lock described by this annotation is not needed to be acquired. + */ + String except() default ""; + +} diff --git a/src/main/java/org/galemc/gale/executor/annotation/PotentiallyBlocking.java b/src/main/java/org/galemc/gale/executor/annotation/PotentiallyBlocking.java new file mode 100644 index 0000000000000000000000000000000000000000..71f26852c96dea34ea07efe07f834f8262509957 --- /dev/null +++ b/src/main/java/org/galemc/gale/executor/annotation/PotentiallyBlocking.java @@ -0,0 +1,39 @@ +// Gale - thread-safety annotations + +package org.galemc.gale.executor.annotation; + +import org.galemc.gale.executor.thread.BaseThread; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Target; + +/** + * An annotation primarily for methods, identifying methods that may block the thread. + *
+ * When applied to a class, this annotation indicates it holds for all methods, both instance and static, + * belonging to the class, or any superclass thereof, or any inner or statically nested class of the class or + * any superclass thereof, except for any cases where a conflicting annotation with a smaller scope is also present. + *
+ * In a method annotated with {@link PotentiallyBlocking}, fields and methods annotated with + * {@link PotentiallyBlocking}, {@link PotentiallyYielding} or {@link YieldFree} may all be used. + *
+ * Methods that are potentially blocking, including those annotated with {@link PotentiallyBlocking}, must never + * be called on a {@link BaseThread}. + * + * @author Martijn Muijsers under AGPL-3.0 + */ +@Documented +@Target({ElementType.METHOD, ElementType.TYPE}) +public @interface PotentiallyBlocking { + + /** + * @return A description of when the described method is potentially blocking. + * When describing conditions, the description should make clear whether those conditions must hold for the method + * to block, or make blocking more likely, or will certainly lead the method to block, or preclude the method + * from blocking, or have some other relation to the expectation of blocking. + * If left empty (as default), the method potentially blocks under any conditions. + */ + String value() default ""; + +} diff --git a/src/main/java/org/galemc/gale/executor/annotation/PotentiallyYielding.java b/src/main/java/org/galemc/gale/executor/annotation/PotentiallyYielding.java new file mode 100644 index 0000000000000000000000000000000000000000..e87ee2612348fc559b21256cc7cadfc684f01f8e --- /dev/null +++ b/src/main/java/org/galemc/gale/executor/annotation/PotentiallyYielding.java @@ -0,0 +1,35 @@ +// Gale - thread-safety annotations + +package org.galemc.gale.executor.annotation; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Target; + +/** + * An annotation primarily for methods, identifying methods that do not block, but may yield to other tasks + * under certain circumstances, such as when attempting to acquire a {@link YieldingLock}. + *
+ * When applied to a class, this annotation indicates it holds for all methods, both instance and static, + * belonging to the class, or any superclass thereof, or any inner or statically nested class of the class or + * any superclass thereof, except for any cases where a conflicting annotation with a smaller scope is also present. + *
+ * In a method annotated with {@link PotentiallyYielding}, the only methods that can be called are those + * annotated with {@link PotentiallyYielding} or {@link YieldFree}. + * + * @author Martijn Muijsers under AGPL-3.0 + */ +@Documented +@Target({ElementType.METHOD, ElementType.TYPE}) +public @interface PotentiallyYielding { + + /** + * @return A description of when the described method is potentially yielding. + * When describing conditions, the description should make clear whether those conditions must hold for the method + * to yield, or make yielding more likely, or will certainly lead the method to yield, or preclude the method + * from yielding, or have some other relation to the expectation of yielding. + * If left empty (as default), the method potentially yields under any conditions. + */ + String value() default ""; + +} diff --git a/src/main/java/org/galemc/gale/executor/annotation/YieldFree.java b/src/main/java/org/galemc/gale/executor/annotation/YieldFree.java new file mode 100644 index 0000000000000000000000000000000000000000..dc660a3fb401fc3cb713a4556468fd6686e29c51 --- /dev/null +++ b/src/main/java/org/galemc/gale/executor/annotation/YieldFree.java @@ -0,0 +1,27 @@ +// Gale - thread-safety annotations + +package org.galemc.gale.executor.annotation; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Target; +import java.util.concurrent.locks.Lock; + +/** + * An annotation primarily for methods, identifying methods that do not block, and are yield-free, i.e. that never + * yield to other tasks. Such a method may still speculatively attempt to acquire blocking locks or yielding locks, + * e.g. using {@link Lock#tryLock}, under the condition that failure to acquire the lock does not cause blocking + * or yielding. + *
+ * When applied to a class, this annotation indicates it holds for all methods, both instance and static, + * belonging to the class, or any superclass thereof, or any inner or statically nested class of the class or + * any superclass thereof, except for any cases where a conflicting annotation with a smaller scope is also present. + *
+ * In a method annotated with {@link PotentiallyYielding}, the only methods that can be called are those + * annotated with {@link YieldFree}. + * + * @author Martijn Muijsers under AGPL-3.0 + */ +@Documented +@Target({ElementType.METHOD, ElementType.TYPE}) +public @interface YieldFree {} diff --git a/src/main/java/org/galemc/gale/executor/annotation/thread/AnyThreadSafe.java b/src/main/java/org/galemc/gale/executor/annotation/thread/AnyThreadSafe.java new file mode 100644 index 0000000000000000000000000000000000000000..f9f4deeb3edce30a8052172c0b2be905bbd90844 --- /dev/null +++ b/src/main/java/org/galemc/gale/executor/annotation/thread/AnyThreadSafe.java @@ -0,0 +1,42 @@ +// Gale - thread-safety annotations + +package org.galemc.gale.executor.annotation.thread; + +import org.galemc.gale.executor.annotation.Access; +import org.galemc.gale.executor.annotation.PotentiallyBlocking; +import org.galemc.gale.executor.annotation.PotentiallyYielding; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Target; + +/** + * An annotation primarily for methods, identifying methods that can safely called from any thread, + * including but not limited to threads that are yielding. + *
+ * When applied to a field, this annotation indicates that the field can be safely arbitrarily accessed and/or modified + * from any thread. + *
+ * When applied to a class, this annotation indicates it holds for all methods and fields, both instance and static, + * belonging to the class, or any superclass thereof, or any inner or statically nested class of the class or + * any superclass thereof, except for any cases where a conflicting annotation with a smaller scope is also present. + *
+ * In a method annotated with {@link AnyThreadSafe}, the only fields and methods that can be used are those + * annotated with {@link AnyThreadSafe}, unless extra safety guarantees are checked or explicitly provided. + * Use of methods that are potentially yielding (at least those annotated with {@link PotentiallyYielding}, but also + * those annotated with {@link PotentiallyBlocking} that potentially yield) is discouraged, + * because some threads cannot yield, and must block instead, + * leading to context switches where none may be expected. + * + * @author Martijn Muijsers under AGPL-3.0 + */ +@Documented +@Target({ElementType.METHOD, ElementType.TYPE, ElementType.FIELD}) +public @interface AnyThreadSafe { + + /** + * @see ThreadRestricted#fieldAccess() + */ + Access value() default Access.READ_WRITE; + +} diff --git a/src/main/java/org/galemc/gale/executor/annotation/thread/ThisThreadOnly.java b/src/main/java/org/galemc/gale/executor/annotation/thread/ThisThreadOnly.java new file mode 100644 index 0000000000000000000000000000000000000000..2544ec2ef1d401696d61c6c75b72f79ffbb21e87 --- /dev/null +++ b/src/main/java/org/galemc/gale/executor/annotation/thread/ThisThreadOnly.java @@ -0,0 +1,32 @@ +// Gale - thread-safety annotations + +package org.galemc.gale.executor.annotation.thread; + +import org.galemc.gale.executor.annotation.Access; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Target; + +/** + * An annotation primarily for methods, identifying methods that can only be called from the + * enclosing {@link Thread} instance. + *
+ * This annotation can also be used on fields, similar to {@link ThreadRestricted}. + *
+ * This annotation can only be used within {@link Thread} or subclasses thereof. + * + * @see ThreadRestricted + * + * @author Martijn Muijsers under AGPL-3.0 + */ +@Documented +@Target({ElementType.METHOD, ElementType.FIELD}) +public @interface ThisThreadOnly { + + /** + * @see ThreadRestricted#fieldAccess() + */ + Access value() default Access.READ_WRITE; + +} diff --git a/src/main/java/org/galemc/gale/executor/annotation/thread/ThreadRestricted.java b/src/main/java/org/galemc/gale/executor/annotation/thread/ThreadRestricted.java new file mode 100644 index 0000000000000000000000000000000000000000..4a9df03bfa4d683ad32496a20b19ab53015e8d8f --- /dev/null +++ b/src/main/java/org/galemc/gale/executor/annotation/thread/ThreadRestricted.java @@ -0,0 +1,51 @@ +// Gale - thread-safety annotations + +package org.galemc.gale.executor.annotation.thread; + +import org.galemc.gale.executor.annotation.Access; +import org.galemc.gale.executor.annotation.PotentiallyBlocking; +import org.galemc.gale.executor.annotation.PotentiallyYielding; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Target; + +/** + * An annotation primarily for methods, identifying methods that can only be called on a specific thread or + * set of threads, as described by the given description. + *
+ * When applied to a field, this annotation indicates that the field can only be accessed and/or modified from the + * described specific thread or set of threads. + *
+ * When applied to a class, this annotation indicates it holds for all methods and fields, both instance and static, + * belonging to the class, or any superclass thereof, or any inner or statically nested class of the class or + * any superclass thereof, except for any cases where a conflicting annotation with a smaller scope is also present. + *
+ * In a method annotated with {@link ThreadRestricted}, the only fields and methods that can be used are those + * annotated with {@link ThreadRestricted} that have a similar or stricter condition, + * unless extra safety guarantees are checked or explicitly provided. + * Use of methods that are potentially yielding (at least those annotated with {@link PotentiallyYielding}, but also + * those annotated with {@link PotentiallyBlocking} that potentially yield), when the restriction allows for threads + * that are not yielding, is discouraged, because some threads cannot yield, and must block instead, + * leading to context switches where none may be expected. + * + * @author Martijn Muijsers under AGPL-3.0 + */ +@Documented +@Target({ElementType.METHOD, ElementType.TYPE, ElementType.FIELD}) +public @interface ThreadRestricted { + + /** + * @return A description of the thread or set of threads that this annotation describes a method or field + * being restricted to. + */ + String value(); + + /** + * @return What type of access this annotation describes, when it is applied to a field. + *
+ * This annotation describes all types of access ({@link Access#READ_WRITE}) by default. + */ + Access fieldAccess() default Access.READ_WRITE; + +}