// 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(); }
void Globals::initialize() { StaticInits *s = s_next_inits; while (s) { const ClassPropTable *cpt = s->table; const int *e = s->entries; int n = *e++; while (n--) { const ClassPropTableEntry *p = cpt->m_entries + *e++; char *addr = (char*)this + p->offset; if (LIKELY(p->isFastInit())) { CVarRef v = cpt->getInitV(p->init_offset); switch (p->type) { case KindOfBoolean: *(bool*)addr = v.asBooleanVal(); break; case KindOfInt64: *(int64*)addr = v.asInt64Val(); break; case KindOfDouble: *(double*)addr = v.asDoubleVal(); break; case KindOfString: *(String*)addr = v.asCStrRef(); break; case KindOfArray: *(Array*)addr = v.asCArrRef(); break; case KindOfVariant: *(Variant*)addr = v; break; default: ASSERT(false); } continue; } CVarRef v = cpt->getInitVal(p); if (LIKELY(p->type == KindOfVariant)) { *(Variant*)addr = v; } else { switch (p->type) { case KindOfBoolean: *(bool*)addr = v; break; case KindOfInt64: *(int64*)addr = v; break; case KindOfDouble: *(double*)addr = v; break; case KindOfString: *(String*)addr = v; break; case KindOfArray: *(Array*)addr = v; break; default: ASSERT(false); } } } s = s->next; } }