[SPIGOT-6784] (API) Documenting thread safety of methods and constructors in the Bukkit Api Created: 04/Nov/21  Updated: 15/Jan/22

Status: Open
Project: Spigot
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: New Feature Priority: Minor
Reporter: Lauriichan Assignee: Unassigned
Resolution: Unresolved Votes: 3
Labels: API

Version: This server is running CraftBukkit version 3238-Spigot-6c1c1b2-9217b52 (MC: 1.17.1) (Implementing API version 1.17.1-R0.1-SNAPSHOT)
Guidelines Read: Yes

 Description   

Working Repository: Bukkit Api on SyntaxPhoenix

Everyone is invited to help annotating the whole BukkitApi with the annotations related to this request:

  • FullThreadSafe
  • ContextThreadSafe
  • NonThreadSafe

 

Explanation:

FullThreadSafe:
A method or constructor is FullThreadSafe if that method or constructor can be called on any thread at any time in any context. Meaning there will be no Exception when running this method on multiple thread at the same time on the same object.

ContextThreadSafe:
A method or constructor is ContextThreadSafe if the method or constructor uses mutable variables. For example a ArrayList would be ContextThreadSafe. As the owner of the ArrayList can freely modify it and use it while other threads would mostly only be able to read from that List without causing any issues. Most of the time getters for variables of a mutable object can be considered FullThreadSafe however some cannot because of the way they retrieve the corresponding value.

NonThreadSafe:
A method or constructor is NonThreadSafe if the method or constructor can only be used on the Main Server Thread. For example stuff like "World.setBlock" would be such an example. 

 

UPDATE (15.01.2022):

We finally got time to work on this big project to annotate everything.
As of now there isn't much annotated, just some mutable objects and that's more or less it.

The Idea of adding those Annotations is to give developers that use the bukkit api a clear understanding on which method they can use in which context.
For example there are methods like "Bukkit.createBlockData()" which are in practice completely thread safe however you probably don't know that if you didn't look into the CraftBukkit source.

Therefore adding such documentation would help developers understand what they can or can not do.

Also this could lead to consistency along forks and Spigot. As of now some forks have different thread safety for different method compared to Spigot. Maybe by adding those annotations they will either modify those annotations so people that use their fork know as much as the people who use Spigot or they will adjust their code accordingly to the documented thread safety which would make those forks more compatible with Spigot plugins.

 

Small Info:

At the beginning this issue was mostly related to the Bukkit.createBlockData method. However just documenting one method makes no sense. Therefore I modified the description and title accordingly and added the concept discussed in the comments as well as the working repository above.



 Comments   
Comment by Lauriichan [ 15/Jan/22 ]

I got one important question, is there a some indication on which method is actually ThreadSafe?
I'm not as familiar with most of the Api which is why I can't really tell what is actually ThreadSafe and what not so if there is something I should know about that I could do a lot more annotating.

Maybe someone could tell me for example which packages contain Fully Thread Safe Classes or something like that?

EDIT: Right now there is almost nothing annotated since the lack of time over the last two months

Comment by Lauriichan [ 08/Nov/21 ]

oh yeah, you're right, I made it public now

And since we didn't really start yet you can just choose a package, create a branch and start working on it
I gave you write access to the repository

Comment by Marvin Rieple [ 07/Nov/21 ]

Your repo is private. Also if you can write a package which I should go through, it would probably help to prevent accidentally working on the same classes.

Comment by Lauriichan [ 07/Nov/21 ]

We could also rename the second one there is no problem with that.

If you have a better name for the thread safety of mutable objects then we can use that

Comment by md_5 [ 07/Nov/21 ]

I'm not sure. I would've suggested something with Context but you've already used that so not sure

Comment by Lauriichan [ 06/Nov/21 ]

Any Idea on how we could name a 4th annotation and their description?
I mean if its more clear then sure it would be great

Comment by md_5 [ 06/Nov/21 ]

Hmmm, I guess the argument is that you will never 'own' the context of a non thread safe server object. I guess its technically true (and makes this task a lot easier) but it is less clear.

Comment by Lauriichan [ 06/Nov/21 ]

> Good question, maybe we need a 4th option

Couldn't we combine that "single thread" and "context related" things into one annotation?

Comment by Lauriichan [ 06/Nov/21 ]

> Also careful about changing formatting in your repository Laurii, that could become a headache to undo down the track.
Suggest disabling auto format in your IDE.

Yeah I know, I already created a new workspace because of our code style so that I can use a different one for spigot.
Maybe I'll also disable it, don't know yet. I'll definitely not use a cleanup or format on the whole project as that will mess things up yeah

Comment by md_5 [ 06/Nov/21 ]

Also careful about changing formatting in your repository Laurii, that could become a headache to undo down the track.
Suggest disabling auto format in your IDE.

Comment by md_5 [ 06/Nov/21 ]

> One thing however which could be hard to annotate are methods which depend on the "context" / implementation. For example RegionAccessor#spawn or RegionAccessor#setType if the RegionAccessor is implemented by the World object those methods are only save to call on the server Thread. If however the RegionAccessor is implemented by LimitedRegion it is only save to call those methods with the Thread which provided the LimitedRegion. How would you annotate such methods?

Good question, maybe we need a 4th option

Comment by Lauriichan [ 06/Nov/21 ]

@Marvin Rieple

If you want to help annotating every method with the correct annotation then you can
visit our stash repository.

Right now we only added the annotations and added them to the Annotation test but we'll soon start annotating some methods and constructors

Comment by Lauriichan [ 06/Nov/21 ]

@md_5

I think a good way of naming everything is:
NonThreadSafe
ContextThreadSafe
FullThreadSafe

Comment by Lauriichan [ 06/Nov/21 ]

I think something like that would fall in the "SingleThreadSafe" category

Comment by Marvin Rieple [ 06/Nov/21 ]

I like this Idea since it makes clear which method can be called on an other Thread and which not. And maybe even leads to looking at some methods and try to make them thread safe in craftbukkit.

If you link the repo / branch your working with I'm willing to add annotation to some part of the bukkit api.

One thing however which could be hard to annotate are methods which depend on the "context" / implementation. For example RegionAccessor#spawn or RegionAccessor#setType if the RegionAccessor is implemented by the World object those methods are only save to call on the server Thread. If however the RegionAccessor is implemented by LimitedRegion it is only save to call those methods with the Thread which provided the LimitedRegion. How would you annotate such methods?

Comment by Lauriichan [ 04/Nov/21 ]

That should be no problem as there is already a annotation in use in the SpigotApi called Contract which uses a String parameter

See here: https://hub.spigotmc.org/javadocs/spigot/org/bukkit/block/banner/PatternType.html#getByIdentifier(java.lang.String)

But we could also use a annotation fur each should also be no problem at all
And I think it would also be possible to unit test the type of annotation that I sent above

Comment by md_5 [ 04/Nov/21 ]

> Like the Thread who currently owns the object is safe to use it?

Something like that, I'm not sure of a good name.

> Or maybe for non ThreadSafe operation just no annotation at all

Better to have one on everything so we can unit test it like null/notnull.

> Also about using a annotation for this, what about this layout:

Does enum level show in Javadocs? Java convention seems to be mostly Null/NotNull instead of Nullable(true/false) but I'm not fussed if it appears cleanly in javadocs/ IDEs.

Comment by Lauriichan [ 04/Nov/21 ]

How would you define Single Thread safe?
Like the Thread who currently owns the object is safe to use it?

Also about using a annotation for this, what about this layout:

 

package example;
import static java.lang.annotation.ElementType.CONSTRUCTOR;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.SOURCE;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
@Documented
@Retention(SOURCE)
@Target({
    METHOD,
    CONSTRUCTOR
})
public @interface ThreadSafety {
    SafetyLevel level();
    
}

 

package example;
public enum SafetyLevel {
    
    NONE,
    SINGLE,
    FULL;
}

Or maybe for non ThreadSafe operation just no annotation at all

Comment by md_5 [ 04/Nov/21 ]

> Documenting each and every method with such a annotation will consume a lot of time

It's been done before: https://hub.spigotmc.org/stash/projects/SPIGOT/repos/bukkit/commits/3f0591ead707879a05dac22aa958af75e7e1b97e

I think there needs to be three levels of thread safety:

  1. Fully thread safe (concurrent, scheduler, singletons, many constructors)
  2. Single thread safe (?, mostly mutable things like ItemStack, BlockData)
  3. Not thread safe (everything else)
Comment by Lauriichan [ 04/Nov/21 ]

I fully agree with your point.

Documenting each and every method with such a annotation will consume a lot of time but I think it would be good to start doing that especially since more people tend to do stuff on another Thread than the main server Thread.

I think if you agree with that opinion, we could start adding such a annotation in a PR after we signed the CLA

Comment by md_5 [ 04/Nov/21 ]

I think it's a whole lot more nuanced than that. Thread safe can mean a lot of things. To use the BlockData example, creating a new BlockData is thread safe in all senses. But manipulating a BlockData instance is thread safe in that it can be done off the server thread, but not thread safe in that it can be done concurrently.

I also think singling out BlockData for documentation is a bit weird. Bukkit.getServer() is thread safe too, but that's not documented. Same with many many many other methods (and a few constructors). At some point developers need to make a reasoned call and exercise thought. It's pretty clear that BlockData can be created off thread given we have an async world gen API.

If this were to be done my view is it should be done consistently by annotating every single method in the API, the way we have done with nullability. It's just otherwise not compelling to me why we would put documentation (which no one reads) in one specific method out of hundreds.

Comment by Sebastian Diers [ 04/Nov/21 ]

@md5 The change in the documentation would also affect some of spigots forks, that removed the Map that hold the BlockData for having 'more performance'. This in the end results in the method not beeing threadsafe. With the addition of async tasks in worldgenerators this leads to massive performance-issues as each call would need to be made sync or developers would need to store every Material theirself. So it is important, that the method is threadsafe and if spigot clearly defines the method threadsafe in their docs the forks will surely follow, as developers build for spigot and not the forks. 

Comment by Lauriichan [ 04/Nov/21 ]

> Um what do you mean marked thread safe?

With a note in the docs or maybe a annotation
Something like that

> What APIs are marked thread safe?

I don't really know if there is any really marked as Thread Safe as I didn't read the whole API but I think it would be nice if we could add such information to the docs so developers know what they can access from other threads without issues

Comment by md_5 [ 04/Nov/21 ]

> Especially when designing World-Generators this might give a performance boost.

Can you explain how documentation gives a performance boost?

Comment by md_5 [ 04/Nov/21 ]

Um what do you mean marked thread safe?
What APIs are marked thread safe?

Comment by Sebastian Diers [ 04/Nov/21 ]

Would definitely agree on that issue. Especially when designing World-Generators this might give a performance boost. I also see no reason why it should be not Threadsafe.

Generated at Sat Dec 13 15:25:57 UTC 2025 using Jira 10.3.13#10030013-sha1:56dd970ae30ebfeda3a697d25be1f6388b68a422.