Skip to content

Commit

Permalink
Make usage of stateful patterns thread-safe (#2633)
Browse files Browse the repository at this point in the history
* Make usage of No(Axis)Patterns thread-safe

* make more pattern usage thread-safe

* make more WE patterns thread safe

* remove StatefulPattern
  • Loading branch information
SirYwell committed Mar 27, 2024
1 parent 8095111 commit 7b8c789
Show file tree
Hide file tree
Showing 18 changed files with 117 additions and 1 deletion.
@@ -1,6 +1,7 @@
package com.fastasyncworldedit.core.function.pattern;

import com.sk89q.worldedit.function.pattern.AbstractPattern;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.internal.expression.EvaluationException;
import com.sk89q.worldedit.internal.expression.Expression;
import com.sk89q.worldedit.internal.expression.ExpressionException;
Expand Down Expand Up @@ -57,4 +58,9 @@ public BaseBlock applyBlock(BlockVector3 vector) {
}
}

@Override
public Pattern fork() {
return new ExpressionPattern(this.expression.clone());
}

}
Expand Up @@ -7,6 +7,8 @@
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.world.block.BaseBlock;

import java.util.Arrays;

import static java.lang.Math.floorDiv;

/**
Expand Down Expand Up @@ -52,4 +54,10 @@ public boolean apply(Extent extent, BlockVector3 get, BlockVector3 set) throws W
return patternsArray[index].apply(extent, get, set);
}

@Override
public Pattern fork() {
final Pattern[] forked = Arrays.stream(this.patternsArray).map(Pattern::fork).toArray(Pattern[]::new);
return new Linear2DBlockPattern(forked, this.xScale, this.zScale);
}

}
Expand Up @@ -7,6 +7,8 @@
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.world.block.BaseBlock;

import java.util.Arrays;

import static java.lang.Math.floorDiv;

/**
Expand Down Expand Up @@ -56,4 +58,10 @@ public boolean apply(Extent extent, BlockVector3 get, BlockVector3 set) throws W
return patternsArray[index].apply(extent, get, set);
}

@Override
public Pattern fork() {
final Pattern[] forked = Arrays.stream(this.patternsArray).map(Pattern::fork).toArray(Pattern[]::new);
return new Linear3DBlockPattern(forked, this.xScale, this.yScale, this.zScale);
}

}
Expand Up @@ -47,4 +47,10 @@ public void reset() {
index = 0;
}

@Override
public Pattern fork() {
final Pattern[] forked = Arrays.stream(this.patternsArray).map(Pattern::fork).toArray(Pattern[]::new);
return new LinearBlockPattern(forked);
}

}
Expand Up @@ -43,4 +43,9 @@ public boolean apply(Extent extent, BlockVector3 get, BlockVector3 set) throws W
return secondary.apply(extent, get, set);
}

@Override
public Pattern fork() {
return new MaskedPattern(this.mask.copy(), this.primary.fork(), this.secondary.fork());
}

}
Expand Up @@ -36,4 +36,9 @@ public boolean apply(Extent extent, BlockVector3 get, BlockVector3 set) throws W
return pattern.apply(extent, mutable, set);
}

@Override
public Pattern fork() {
return new NoXPattern(this.pattern.fork());
}

}
Expand Up @@ -36,4 +36,9 @@ public boolean apply(Extent extent, BlockVector3 get, BlockVector3 set) throws W
return pattern.apply(extent, mutable, set);
}

@Override
public Pattern fork() {
return new NoYPattern(this.pattern.fork());
}

}
@@ -1,6 +1,7 @@
package com.fastasyncworldedit.core.function.pattern;

import com.fastasyncworldedit.core.math.MutableBlockVector3;
import com.fastasyncworldedit.core.queue.Filter;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.function.pattern.AbstractPattern;
Expand Down Expand Up @@ -36,4 +37,9 @@ public boolean apply(Extent extent, BlockVector3 get, BlockVector3 set) throws W
return pattern.apply(extent, mutable, set);
}

@Override
public Pattern fork() {
return new NoZPattern(this.pattern.fork());
}

}
Expand Up @@ -60,4 +60,9 @@ public boolean apply(Extent extent, BlockVector3 get, BlockVector3 set) throws W
return pattern.apply(extent, get, mutable);
}

@Override
public Pattern fork() {
return new OffsetPattern(this.pattern.fork(), this.dx, this.dy, this.dz, this.minY, this.maxY);
}

}
Expand Up @@ -72,4 +72,9 @@ public boolean apply(Extent extent, BlockVector3 get, BlockVector3 set) throws W
return pattern.apply(extent, get, mutable);
}

@Override
public Pattern fork() {
return new RandomOffsetPattern(this.pattern.fork(), this.dx, this.dy, this.dz, this.minY, this.maxY);
}

}
Expand Up @@ -63,4 +63,11 @@ public void reset() {
origin = null;
}

@Override
public Pattern fork() {
RelativePattern forked = new RelativePattern(this.pattern.fork(), this.minY, this.maxY);
forked.origin = this.origin; // maintain origin for forks
return forked;
}

}
Expand Up @@ -94,4 +94,9 @@ public boolean apply(Extent extent, BlockVector3 get, BlockVector3 set) throws W
return pattern.apply(extent, get, set);
}

@Override
public Pattern fork() {
return new SolidRandomOffsetPattern(this.pattern.fork(), this.dx, this.dy, this.dz, this.minY, this.maxY);
}

}
Expand Up @@ -129,4 +129,9 @@ private boolean canPassthrough(BlockVector3 v) {
return !block.getBlockType().getMaterial().isMovementBlocker();
}

@Override
public Pattern fork() {
return new SurfaceRandomOffsetPattern(this.pattern.fork(), this.moves, this.minY, this.maxY);
}

}
Expand Up @@ -235,4 +235,11 @@ public Iterable<BlockVector2> asFlatRegion() {
};
}

//FAWE - stateful pattern
@Override
public Pattern fork() {
return new ForgetfulExtentBuffer(extent, mask.copy());
}
//FAWE end

}
Expand Up @@ -25,6 +25,8 @@
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.world.block.BaseBlock;

import java.util.Arrays;

import static com.google.common.base.Preconditions.checkArgument;

/**
Expand Down Expand Up @@ -64,4 +66,12 @@ public BaseBlock applyBlock(BlockVector3 position) {
return lastBlock;
}

//FAWE - stateful pattern
@Override
public Pattern fork() {
final Pattern[] forkedPatterns = Arrays.stream(patterns).map(Pattern::fork).toArray(Pattern[]::new);
return new ExtentBufferedCompositePattern(getExtent(), forkedPatterns);
}
//FAWE end

}
Expand Up @@ -59,6 +59,11 @@ default void applyBlock(final FilterBlock block) {
apply(block, block, block);
}

@Override
default Pattern fork() { // covariant return type
return this;
}

//FAWE end

/**
Expand Down
Expand Up @@ -67,6 +67,13 @@ public RandomPattern(SimpleRandom random, RandomPattern parent) {
this.collection = RandomCollection.of(weights, random);
this.patterns = parent.patterns;
}

private RandomPattern(SimpleRandom random, Map<Pattern, Double> weights) {
this.random = random;
this.weights = weights;
this.collection = RandomCollection.of(weights, random);
this.patterns = new LinkedHashSet<>(weights.keySet());
}
//FAWE end

/**
Expand Down Expand Up @@ -107,6 +114,14 @@ public BaseBlock applyBlock(BlockVector3 position) {
public boolean apply(Extent extent, BlockVector3 get, BlockVector3 set) throws WorldEditException {
return collection.next(get.getBlockX(), get.getBlockY(), get.getBlockZ()).apply(extent, get, set);
}

@Override
public Pattern fork() {
final LinkedHashMap<Pattern, Double> newWeights = new LinkedHashMap<>();
this.weights.forEach((p, w) -> newWeights.put(p.fork(), w));
return new RandomPattern(this.random, newWeights);
}

//FAWE end

}
Expand Up @@ -29,13 +29,16 @@

import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;

import static com.sk89q.worldedit.blocks.Blocks.resolveProperties;

public class StateApplyingPattern extends AbstractExtentPattern {

private final Map<String, String> states;
private final Map<BlockType, Map<Property<Object>, Object>> cache = Maps.newHashMap();
//FAWE - avoid race conditions
private final Map<BlockType, Map<Property<Object>, Object>> cache = new ConcurrentHashMap<>();
//FAWE end

public StateApplyingPattern(Extent extent, Map<String, String> statesToSet) {
super(extent);
Expand Down

0 comments on commit 7b8c789

Please sign in to comment.