takahirox / tiny-web-metaverse

A web-based 3D virtual space lightweight framework with high flexibility, extensibility, and easy hosting, built on ECS architecture
MIT License
118 stars 13 forks source link

Consider the chance of that resource can be shared when cleaning up #36

Open takahirox opened 9 months ago

takahirox commented 9 months ago

Cleaning up system code is like

const fooExitQuery = exitQuery(defineQuery([FooComponent]));

export const fooSystem = (world: IWorld): void => {
  fooExitQuery(world).forEach(eid => {
    const proxy = FooProxy.get(eid);
    const foo = proxy.foo;
    foo.close();
    proxy.free();
  });     
};

Consider the change of that resource can be shared. For example, foo.close() should be called only if it isn't referenced from somewhere else. We may need reference count?

takahirox commented 8 months ago

An idea

// utils/reference.ts
const referenceCounts: Map<Object, number> = new Map();

export const referenceCountUp = (obj: Object): number => {
  if (!referenceCounts.has(obj)) {
    referenceCounts.set(obj, 0);
  }
  const newCount = referenceCounts.get(obj)! + 1;
  referenceCounts.set(obj, newCount);
  return newCount;
};

export const referenceCountDown = (obj: Object): number => {
  const newCount = referenceCounts.get(obj)! - 1;
  if (newCount === 0) {
    referenceCounts.delete(obj);
  } else {
    referenceCounts.set(obj, newCount);
  }
  return newCount;
};

// Somewhere for creation
import { referenceCountUp } from "utils/reference";

const foo = new Foo();
addComponent(world, FooComponent, eid);
FooProxy.get(eid).allocate(foo);
referenceCountUp(foo);

// Somewhere for deletion
import { referenceCountDown } from "utils/reference";

const proxy = FooProxy.get(eid);
const foo = proxy.foo;
if (referenceCountDown(foo) === 0) {
  foo.close();
}
proxy.free();
removeComponent(world, Foo, eid);