void CLR_RT_HeapBlock_Timer::SpawnTimer( CLR_RT_Thread* th ) { NATIVE_PROFILE_CLR_CORE(); //Only one managed timer max _ASSERTE(m_references.NumOfNodes() == 1); CLR_RT_ObjectToEvent_Source* ref = (CLR_RT_ObjectToEvent_Source*)m_references.FirstValidNode(); CLR_RT_HeapBlock* managedTimer = ref->m_objectPtr; CLR_RT_HeapBlock* callback = &managedTimer[ Library_corlib_native_System_Threading_Timer::FIELD__m_callback ]; CLR_RT_HeapBlock* state = &managedTimer[ Library_corlib_native_System_Threading_Timer::FIELD__m_state ]; CLR_RT_HeapBlock_Delegate* delegate = callback->DereferenceDelegate(); CLR_RT_ProtectFromGC gc( *managedTimer ); _ASSERTE(delegate != NULL); if(delegate == NULL) return; _ASSERTE(delegate->DataType() == DATATYPE_DELEGATE_HEAD); m_ticksLastExpiration = g_CLR_RT_ExecutionEngine.m_currentMachineTime; m_timeLastExpiration = m_timeExpire; m_timeExpire = TIMEOUT_INFINITE; if(SUCCEEDED(th->PushThreadProcDelegate( delegate ))) { CLR_RT_StackFrame* stack = th->FirstFrame(); if(stack->Next() != NULL) { int numArgs = stack->m_call.m_target->numArgs; if(numArgs > 0) { stack->m_arguments[ numArgs-1 ].Assign( *state ); } } // // Associate the timer with the thread. // m_flags |= CLR_RT_HeapBlock_Timer::c_Executing; m_flags &= ~CLR_RT_HeapBlock_Timer::c_Triggered; th->m_terminationCallback = CLR_RT_HeapBlock_Timer::ThreadTerminationCallback; th->m_terminationParameter = this; } }
HRESULT CLR_RT_HeapBlock_Delegate_List::Change( CLR_RT_HeapBlock& reference, CLR_RT_HeapBlock& delegateSrc, CLR_RT_HeapBlock& delegateTarget, bool fCombine, bool fWeak ) { NATIVE_PROFILE_CLR_CORE(); TINYCLR_HEADER(); CLR_RT_HeapBlock_Delegate_List* dlgListSrc; CLR_RT_HeapBlock_Delegate_List* dlgListDst; CLR_RT_HeapBlock_Delegate* dlg; CLR_RT_HeapBlock* newDlgs; CLR_RT_HeapBlock* oldDlgs; CLR_UINT32 oldNum; CLR_UINT32 newNum; CLR_UINT32 num = 0; reference.SetObjectReference( NULL ); if(delegateSrc .DataType() != DATATYPE_OBJECT || delegateTarget.DataType() != DATATYPE_OBJECT ) { TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); } dlg = delegateTarget.DereferenceDelegate(); if(dlg == NULL) { reference.SetObjectReference( delegateSrc.DereferenceDelegate() ); TINYCLR_SET_AND_LEAVE(S_OK); } if(dlg->DataType() == DATATYPE_DELEGATELIST_HEAD) { CLR_RT_HeapBlock intermediate; intermediate.Assign( delegateSrc ); CLR_RT_ProtectFromGC gc( intermediate ); dlgListDst = (CLR_RT_HeapBlock_Delegate_List*)dlg; newDlgs = dlgListDst->GetDelegates(); for(num=0; num<dlgListDst->m_length; num++, newDlgs++) { if(newDlgs->DataType() == DATATYPE_OBJECT && newDlgs->DereferenceDelegate() != NULL) // The delegate could have been GC'ed. { TINYCLR_CHECK_HRESULT(Change( reference, intermediate, *newDlgs, fCombine, fWeak )); intermediate.Assign( reference ); } } } else { dlgListSrc = delegateSrc.DereferenceDelegateList(); if(dlgListSrc == NULL) { oldDlgs = NULL; oldNum = 0; } else { switch(dlgListSrc->DataType()) { case DATATYPE_DELEGATE_HEAD: oldDlgs = &delegateSrc; oldNum = 1; break; case DATATYPE_DELEGATELIST_HEAD: oldDlgs = dlgListSrc->GetDelegates(); oldNum = dlgListSrc->m_length; break; default: TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); } } if(fCombine) { if(oldNum == 0 && fWeak == false) { // // Empty input list, copy the delegate. // reference.Assign( delegateTarget ); TINYCLR_SET_AND_LEAVE(S_OK); } //--// newNum = oldNum + 1; } else { for(num=0, newDlgs=oldDlgs; num<oldNum; num++, newDlgs++) { CLR_RT_HeapBlock_Delegate* ptr = newDlgs->DereferenceDelegate(); if(ptr) { if( ptr->DelegateFtn().m_data == dlg->DelegateFtn().m_data && ptr->m_object.Dereference() == dlg->m_object.Dereference() ) { break; } } } if(num == oldNum) { reference.Assign( delegateSrc ); // Nothing to remove. TINYCLR_SET_AND_LEAVE(S_OK); } if(oldNum == 2 && (dlgListSrc->m_flags & CLR_RT_HeapBlock_Delegate_List::c_Weak) == 0) { reference.Assign( oldDlgs[ 1-num ] ); // Convert from a list to delegate. TINYCLR_SET_AND_LEAVE(S_OK); } if(oldNum == 1) { reference.SetObjectReference( NULL ); // Oops, empty delegate... TINYCLR_SET_AND_LEAVE(S_OK); } //--// newNum = oldNum - 1; } TINYCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Delegate_List::CreateInstance( dlgListDst, newNum )); dlgListDst->m_cls = dlg->m_cls; newDlgs = dlgListDst->GetDelegates(); if(fCombine) { newDlgs = dlgListDst->CopyAndCompress( oldDlgs, newDlgs, oldNum ); newDlgs->Assign( delegateTarget ); } else { newDlgs = dlgListDst->CopyAndCompress( oldDlgs , newDlgs, num++ ); newDlgs = dlgListDst->CopyAndCompress( oldDlgs + num, newDlgs, oldNum - num ); } dlgListDst->m_flags = (dlgListSrc && oldNum > 1) ? dlgListSrc->m_flags : 0; if(fWeak) dlgListDst->m_flags |= CLR_RT_HeapBlock_Delegate_List::c_Weak; reference.SetObjectReference( dlgListDst ); } TINYCLR_NOCLEANUP(); }