Skip to content

Commit

Permalink
Implement tests for deletion, correctly implementation delay of deletion
Browse files Browse the repository at this point in the history
  • Loading branch information
jerbob92 committed Sep 22, 2023
1 parent ee8c165 commit 1332047
Show file tree
Hide file tree
Showing 9 changed files with 993 additions and 108 deletions.
2 changes: 2 additions & 0 deletions engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ type Engine interface {
NewFunctionExporterForModule(guest wazero.CompiledModule) FunctionExporter
}

type DelayFunction internal.DelayFunction

type EngineKey = internal.EngineKey

func CreateEngine(config internal.IEngineConfig) Engine {
Expand Down
8 changes: 8 additions & 0 deletions examples/classes/generated/classes.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions generator/generator/templates/classes.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,14 @@ func (class *{{ $class.GoName }}) Delete(ctx context.Context) error {
return class.DeleteInstance(ctx, class)
}

func (class *{{ $class.GoName }}) DeleteLater(ctx context.Context) (embind.ClassBase, error) {
return class.DeleteInstanceLater(ctx, class)
}

func (class *{{ $class.GoName }}) IsDeleted(ctx context.Context) bool {
return class.IsInstanceDeleted(ctx, class)
}

func (class *{{ $class.GoName }}) IsAliasOf(ctx context.Context, second embind.ClassBase) (bool, error) {
return class.IsAliasOfInstance(ctx, class, second)
}
Expand Down
34 changes: 24 additions & 10 deletions internal/class.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,11 +115,11 @@ func (erc *classType) validate() error {
return nil
}

func (erc *classType) isDeleted(handle IClassBase) bool {
func (erc *classType) isDeleted(ctx context.Context, handle IClassBase) bool {
return handle.getRegisteredPtrTypeRecord().ptr == 0
}

func (erc *classType) deleteLater(handle IClassBase) (any, error) {
func (erc *classType) deleteLater(ctx context.Context, handle IClassBase) (IClassBase, error) {
registeredPtrTypeRecord := handle.getRegisteredPtrTypeRecord()
if registeredPtrTypeRecord.ptr == 0 {
return nil, fmt.Errorf("class handle already deleted")
Expand All @@ -129,13 +129,17 @@ func (erc *classType) deleteLater(handle IClassBase) (any, error) {
return nil, fmt.Errorf("object already scheduled for deletion")
}

// @todo: implement me.
/*
deletionQueue.push(this);
if (deletionQueue.length === 1 && delayFunction) {
delayFunction(flushPendingDeletes);
}
*/
e := MustGetEngineFromContext(ctx, nil).(*engine)
e.deletionQueue = append(e.deletionQueue, handle)

if len(e.deletionQueue) == 1 && e.delayFunction != nil {
err := e.delayFunction(func(ctx context.Context) error {
return e.FlushPendingDeletes(ctx)
})
if err != nil {
return nil, err
}
}

registeredPtrTypeRecord.deleteScheduled = true

Expand Down Expand Up @@ -214,7 +218,7 @@ func (erc *classType) delete(ctx context.Context, handle IClassBase) error {
return err
}

if registeredPtrTypeRecord.preservePointerOnDelete {
if !registeredPtrTypeRecord.preservePointerOnDelete {
registeredPtrTypeRecord.smartPtr = 0
registeredPtrTypeRecord.ptr = 0
}
Expand Down Expand Up @@ -453,6 +457,14 @@ func (ecb *ClassBase) DeleteInstance(ctx context.Context, this IClassBase) error
return ecb.classType.delete(ctx, this)
}

func (ecb *ClassBase) DeleteInstanceLater(ctx context.Context, this IClassBase) (IClassBase, error) {
return ecb.classType.deleteLater(ctx, this)
}

func (ecb *ClassBase) IsInstanceDeleted(ctx context.Context, this IClassBase) bool {
return ecb.classType.isDeleted(ctx, this)
}

func (ecb *ClassBase) IsAliasOfInstance(ctx context.Context, this IClassBase, second IClassBase) (bool, error) {
return ecb.classType.isAliasOf(ctx, this, second)
}
Expand Down Expand Up @@ -520,6 +532,8 @@ type IClassBase interface {
isValid() bool
CloneInstance(ctx context.Context, this IClassBase) (IClassBase, error)
DeleteInstance(ctx context.Context, this IClassBase) error
DeleteInstanceLater(ctx context.Context, this IClassBase) (IClassBase, error)
IsInstanceDeleted(ctx context.Context, this IClassBase) bool
IsAliasOfInstance(ctx context.Context, this IClassBase, second IClassBase) (bool, error)
CallInstanceMethod(ctx context.Context, this any, name string, arguments ...any) (any, error)
SetInstanceProperty(ctx context.Context, this any, name string, value any) error
Expand Down
10 changes: 10 additions & 0 deletions internal/embind.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,15 @@ type IEngine interface {
RegisterEmvalSymbol(name string, symbol any) error
EmvalToHandle(value any) int32
EmvalToValue(handle int32) (any, error)
CountEmvalHandles() int
GetInheritedInstanceCount() int
GetLiveInheritedInstances() []IClassBase
FlushPendingDeletes(ctx context.Context) error
SetDelayFunction(fn DelayFunction) error
}

type DelayFunction func(func(ctx context.Context) error) error

type IEngineConfig interface {
}

Expand Down Expand Up @@ -92,6 +99,9 @@ func CreateEngine(config IEngineConfig) IEngine {
registeredPointers: map[int32]*registeredPointer{},
registeredTuples: map[int32]*registeredTuple{},
registeredObjects: map[int32]*registeredObject{},
registeredInstances: map[uint32]IClassBase{},
deletionQueue: []IClassBase{},
delayFunction: nil,
emvalEngine: createEmvalEngine(),
}
}
4 changes: 4 additions & 0 deletions internal/emval.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@ func (ea *emvalAllocator) get(id int32) (*emvalHandle, error) {
return nil, fmt.Errorf("invalid id: %d", id)
}

if ea.allocated[int(id)] == nil {
return nil, fmt.Errorf("invalid id: %d", id)
}

return ea.allocated[int(id)], nil
}

Expand Down
51 changes: 50 additions & 1 deletion internal/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ type engine struct {
registeredTuples map[int32]*registeredTuple
registeredObjects map[int32]*registeredObject
registeredInstances map[uint32]IClassBase
deletionQueue []IClassBase
delayFunction DelayFunction
emvalEngine *emvalEngine
}

Expand Down Expand Up @@ -761,6 +763,53 @@ func (e *engine) validateThis(ctx context.Context, this any, classType *register

// @todo: check if based.ptrType.registeredClass is or extends classType.registeredClass

// todo: kill this
// todo: kill this (comment from Emscripten)
return e.upcastPointer(ctx, based.getPtr(), based.getPtrType().registeredClass, classType.registeredClass)
}

func (e *engine) CountEmvalHandles() int {
return len(e.emvalEngine.allocator.allocated) - len(e.emvalEngine.allocator.freelist)
}

func (e *engine) GetInheritedInstanceCount() int {
return len(e.registeredInstances)
}

func (e *engine) GetLiveInheritedInstances() []IClassBase {
instances := make([]IClassBase, len(e.registeredInstances))
i := 0
for id := range e.registeredInstances {
instances[i] = e.registeredInstances[id]
i++
}
return instances
}

func (e *engine) FlushPendingDeletes(ctx context.Context) error {
for len(e.deletionQueue) > 0 {
obj := e.deletionQueue[len(e.deletionQueue)-1]
e.deletionQueue = e.deletionQueue[:len(e.deletionQueue)-1]

obj.getRegisteredPtrTypeRecord().deleteScheduled = false
err := obj.DeleteInstance(ctx, obj)
if err != nil {
return err
}
}
return nil
}

func (e *engine) SetDelayFunction(fn DelayFunction) error {
e.delayFunction = fn

if len(e.deletionQueue) > 0 && fn != nil {
err := fn(func(ctx context.Context) error {
return e.FlushPendingDeletes(ctx)
})
if err != nil {
return err
}
}

return nil
}
Loading

0 comments on commit 1332047

Please sign in to comment.