/*
 * Copyright 2015 Facebook, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <folly/futures/Barrier.h>

namespace folly { namespace futures {

Barrier::Barrier(uint32_t n)
  : size_(n),
    controlBlock_(allocateControlBlock()) { }

Barrier::~Barrier() {
  auto block = controlBlock_.load(std::memory_order_relaxed);
  auto prev = block->valueAndReaderCount.load(std::memory_order_relaxed);
  DCHECK_EQ(prev >> kReaderShift, 0);
  auto val = prev & kValueMask;
  auto p = promises(block);

  for (uint32_t i = 0; i < val; ++i) {
    p[i].setException(
        folly::make_exception_wrapper<std::runtime_error>("Barrier destroyed"));
  }

  freeControlBlock(controlBlock_);
}

auto Barrier::allocateControlBlock() -> ControlBlock* {
  auto block = static_cast<ControlBlock*>(malloc(controlBlockSize(size_)));
  if (!block) {
    throw std::bad_alloc();
  }
  block->valueAndReaderCount = 0;

  auto p = promises(block);
  uint32_t i = 0;
  try {
    for (i = 0; i < size_; ++i) {
      new (p + i) BoolPromise();
    }
  } catch (...) {
    for (; i != 0; --i) {
      p[i - 1].~BoolPromise();
    }
    throw;
  }

  return block;
}

void Barrier::freeControlBlock(ControlBlock* block) {
  auto p = promises(block);
  for (uint32_t i = size_; i != 0; --i) {
    p[i - 1].~BoolPromise();
  }
  free(block);
}

folly::Future<bool> Barrier::wait() {
  // Load the current control block first. As we know there is at least
  // one thread in the current epoch (us), this means that the value is
  // < size_, so controlBlock_ can't change until we bump the value below.
  auto block = controlBlock_.load(std::memory_order_acquire);
  auto p = promises(block);

  // Bump the value and record ourselves as reader.
  // This ensures that block stays allocated, as the reader count is > 0.
  auto prev = block->valueAndReaderCount.fetch_add(kReader + 1,
                                                   std::memory_order_acquire);

  auto prevValue = static_cast<uint32_t>(prev & kValueMask);
  DCHECK_LT(prevValue, size_);
  auto future = p[prevValue].getFuture();

  if (prevValue + 1 == size_) {
    // Need to reset the barrier before fulfilling any futures. This is
    // when the epoch is flipped to the next.
    controlBlock_.store(allocateControlBlock(), std::memory_order_release);

    p[0].setValue(true);
    for (uint32_t i = 1; i < size_; ++i) {
      p[i].setValue(false);
    }
  }

  // Free the control block if we're the last reader at max value.
  prev = block->valueAndReaderCount.fetch_sub(kReader,
                                              std::memory_order_acq_rel);
  if (prev == (kReader | uint64_t(size_))) {
    freeControlBlock(block);
  }

  return future;
}

}}  // namespaces
