Ejemplo n.º 1
0
// 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;
}
Ejemplo n.º 2
0
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);
}