// f_parallel_for
//  begin - start of range to process
//	end - 1 after end of range to process
//  func - worker function of the form worker($begin, $end, $inputdata) - returns an array of max length ($end-$begin)
//  blocksize - optional blocksize, refer to TBB documentation
// Returns: array of maximum length ($end-$begin)
//
// Call 'func' for non-overlapping array segments to cover all of arraydata
// This will use threads as appropriate for the machine.
// If a result is returned by 'func' it will be placed into the result array elements corresponding to the input elements
Variant f_parallel_for_array(CVarRef arraydata, CVarRef func, int64 blocksize /* = -1 */) {
	if(!arraydata.isArray())
	{
		raise_error("parallel_for_array expected an array in first argument");
		return Variant();
	}

	// Get the input array
	const Array aArray = arraydata.asCArrRef();
	ArrayData *pdArray = aArray.getArrayData();

	size_t asize = pdArray->size();
	if(asize==0)
		return Variant();

	MemoryManager *mm = MemoryManager::TheMemoryManager().get();
	if (RuntimeOption::CheckMemory) {
	    mm->checkMemory(false);
	  }

    TbbContext myContext  = TbbContext::Entry("parallel_for_array");

    std::vector<Variant> outArray;
    outArray.resize(asize);

    // Construct task parameters
	PforTaskParameters tclass = PforTaskParameters(myContext, pdArray, func, &outArray);

    TbbInitializeIfNeeded();

    if (blocksize == -1) {
            // Use auto_partitioner for block size
            tbb::parallel_for(tbb::blocked_range<int64>(0, asize), tclass, tbb::auto_partitioner());
    } else {
            // Use manually set block size
            tbb::parallel_for(tbb::blocked_range<int64>(0, asize, blocksize), tclass);
    }

    myContext.Exit();


    // Create the result array
	Array resPHPArray = Array::Create();
	for(size_t ai=0; ai<outArray.size(); ai++) {
		Variant amem = outArray[ai];
		// printf(" ai=%d, append %s\n", (int)ai, amem.toString().c_str());
		if(!amem.isNull())
			resPHPArray.append(amem);
	}

	if(resPHPArray.size()==0)
		return Variant();		// i.e null

	return resPHPArray.getArrayData();
}