| 2629 | } |
| 2630 | |
| 2631 | bool FreeVars::FullyReleased(ULONG aRefPendingRelease) |
| 2632 | { |
| 2633 | // This function is part of a workaround for circular references that occur because all closures |
| 2634 | // have a reference to this FreeVars, while any closure referenced by itself or another closure |
| 2635 | // has a reference in mVar[]. |
| 2636 | if (mRefCount) |
| 2637 | return mRefCount < 0; |
| 2638 | int circular_closures = 0; |
| 2639 | for (int i = 0; i < mVarCount; ++i) |
| 2640 | if (mVar[i].Type() == VAR_CONSTANT) |
| 2641 | { |
| 2642 | ASSERT(mVar[i].HasObject() && dynamic_cast<ObjectBase*>(mVar[i].Object())); // Any object in VAR_CONSTANT must derive from ObjectBase. |
| 2643 | auto obj = (ObjectBase *)mVar[i].Object(); |
| 2644 | if (obj->RefCount() && aRefPendingRelease == 0) |
| 2645 | return false; |
| 2646 | --aRefPendingRelease; |
| 2647 | ++circular_closures; |
| 2648 | } |
| 2649 | --mRefCount; // Now that delete is certain, make this non-zero to prevent reentry. |
| 2650 | if (circular_closures) |
| 2651 | { |
| 2652 | // All closures in downvars have mRefCount == 0, meaning their only reference is the |
| 2653 | // uncounted one in mVar[]. In order to free the object properly, mRefCount needs to |
| 2654 | // be restored to 1 prior to Release(), which will be called by Var::Free(). |
| 2655 | for (int i = 0; i < mVarCount; ++i) |
| 2656 | if (mVar[i].Type() == VAR_CONSTANT) |
| 2657 | { |
| 2658 | auto obj = (ObjectBase *)mVar[i].Object(); |
| 2659 | obj->AddRef(); |
| 2660 | } |
| 2661 | } |
| 2662 | delete this; |
| 2663 | return true; |
| 2664 | } |
| 2665 | |
| 2666 | |
| 2667 | ResultType IObjectPtr::ExecuteInNewThread(TCHAR *aNewThreadDesc, ExprTokenType *aParamValue, int aParamCount, __int64 *aRetVal) const |