/// <summary> /// Prepares for execution as a stolen chore. /// </summary> void _UnrealizedChore::_PrepareStealUnstructured(ContextBase *pBaseContext) { InternalContextBase *pContext = static_cast<InternalContextBase *> (pBaseContext); if (pContext->GetRootCollection() == NULL) { _TaskCollection* pTaskCollection = static_cast<_TaskCollection *> (_M_pTaskCollection); ContextBase *pOriginContext = reinterpret_cast <ContextBase *> (pTaskCollection->_M_pOwningContext); pContext->SetRootCollection(pTaskCollection); // // pOriginContext is only safe to touch if the act of stealing from a non-detached context put a hold on that context // to block deletion until we are chained for cancellation. // SafeRWList<ListEntry> *pList = reinterpret_cast<SafeRWList<ListEntry> *> (pTaskCollection->_M_stealTracker); ASSERT(sizeof(pTaskCollection->_M_stealTracker) >= sizeof(*pList)); if (_M_fDetached) { // // We cannot touch the owning context -- it was detached as of the steal. The chain goes onto the task collection. // pContext->NotifyTaskCollectionChainedStealer(); pList->AddTail(&(pContext->m_stealChain)); } else { pList->AcquireWrite(); pTaskCollection->_M_activeStealersForCancellation++; pList->ReleaseWrite(); pOriginContext->AddStealer(pContext, true); } } }
/// <summary> /// Prepares for execution as a stolen chore. /// </summary> void _UnrealizedChore::_PrepareStealStructured(ContextBase *pBaseContext) { InternalContextBase *pContext = static_cast<InternalContextBase *> (pBaseContext); if (pContext->GetRootCollection() == NULL) { _StructuredTaskCollection *pTaskCollection = static_cast<_StructuredTaskCollection *> (_M_pTaskCollection); ContextBase *pOriginContext = reinterpret_cast <ContextBase *> (pTaskCollection->_M_pOwningContext); pContext->SetRootCollection(pTaskCollection); pOriginContext->AddStealer(pContext, false); } }
bool BedtoolsDriver::subMain(int argc, char **argv) { _subCmd = argv[1]; ContextBase *context = getContext(); //process all command line arguments, check for valid usage, //show help and error messages if needed. if (!context->testCmdArgs(argc - 1, argv + 1)) { _hadError = context->errorEncountered(); delete context; return false; } //establish which tool we're using (intersect, map, closest, etc). //initialize it. ToolBase *tool = getTool(context); if (!tool->init()) { delete context; return false; } //set-up output manager. RecordOutputMgr *outputMgr = new RecordOutputMgr(); outputMgr->init(context); //process input RecordKeyVector hits; while (tool->findNext(hits)) { tool->processHits(outputMgr, hits); tool->cleanupHits(hits); } tool->finalizeCalculations(); tool->giveFinalReport(outputMgr); delete outputMgr; delete tool; delete context; return true; }
inline void proc() const { LBSApiBase* lbsApi = (LBSApiBase*)mContext->getLocApi()->getSibling(); lbsApi->shutdown(); }
inline ~LbsShutDownMsg() { delete mContext->getMsgTask(); delete mContext; }
virtual void ContextRunStarting(const ContextBase& context) { m_out << "\n# Describe " << context.Name() << std::endl; }
virtual void ContextRunStarting(const ContextBase& ctx) { std::cout << "\n<DESCRIBE::>" << ctx.Name() << std::endl; }
void __cdecl _UnrealizedChore::_UnstructuredChoreWrapper(_UnrealizedChore * pChore) { InternalContextBase *pContext = static_cast<InternalContextBase *> (SchedulerBase::FastCurrentContext()); // The context could be canceled if it was already prepared for steal (this happens during a block unblock race) ASSERT(pContext != NULL && (!pContext->HasInlineCancellation() || pContext->GetRootCollection() != NULL)); _TaskCollection* pTaskCollection = static_cast<_TaskCollection *> (pChore->_M_pTaskCollection); // // pOriginContext is only safe to touch if the act of stealing from a non-detached context put a hold on that context // to block deletion until we are chained for cancellation. // ContextBase *pOriginContext = reinterpret_cast <ContextBase *> (pTaskCollection->_M_pOwningContext); SafeRWList<ListEntry> *pList = reinterpret_cast<SafeRWList<ListEntry> *> (pTaskCollection->_M_stealTracker); pChore->_PrepareStealUnstructured(pContext); _CancellationTokenState *pTokenState = pTaskCollection->_GetTokenState(); _CancellationTokenRegistration *pRegistration = NULL; if (_CancellationTokenState::_IsValid(pTokenState)) { pRegistration = pTokenState->_RegisterCallback(reinterpret_cast<TaskProc>(&_UnrealizedChore::_CancelViaToken), (ContextBase *)pContext); } // // Waiting on the indirect alias may throw (e.g.: the entire context may have been canceled). If it // throws, we need to deal with appropriate marshaling. // try { // // Set up an indirect alias for this task collection. Any usage of the original task collection // within this stolen chore will automatically redirect through the indirect alias. This allows // preservation of single-threaded semantics within the task collection while allowing it to be "accessed" // from stolen chores (multiple threads). // // This stack based collection will wait on stolen chores at destruction time. In the event the collection is not // used during the steal, this doesn't do much. // _TaskCollection indirectAlias(pTaskCollection, false); pContext->SetIndirectAlias(&indirectAlias); try { // // We need to consider this a possible interruption point. It's entirely possible that we stole and raced with a // cancellation thread. The collection was canceled after we stole(e.g.: removed from the WSQ) but before we added ourselves // to the stealing chain list above. In this case, the entire context will wait until completion (bad). Immediately // after we go on the list (a memory barrier), we need to check the collection cancellation flag. If the collection is going away, // we need to get out *NOW* otherwise the entire subtree executes. // if (pTaskCollection->_M_pOriginalCollection->_M_exitCode != 0 || (_CancellationTokenState::_IsValid(pTokenState) && pTokenState->_IsCanceled()) || (pTaskCollection->_M_executionStatus != TASKCOLLECTION_EXECUTION_STATUS_CLEAR && pTaskCollection->_M_executionStatus != TASKCOLLECTION_EXECUTION_STATUS_INLINE && pTaskCollection->_M_executionStatus != TASKCOLLECTION_EXECUTION_STATUS_INLINE_WAIT_WITH_OVERFLOW_STACK)) throw _Interruption_exception(); pChore->m_pFunction(pChore); } catch(const _Interruption_exception &) { // // If someone manually threw _Interruption_exception, we will have a cancel count but not a canceled context. This // means we need to apply the cancel one level up. Normally, the act of throwing would do that via being caught in the // wait, but this is special "marshaling" for _Interruption_exception. // if (pContext->HasInlineCancellation() && !pContext->IsEntireContextCanceled()) pTaskCollection->_Cancel(); } catch(...) { // // Track the exception that was thrown here and subsequently cancel all work. _RaisedException makes the decision on what // exceptions to keep and what to discard. The flags it sets will indicate to the thread calling ::Wait that it must rethrow. // pTaskCollection->_RaisedException(); pTaskCollection->_Cancel(); } indirectAlias._Wait(); } catch(const _Interruption_exception &) { // // If someone manually threw _Interruption_exception out of a task on the indirect alias, the same thing applies as to // a directly stolen chore (above). // if (pContext->HasInlineCancellation() && !pContext->IsEntireContextCanceled()) pTaskCollection->_Cancel(); } catch(...) { // // Track the exception that was thrown here and subsequently cancel all work. _RaisedException makes the decision on what // exceptions to keep and what to discard. The flags it sets will indicate to the thread calling ::Wait that it must rethrow. // pTaskCollection->_RaisedException(); pTaskCollection->_Cancel(); } pContext->SetIndirectAlias(NULL); ASSERT(pContext->GetGoverningTokenState() == NULL); if ( !pChore->_M_fDetached) { // // pOriginContext may die at any point (detachment). When it does, it will transfer the stolen chore trace from the context to the // given task collection (us) under lock. We can, therefore, take this lock and check if we are still okay to check the context. // pList->AcquireWrite(); if (pContext->IsContextChainedStealer()) pOriginContext->RemoveStealer(pContext); else pList->UnlockedRemove(&(pContext->m_stealChain)); pTaskCollection->_M_activeStealersForCancellation--; pList->ReleaseWrite(); } else { pList->Remove(&(pContext->m_stealChain)); } if (pRegistration != NULL) { pTokenState->_DeregisterCallback(pRegistration); pRegistration->_Release(); } pContext->ClearCancel(); pContext->ClearAliasTable(); pContext->SetRootCollection(NULL); pChore->_M_pTaskCollection = NULL; pTaskCollection->_NotifyCompletedChoreAndFree(pChore); }
void __cdecl _UnrealizedChore::_StructuredChoreWrapper(_UnrealizedChore * pChore) { InternalContextBase *pContext = static_cast<InternalContextBase *> (SchedulerBase::FastCurrentContext()); // The context could be canceled if it was already prepared for steal (this happens during a block unblock race) ASSERT(pContext != NULL && (!pContext->HasInlineCancellation() || pContext->GetRootCollection() != NULL)); _StructuredTaskCollection *pTaskCollection = static_cast<_StructuredTaskCollection *> (pChore->_M_pTaskCollection); ContextBase *pOriginContext = reinterpret_cast <ContextBase *> (pTaskCollection->_M_pOwningContext); pChore->_PrepareStealStructured(pContext); // // This allows cancellation of stolen chores based on a cancellation token between the declaration of a stg and its inlining. // _CancellationTokenState *pTokenState = pTaskCollection->_GetTokenState(); _CancellationTokenRegistration *pRegistration = NULL; if (_CancellationTokenState::_IsValid(pTokenState)) { pRegistration = pTokenState->_RegisterCallback(reinterpret_cast<TaskProc>(&_UnrealizedChore::_CancelViaToken), (ContextBase *)pContext); } try { // // We need to consider this a possible interruption point. It's entirely possible that we stole and raced with a // cancellation thread. The collection was canceled after we stole(e.g.: removed from the WSQ) but before we added ourselves // to the stealing chain list above. In this case, the entire context will wait until completion (bad). Immediately // after we go on the list (a memory barrier) we need to check the collection cancelation flag. If the collection is going away, // we need to get out *NOW* otherwise the entire subtree executes. // if (pTaskCollection->_IsAbnormalExit()) throw _Interruption_exception(); pChore->m_pFunction(pChore); } catch(const _Interruption_exception &) { // // If someone manually threw the _Interruption_exception exception, we will have a cancel count but not a canceled context. This // means we need to apply the cancel one level up. Normally, the act of throwing would do that via being caught in the // wait, but this is special "marshaling" for _Interruption_exception. // if (pContext->HasInlineCancellation() && !pContext->IsEntireContextCanceled()) pTaskCollection->_Cancel(); } catch(...) { // // Track the exception that was thrown here. _RaisedException makes the decision on what // exceptions to keep and what to discard. The flags it sets will indicate to the thread calling ::Wait that it must rethrow. // pTaskCollection->_RaisedException(); pTaskCollection->_Cancel(); } pOriginContext->RemoveStealer(pContext); ASSERT(pContext->GetGoverningTokenState() == NULL); // // This allows cancellation of stolen chores based on a cancellation token between the declaration of a stg and its inlining. // if (pRegistration != NULL) { ASSERT(pTokenState != NULL); pTokenState->_DeregisterCallback(pRegistration); pRegistration->_Release(); } pContext->ClearCancel(); pContext->SetRootCollection(NULL); pChore->_M_pTaskCollection = NULL; pTaskCollection->_CountUp(); }