Object c_AwaitAllWaitHandle::ti_fromarray(const Array& dependencies) {
  auto ad = dependencies.get();
  assert(ad);
  if (!ad->size()) return returnEmpty();

retry:
  switch (ad->kind()) {
    case ArrayData::kPackedKind:
      return FromPackedArray(ad);

    case ArrayData::kMixedKind:
    case ArrayData::kStructKind:
      return FromMixedArray(MixedArray::asMixed(ad));

    case ArrayData::kProxyKind:
      ad = ProxyArray::innerArr(ad);
      goto retry;

    case ArrayData::kApcKind:
    case ArrayData::kGlobalsKind:
      // APC can't store WaitHandles, GlobalsArray is used only for
      // $GLOBALS, which contain non-WaitHandles.
      failArray();

    case ArrayData::kEmptyKind:
      // Handled by dependencies->size() check.
      not_reached();

    case ArrayData::kNumKinds:
      not_reached();
  }

  not_reached();
}
Exemple #2
0
Object c_AwaitAllWaitHandle::FromPackedArray(const ArrayData* dependencies) {
  auto const start = reinterpret_cast<const TypedValue*>(dependencies + 1);
  auto const stop = start + dependencies->getSize();
  int32_t cnt = 0;

  for (auto iter = start; iter < stop; ++iter) {
    auto const current = tvToCell(iter);
    auto const child = c_WaitHandle::fromCell(current);
    if (UNLIKELY(!child)) failArray();
    cnt += !child->isFinished();
  }

  if (!cnt) return returnEmpty();

  SmartPtr<c_AwaitAllWaitHandle> result(Alloc(cnt));
  auto next = &result->m_children[cnt];

  for (auto iter = start; iter < stop; ++iter) {
    auto const current = tvToCell(iter);
    auto const child = c_WaitHandle::fromCell(current);
    if (child->isFinished()) continue;
    child->incRefCount();
    *(--next) = static_cast<c_WaitableWaitHandle*>(child);
  }

  assert(next == &result->m_children[0]);
  result->initialize();
  return Object(std::move(result));
}
Exemple #3
0
Object c_AwaitAllWaitHandle::FromMixedArray(const MixedArray* dependencies) {
  auto const start = dependencies->data();
  auto const stop = start + dependencies->iterLimit();
  int32_t cnt = 0;

  for (auto iter = start; iter < stop; ++iter) {
    if (MixedArray::isTombstone(iter->data.m_type)) continue;
    auto const current = tvToCell(&iter->data);
    auto const child = c_WaitHandle::fromCell(current);
    if (UNLIKELY(!child)) failArray();
    cnt += !child->isFinished();
  }

  if (!cnt) return returnEmpty();

  SmartPtr<c_AwaitAllWaitHandle> result(Alloc(cnt));
  auto next = &result->m_children[cnt];

  for (auto iter = start; iter < stop; ++iter) {
    if (MixedArray::isTombstone(iter->data.m_type)) continue;
    auto const current = tvToCell(&iter->data);
    auto const child = c_WaitHandle::fromCell(current);
    if (child->isFinished()) continue;
    child->incRefCount();
    *(--next) = static_cast<c_WaitableWaitHandle*>(child);
  }

  assert(next == &result->m_children[0]);
  result->initialize();
  return Object(std::move(result));
}
Object HHVM_STATIC_METHOD(AwaitAllWaitHandle, fromArray,
                          const Array& dependencies) {
  auto ad = dependencies.get();
  assertx(ad);
  assertx(ad->isPHPArray());
  if (!ad->size()) return Object{returnEmpty()};

retry:
  switch (ad->kind()) {
    case ArrayData::kPackedKind:
      return c_AwaitAllWaitHandle::Create<true>([=](auto fn) {
        PackedArray::IterateV(ad, fn);
      });

    case ArrayData::kMixedKind:
      return c_AwaitAllWaitHandle::Create<true>([=](auto fn) {
        MixedArray::IterateV(MixedArray::asMixed(ad), fn);
      });

    case ArrayData::kProxyKind:
      ad = ProxyArray::innerArr(ad);
      goto retry;

    case ArrayData::kApcKind:
    case ArrayData::kGlobalsKind:
      // APC can't store WaitHandles, GlobalsArray is used only for
      // $GLOBALS, which contain non-WaitHandles.
      failArray();

    case ArrayData::kEmptyKind:
      // Handled by dependencies->size() check.
      not_reached();

    case ArrayData::kVecKind:
    case ArrayData::kDictKind:
    case ArrayData::kKeysetKind:
      // Shouldn't get Hack arrays
      not_reached();

    case ArrayData::kNumKinds:
      not_reached();
  }

  not_reached();
}