bool MutableArrayIter::advance() { ArrayData *data = m_var ? getData() : m_data; if (!data) return false; // If the foreach loop's array changed since the previous iteration, // we recover by creating a new strong iterator for the new array, // starting with at the position indicated by the new array's internal // pointer. if (m_fp.container != data) { // Free the current strong iterator if its valid if (m_fp.container != NULL) { m_fp.container->freeFullPos(m_fp); } assert(m_fp.container == NULL); // If needed, escalate the array to an array type that can support // foreach by reference escalateCheck(); // Trigger COW if needed, copying over strong iterators data = cowCheck(); // Create a new strong iterator for the new array data->newFullPos(m_fp); } else { // Trigger COW if needed, copying over strong iterators data = cowCheck(); } assert(m_fp.container == data); if (!data->setFullPos(m_fp)) return false; CVarRef curr = data->currentRef(); m_valp->assignRef(curr); if (m_key) m_key->assignVal(data->key()); data->next(); data->getFullPos(m_fp); return true; }
bool MutableArrayIter::advance() { ArrayData *data = m_var ? getData() : m_data; if (!data) return false; // If the foreach loop's array changed since the previous iteration, // we recover by creating a new strong iterator for the new array, // starting with at the position indicated by the new array's internal // pointer. if (m_fp.container != data) { // Free the current strong iterator if its valid if (m_fp.container != NULL) { m_fp.container->freeFullPos(m_fp); } // Create a new strong iterator for the new array ASSERT(m_fp.container == NULL); data->newFullPos(m_fp); } ASSERT(m_fp.container == data); if (!data->setFullPos(m_fp)) return false; CVarRef curr = data->currentRef(); curr.setContagious(); m_val = curr; if (m_key) *m_key = data->key(); data->next(); data->getFullPos(m_fp); return true; }
// The default operator called from parallel_for void operator() (const tbb::blocked_range<int64> &range) const { callerContext.EnteringOperator(); // Build arguments array Array args = Array::Create(); // Pass the range start and end as parameters args.append(range.begin()); args.append(range.end()); // If an input array is defined, copy it and pass as a parameter if(inputArrayOfVariant.size() > 0) { Array inputPHPArray = Array::Create(); for(size_t ai=0; ai<inputArrayOfVariant.size(); ai++) inputPHPArray.append(inputArrayOfVariant[ai]); Variant inputArrayArg(inputPHPArray.getArrayData()); args.append(inputArrayArg); } // Call user supplied callback with arguments // This is a PHP function of the form worker($begin, $end, $array), returning an array or nothing // If an array is returned, it is expected to have elements which will be comingled into the output // array in the elements defined by the input range. Variant vres = f_call_user_func_array(this->callback, args); callerContext.ExitingOperator(); // Call this straight after the callback completes // Return if no result to pass back if(vres.isNull() || !vres.isArray()) return; // Now we take the output array [0..N) and assign it into the overall output array at [begin..begin+N) // Extract output array from result variant const Array aOutputArray = vres.asCArrRef(); ArrayData *pdOutputArray = aOutputArray.getArrayData(); Variant v = pdOutputArray->reset(); // Check the output array is the same size or smaller than the range passed size_t outIdx = range.begin(); if(pdOutputArray->size() > (range.end()-range.begin())) { raise_warning("Callback function returned array larger than passed range size"); return; } // Copy each row while(!v.isBoolean() || v.toBoolean()) { // printf(" outIdx=%d, v=%s\n", (int)outIdx, v.toString().c_str()); ( *pOutputArrayOfVariant ) [outIdx++] = v; v = pdOutputArray->next(); } }
bool MutableArrayIter::advance() { ArrayData *data = getData(); if (!data) return false; if (!data->setFullPos(m_pos)) return false; CVarRef curr = data->currentRef(); curr.setContagious(); m_val = curr; if (m_key) *m_key = data->key(); data->next(); data->getFullPos(m_pos); return true; }