// nthread(iNumThreads, strFunc, vecArgs, ...) static Symbol* fkt_nthread(const std::vector<Symbol*>& vecSyms, ParseInfo& info, RuntimeInfo &runinfo, SymbolTable* pSymTab) { if(vecSyms.size()<3) { std::ostringstream ostrErr; ostrErr << linenr(runinfo) << "nthread needs at least 3 arguments: N, func, arg." << std::endl; throw tl::Err(ostrErr.str(),0); } Symbol* _pSymN = vecSyms[0]; if(_pSymN->GetType() != SYMBOL_INT) { std::ostringstream ostrErr; ostrErr << linenr(runinfo) << "Number of threads has to be integer." << std::endl; throw tl::Err(ostrErr.str(),0); } SymbolInt *pSymN = (SymbolInt*)_pSymN; t_int iNumThreads = pSymN->GetVal(); Symbol* _pSymIdent = vecSyms[1]; if(_pSymIdent->GetType() != SYMBOL_STRING) { std::ostringstream ostrErr; ostrErr << linenr(runinfo) << "Thread proc identifier needs to be a string." << std::endl; throw tl::Err(ostrErr.str(), 0); } SymbolString *pSymIdent = (SymbolString*)_pSymIdent; const t_string& strIdent = pSymIdent->GetVal(); Symbol* _pSymArr = vecSyms[2]; if(_pSymArr->GetType() != SYMBOL_ARRAY) { std::ostringstream ostrErr; ostrErr << linenr(runinfo) << "Thread arg has to be an array." << std::endl; throw tl::Err(ostrErr.str(), 0); } SymbolArray *pSymArr = (SymbolArray*)_pSymArr; const std::vector<Symbol*>& vecArr = pSymArr->GetArr(); NodeFunction* pFunc = info.GetFunction(strIdent); if(pFunc == 0) { std::ostringstream ostrErr; ostrErr << linenr(runinfo) << "Thread proc \"" << strIdent << "\" not defined." << std::endl; throw tl::Err(ostrErr.str(), 0); } if(iNumThreads > int(vecArr.size())) { iNumThreads = vecArr.size(); tl::log_warn(linenr(runinfo), "More threads requested in nthread than necessary, ", "reducing to array size (", iNumThreads, ")."); } std::vector<SymbolArray*> vecSymArrays; vecSymArrays.resize(iNumThreads); t_int iCurTh = 0; for(Symbol* pThisSym : vecArr) { if(!vecSymArrays[iCurTh]) vecSymArrays[iCurTh] = new SymbolArray(); vecSymArrays[iCurTh]->GetArr().push_back(pThisSym->clone()); vecSymArrays[iCurTh]->UpdateLastNIndices(1); ++iCurTh; if(iCurTh == iNumThreads) iCurTh = 0; } std::vector<std::thread*> vecThreads; vecThreads.reserve(iNumThreads); for(iCurTh=0; iCurTh<iNumThreads; ++iCurTh) { std::vector<Symbol*>* vecThreadSyms = new std::vector<Symbol*>; vecThreadSyms->reserve(vecSyms.size()-3+1); vecThreadSyms->push_back(vecSymArrays[iCurTh]); for(unsigned int iSym=3; iSym<vecSyms.size(); ++iSym) vecThreadSyms->push_back(vecSyms[iSym]->clone()); std::thread *pth = new std::thread(::thread_proc, pFunc, &info, vecThreadSyms); vecThreads.push_back(pth); } /* // automatically join for(iCurTh=0; iCurTh<iNumThreads; ++iCurTh) { vecThreads[iCurTh]->join(); delete vecThreads[iCurTh]; vecThreads[iCurTh] = 0; }*/ SymbolArray* pArrThreads = new SymbolArray(); for(iCurTh=0; iCurTh<iNumThreads; ++iCurTh) { std::thread* pCurThread = vecThreads[iCurTh]; t_int iHandle = info.phandles->AddHandle(new HandleThread(pCurThread)); SymbolInt *pSymThreadHandle = new SymbolInt(iHandle); pArrThreads->GetArr().push_back(pSymThreadHandle); } pArrThreads->UpdateIndices(); return pArrThreads; }
static Symbol* fkt_thread_task(const std::vector<Symbol*>& vecSyms, ParseInfo& info, RuntimeInfo &runinfo, SymbolTable* pSymTab, bool bTask=0) { if(vecSyms.size()<1) { std::ostringstream ostrErr; ostrErr << linenr(runinfo) << "Need thread proc identifier." << std::endl; throw tl::Err(ostrErr.str(), 0); } Symbol* _pSymIdent = vecSyms[0]; if(_pSymIdent->GetType() != SYMBOL_STRING) { std::ostringstream ostrErr; ostrErr << linenr(runinfo) << "Thread proc identifier needs to be a string." << std::endl; throw tl::Err(ostrErr.str(), 0); } SymbolString *pSymIdent = (SymbolString*)_pSymIdent; const t_string& strIdent = pSymIdent->GetVal(); NodeFunction* pFunc = info.GetFunction(strIdent); if(pFunc == 0) { std::ostringstream ostrErr; ostrErr << linenr(runinfo) << "Thread proc \"" << strIdent << "\" not defined." << std::endl; throw tl::Err(ostrErr.str(), 0); } std::vector<Symbol*>* vecThreadSymsClone = clone_symbols(&vecSyms, 1); t_int iHandle = -1; if(bTask) { bool bIsThread = 1; std::launch policy = std::launch::async /*| std::launch::deferred*/; unsigned int iNumThreads = info.phandles->CountAllThreads(); //log_debug("Number of threads running: ", iNumThreads); // start deferred if(iNumThreads >= std::thread::hardware_concurrency()) { bIsThread = 0; // let system decide policy |= std::launch::deferred; //log_debug("starting (probably) deferred"); } //else log_debug("starting as thread"); std::future<Symbol*> *pFuture = new std::future<Symbol*>( std::async(policy, ::task_proc, pFunc, &info, vecThreadSymsClone)); iHandle = info.phandles->AddHandle(new HandleTask(pFuture, bIsThread)); } else { std::thread* pThread = new std::thread(::thread_proc, pFunc, &info, vecThreadSymsClone); iHandle = info.phandles->AddHandle(new HandleThread(pThread)); } return new SymbolInt(iHandle); }