MakeWeakHandle() private method

private MakeWeakHandle ( HandleProxy handleProxy ) : void
handleProxy HandleProxy
return void
        /// <summary>
        /// Does one step in the work process (mostly garbage collection for freeing up unused handles).
        /// True is returned if more work is pending, and false otherwise.
        /// </summary>
        bool _DoWorkStep()
        {
            // ... check one abandoned object ...

            LinkedListNode <IV8Disposable> abandoned = null;

            lock (_AbandondObjects)
            {
                if (_AbandondObjects.Count > 0)
                {
                    abandoned = _AbandondObjects.First; // (take the first abandoned object and try to dispose of it)
                    _AbandondObjects.RemoveFirst();
                    // WARNING: Until '_AbandondObjectsIndex' is also updated, DO NOT release lock until the node is put back, or removed from the index!
                }

                if (abandoned != null)
                {
                    if (abandoned.Value.CanDispose)
                    {
                        abandoned.Value.Dispose();
                        GC.SuppressFinalize(abandoned); // (required otherwise the object's finalizer will be triggered again)
                        _AbandondObjectsIndex.Remove(abandoned.Value);
                    }
                    else
                    {
                        _AbandondObjects.AddLast(abandoned); // (still can't dispose this yet)
                    }
                }
            }

            // ... and do one handle ready to be disposed ...

            IV8Disposable disposable = null;

            lock (_DisposalQueue) // TODO: consider using read/write locks in more places
            {
                if (_DisposalQueue.Count > 0)
                {
                    disposable = _DisposalQueue.Dequeue();
                }
            }

            if (disposable != null)
            {
                if (disposable.CanDispose)
                {
                    disposable.Dispose();
                }
                else
                {
                    // ... cannot dispose this yet; place it in the "abandoned" queue for later (next generation disposal) ...

                    lock (_AbandondObjects)
                    {
                        _AbandondObjectsIndex[disposable] = _AbandondObjects.AddLast(disposable);
                    }

                    // ... if this is a manage object, it is now abandoned, so make the native handle weak ...

                    if (disposable is V8NativeObject)
                    {
                        var v8Obj = (V8NativeObject)disposable;
                        if (!v8Obj.InternalHandle.IsEmpty && v8Obj.InternalHandle._HandleProxy->IsPendingDisposal)
                        {
                            V8NetProxy.MakeWeakHandle(v8Obj.InternalHandle); // ('Disposed' will be 2 after this, so no worries about doing this more than once)

                            /* Once the native GC attempts to collect the underlying native object, then '_OnNativeGCRequested()' will get
                             * called to finalize the disposal of the managed object.
                             * Note 1: Once the native V8 engine agrees, this object will be removed due to a global V8 GC callback
                             *         registered when the V8.Net wrapper engine was created.
                             * Note 2: Don't call this while '_Objects' is locked, because the main thread may be executing script that may
                             *         also need a lock, and this call may become blocked by a native side mutex.
                             */
                        }
                    }
                }
            }

            return(_WeakObjects.Count + _DisposalQueue.Count > 0);
        }
Ejemplo n.º 2
0
 /// <summary>
 /// Called by the worker thread to make the native handle weak.  Once the native GC attempts to collect the underlying native object, then
 /// '_OnNativeGCRequested()' will get called to finalize the disposal of the managed object.
 /// </summary>
 internal void _MakeWeak()
 {
     V8NetProxy.MakeWeakHandle(_Handle);
     // (once the native V8 engine agrees, this instance will be removed due to a global GC callback registered when the engine was created)
 }