コード例 #1
0
                // 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();
                    	}

                }
コード例 #2
0
// 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();
}
コード例 #3
0
ファイル: ext_collections.cpp プロジェクト: facebook/hhvm
ArrayIter getArrayIterHelper(const Variant& v, size_t& sz) {
  if (v.isArray()) {
    ArrayData* ad = v.getArrayData();
    sz = ad->size();
    return ArrayIter(ad);
  }
  if (v.isObject()) {
    ObjectData* obj = v.getObjectData();
    if (obj->isCollection()) {
      sz = collections::getSize(obj);
      return ArrayIter(obj);
    }
    bool isIterable;
    Object iterable = obj->iterableObject(isIterable);
    if (isIterable) {
      sz = 0;
      return ArrayIter(iterable.detach(), ArrayIter::noInc);
    }
  }
  SystemLib::throwInvalidArgumentExceptionObject(
    "Parameter must be an array or an instance of Traversable");
}
コード例 #4
0
ALWAYS_INLINE
typename std::enable_if<
  std::is_base_of<BaseMap, TMap>::value, Object>::type
BaseMap::FromArray(const Class*, const Variant& arr) {
  if (!arr.isArray()) {
    SystemLib::throwInvalidArgumentExceptionObject(
      "Parameter arr must be an array");
  }
  auto map = req::make<TMap>();
  ArrayData* ad = arr.getArrayData();
  map->reserve(ad->size());
  for (ssize_t pos = ad->iter_begin(), limit = ad->iter_end(); pos != limit;
       pos = ad->iter_advance(pos)) {
    Variant k = ad->getKey(pos);
    auto* tv = ad->getValueRef(pos).asCell();
    if (k.isInteger()) {
      map->setRaw(k.toInt64(), tv);
    } else {
      assert(k.isString());
      map->setRaw(k.getStringData(), tv);
    }
  }
  return Object(std::move(map));
}
コード例 #5
0
SharedVariant::SharedVariant(CVarRef source, bool serialized,
                             bool inner /* = false */,
                             bool unserializeObj /* = false */)
  : m_count (1), m_shouldCache(false), m_flags(0){
  ASSERT(!serialized || source.isString());

  m_type = source.getType();

  switch (m_type) {
  case KindOfBoolean:
    {
      m_data.num = source.toBoolean();
      break;
    }
  case KindOfByte:
  case KindOfInt16:
  case KindOfInt32:
  case KindOfInt64:
    {
      m_type = KindOfInt64;
      m_data.num = source.toInt64();
      break;
    }
  case KindOfDouble:
    {
      m_data.dbl = source.toDouble();
      break;
    }
  case KindOfStaticString:
  case KindOfString:
    {
      String s = source.toString();
      if (serialized) {
        m_type = KindOfObject;
        // It is priming, and there might not be the right class definitions
        // for unserialization.
        s = apc_reserialize(s);
      }
      m_data.str = s->copy(true);
      break;
    }
  case KindOfArray:
    {
      ArrayData *arr = source.getArrayData();

      if (!inner) {
        // only need to call hasInternalReference() on the toplevel array
        PointerSet seen;
        if (arr->hasInternalReference(seen)) {
          setSerializedArray();
          m_shouldCache = true;
          String s = apc_serialize(source);
          m_data.str = new StringData(s.data(), s.size(), CopyString);
          break;
        }
      }

      size_t size = arr->size();
      if (arr->isVectorData()) {
        setIsVector();
        m_data.vec = new VectorData(size);
        uint i = 0;
        for (ArrayIter it(arr); !it.end(); it.next(), i++) {
          SharedVariant* val = Create(it.secondRef(), false, true,
                                      unserializeObj);
          if (val->m_shouldCache) m_shouldCache = true;
          m_data.vec->vals[i] = val;
        }
      } else {
        m_data.map = new ImmutableMap(size);
        for (ArrayIter it(arr); !it.end(); it.next()) {
          SharedVariant* key = Create(it.first(), false, true,
                                      unserializeObj);
          SharedVariant* val = Create(it.secondRef(), false, true,
                                      unserializeObj);
          if (val->m_shouldCache) m_shouldCache = true;
          m_data.map->add(key, val);
        }
      }
      break;
    }
  case KindOfNull:
    {
      m_data.num = 0;
      break;
    }
  default:
    {
      ASSERT(source.isObject());
      m_shouldCache = true;
      if (unserializeObj) {
        // This assumes hasInternalReference(seen, true) is false
        ImmutableObj* obj = new ImmutableObj(source.getObjectData());
        m_data.obj = obj;
        setIsObj();
      } else {
        String s = apc_serialize(source);
        m_data.str = new StringData(s.data(), s.size(), CopyString);
      }
      break;
    }
  }
}
コード例 #6
0
ThreadSharedVariant::ThreadSharedVariant(CVarRef source, bool serialized,
                                         bool inner /* = false */) {
  ASSERT(!serialized || source.isString());

  setOwner();
  m_ref = 1;

  switch (source.getType()) {
  case KindOfBoolean:
    {
      m_type = KindOfBoolean;
      m_data.num = source.toBoolean();
      break;
    }
  case KindOfByte:
  case KindOfInt16:
  case KindOfInt32:
  case KindOfInt64:
    {
      m_type = KindOfInt64;
      m_data.num = source.toInt64();
      break;
    }
  case KindOfDouble:
    {
      m_type = KindOfDouble;
      m_data.dbl = source.toDouble();
      break;
    }
  case KindOfStaticString:
  case KindOfString:
    {
      String s = source.toString();
      m_type = serialized ? KindOfObject : KindOfString;
      if (serialized) {
        // It is priming, and there might not be the right class definitions
        // for unserialization.
        s = apc_reserialize(s);
      }
      m_data.str = s->copy(true);
      break;
    }
  case KindOfArray:
    {
      m_type = KindOfArray;

      ArrayData *arr = source.getArrayData();

      if (!inner) {
        // only need to call hasInternalReference() on the toplevel array
        PointerSet seen;
        if (arr->hasInternalReference(seen)) {
          setSerializedArray();
          setShouldCache();
          String s = apc_serialize(source);
          m_data.str = new StringData(s.data(), s.size(), CopyString);
          break;
        }
      }

      size_t size = arr->size();
      if (arr->isVectorData()) {
        setIsVector();
        m_data.vec = new VectorData(size);
        uint i = 0;
        for (ArrayIter it(arr); !it.end(); it.next(), i++) {
          ThreadSharedVariant* val = createAnother(it.second(), false, true);
          if (val->shouldCache()) setShouldCache();
          m_data.vec->vals[i] = val;
        }
      } else {
        m_data.map = new ImmutableMap(size);
        uint i = 0;
        for (ArrayIter it(arr); !it.end(); it.next(), i++) {
          ThreadSharedVariant* key = createAnother(it.first(), false);
          ThreadSharedVariant* val = createAnother(it.second(), false, true);
          if (val->shouldCache()) setShouldCache();
          m_data.map->add(key, val);
        }
      }
      break;
    }
  default:
    {
      m_type = KindOfObject;
      setShouldCache();
      String s = apc_serialize(source);
      m_data.str = new StringData(s.data(), s.size(), CopyString);
      break;
    }
  }
}
コード例 #7
0
SharedVariant::SharedVariant(CVarRef source, bool serialized,
                             bool inner /* = false */,
                             bool unserializeObj /* = false */)
  : m_shouldCache(false), m_flags(0) {
  assert(!serialized || source.isString());
  m_count = 1;
  m_type = source.getType();
  switch (m_type) {
  case KindOfBoolean:
    {
      m_data.num = source.toBoolean();
      break;
    }
  case KindOfInt64:
    {
      m_type = KindOfInt64;
      m_data.num = source.toInt64();
      break;
    }
  case KindOfDouble:
    {
      m_data.dbl = source.toDouble();
      break;
    }
  case KindOfStaticString:
    {
      if (serialized) goto StringCase;
      m_data.str = source.getStringData();
      break;
    }
StringCase:
  case KindOfString:
    {
      String s = source.toString();
      if (serialized) {
        m_type = KindOfObject;
        // It is priming, and there might not be the right class definitions
        // for unserialization.
        s = apc_reserialize(s);
      }
      StringData* st = StringData::LookupStaticString(s.get());
      if (st) {
        m_data.str = st;
        m_type = KindOfStaticString;
        break;
      }
      m_data.str = s->copy(true);
      break;
    }
  case KindOfArray:
    {
      ArrayData *arr = source.getArrayData();

      if (!inner) {
        // only need to call hasInternalReference() on the toplevel array
        PointerSet seen;
        if (arr->hasInternalReference(seen)) {
          setSerializedArray();
          m_shouldCache = true;
          String s = apc_serialize(source);
          m_data.str = StringData::MakeMalloced(s.data(), s.size());
          break;
        }
      }

      if (arr->isVectorData()) {
        setIsVector();
        m_data.vec = new (arr->size()) VectorData();
        for (ArrayIter it(arr); !it.end(); it.next()) {
          SharedVariant* val = Create(it.secondRef(), false, true,
                                      unserializeObj);
          if (val->m_shouldCache) m_shouldCache = true;
          m_data.vec->vals()[m_data.vec->m_size++] = val;
        }
      } else {
        m_data.map = ImmutableMap::Create(arr, unserializeObj, m_shouldCache);
      }
      break;
    }
  case KindOfUninit:
  case KindOfNull:
    {
      break;
    }
  case KindOfResource:
    {
      // TODO Task #2661075: Here and elsewhere in the runtime, we convert
      // Resources to the empty array during various serialization operations,
      // which does not match Zend behavior. We should fix this.
      m_type = KindOfArray;
      setIsVector();
      m_data.vec = new (0) VectorData();
      break;
    }
  default:
    {
      assert(source.isObject());
      m_shouldCache = true;
      if (unserializeObj) {
        // This assumes hasInternalReference(seen, true) is false
        ImmutableObj* obj = new ImmutableObj(source.getObjectData());
        m_data.obj = obj;
        setIsObj();
      } else {
        String s = apc_serialize(source);
        m_data.str = StringData::MakeMalloced(s.data(), s.size());
      }
      break;
    }
  }
  assert(m_type != KindOfResource);
}