Skip to content

Minor changes to MixinMapGenStructure. - #932

Open
BallOfEnergy1 wants to merge 2 commits into
GTNewHorizons:masterfrom
BallOfEnergy1:map-gen-structure
Open

Minor changes to MixinMapGenStructure.#932
BallOfEnergy1 wants to merge 2 commits into
GTNewHorizons:masterfrom
BallOfEnergy1:map-gen-structure

Conversation

@BallOfEnergy1

Copy link
Copy Markdown
Contributor
  • Replace field with @Share for thread-safety.
  • Replace @WrapOperation with @Redirect, as original was never being used.
  • Replaced Long2ObjectOpenHashMap cast with a cast to the more generic Long2ObjectMap for inter-mod compatibility

- Replace field with `@Share` for thread-safety.
- Replace `@WrapOperation` with `@Redirect`, as `original` was never being used.
- Replaced `Long2ObjectOpenHashMap` cast with a cast to the more generic `Long2ObjectMap` for inter-mod compatibility
return ((Long2ObjectOpenHashMap<StructureStart>) structureMap).put(hodgepodge$localRef, (StructureStart) v);
private Object hodgepodge$primitiveContains(Map<Long, StructureStart> instance, Object k, Object v,
@Share("unboxedLong") LocalLongRef unboxedLong) {
return ((Long2ObjectMap<StructureStart>) structureMap).put(unboxedLong.get(), (StructureStart) v);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think changing the cast of structureMap is a good idea, given that Long2ObjectOpenHashMap is the best map to use in this circumstance, and that this cast allows us to perform a non-interface virtual call (which is faster than an interface virtual call.)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The purpose behind changing this to a more generic cast is for mod compatibility, as one of my mods (Spool) needs to synchronize this map. The performance difference does exist, but it should be negligible in this code as it's not a particularly hot spot.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, what class do you use instead of Long2ObjectOpenHashMap? Do you have some kind of custom implementation of a ConcurrentHashMap for this?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a custom implementation of a Read-Write locked Long2ObjectMap<T>. A similar replacement was already performed in #930.

Operation<Boolean> original) {
return ((Long2ObjectOpenHashMap<StructureStart>) structureMap).containsKey(hodgepodge$localRef);
@Share("unboxedLong") LocalLongRef unboxedLong) {
return ((Long2ObjectMap<StructureStart>) structureMap).containsKey(unboxedLong.get());

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I see a potential problem. This world generator checks containsKey, and if the key is missing, it uses put to create that key. However, any naive concurrent map implementation would treat these two operations as independent, thus allowing for two threads to both detect that the map is missing the key and both attempt to generate that structure at the same time.

Since I assume you don't want that, you might need to re-implement this mixin yourself in order to handle this edge-case. (By locking the map on the first call and only unlocking it after the put, or creating the key with an atomic computeIfAbsent to add a placeholder, or by moving the rest of the method into the computeIfAbsent call using @WrapMethod.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants