[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:
Explanation: FullThreadSafe: ContextThreadSafe: NonThreadSafe:
UPDATE (15.01.2022): We finally got time to work on this big project to annotate everything. 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. 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? 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 |
| 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? |
| 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. Yeah I know, I already created a new workspace because of our code style so that I can use a different one for spigot. |
| 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. |
| 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 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: |
| 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 But we could also use a annotation fur each should also be no problem at all |
| 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? 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:
|
| 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 > 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? |
| 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. |