mirror of
https://github.com/Jozufozu/Flywheel.git
synced 2025-01-14 16:26:07 +01:00
We do a little thieving
- Reimplement stealInstance.
This commit is contained in:
parent
8221616eff
commit
c8590629a1
3 changed files with 55 additions and 4 deletions
|
@ -24,6 +24,19 @@ public interface Instancer<I extends Instance> {
|
||||||
*/
|
*/
|
||||||
I createInstance();
|
I createInstance();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Steal an instance from another instancer.
|
||||||
|
* <br>
|
||||||
|
* This has the effect of swapping the instance's model in-place.
|
||||||
|
* <br><br>
|
||||||
|
* If the given instance is already owned by this instancer, this method does nothing.
|
||||||
|
* <br>
|
||||||
|
* If the given instance was created by a different backend, the behavior of this method is undefined.
|
||||||
|
*
|
||||||
|
* @param instance The instance to steal.
|
||||||
|
*/
|
||||||
|
void stealInstance(I instance);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Populate arr with new instances of this model.
|
* Populate arr with new instances of this model.
|
||||||
*
|
*
|
||||||
|
|
|
@ -29,13 +29,51 @@ public abstract class AbstractInstancer<I extends Instance> implements Instancer
|
||||||
var handle = new InstanceHandleImpl(this, i);
|
var handle = new InstanceHandleImpl(this, i);
|
||||||
I instance = type.create(handle);
|
I instance = type.create(handle);
|
||||||
|
|
||||||
instances.add(instance);
|
addLocked(instance, handle);
|
||||||
handles.add(handle);
|
|
||||||
changed.set(i);
|
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void stealInstance(I instance) {
|
||||||
|
var instanceHandle = instance.handle();
|
||||||
|
|
||||||
|
if (!(instanceHandle instanceof InstanceHandleImpl handle)) {
|
||||||
|
// UB: do nothing
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (handle.instancer == this) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: in theory there could be a race condition here if the instance
|
||||||
|
// is somehow being stolen by 2 different instancers between threads.
|
||||||
|
// That seems kinda impossible so I'm fine leaving it as is for now.
|
||||||
|
|
||||||
|
// Remove the instance from its old instancer.
|
||||||
|
// This won't have any unwanted effect when the old instancer
|
||||||
|
// is filtering deleted instances later, so is safe.
|
||||||
|
handle.setDeleted();
|
||||||
|
|
||||||
|
// Only lock now that we'll be mutating our state.
|
||||||
|
synchronized (lock) {
|
||||||
|
// Add the instance to this instancer.
|
||||||
|
handle.instancer = this;
|
||||||
|
handle.index = instances.size();
|
||||||
|
addLocked(instance, handle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calls must be synchronized on {@link #lock}.
|
||||||
|
*/
|
||||||
|
private void addLocked(I instance, InstanceHandleImpl handle) {
|
||||||
|
instances.add(instance);
|
||||||
|
handles.add(handle);
|
||||||
|
changed.set(handle.index);
|
||||||
|
}
|
||||||
|
|
||||||
public int getInstanceCount() {
|
public int getInstanceCount() {
|
||||||
return instances.size();
|
return instances.size();
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ package com.jozufozu.flywheel.backend.engine;
|
||||||
import com.jozufozu.flywheel.api.instance.InstanceHandle;
|
import com.jozufozu.flywheel.api.instance.InstanceHandle;
|
||||||
|
|
||||||
public class InstanceHandleImpl implements InstanceHandle {
|
public class InstanceHandleImpl implements InstanceHandle {
|
||||||
public final AbstractInstancer<?> instancer;
|
public AbstractInstancer<?> instancer;
|
||||||
public int index;
|
public int index;
|
||||||
|
|
||||||
public InstanceHandleImpl(AbstractInstancer<?> instancer, int index) {
|
public InstanceHandleImpl(AbstractInstancer<?> instancer, int index) {
|
||||||
|
|
Loading…
Reference in a new issue