#include "tile/base/thread/latch.h"

namespace tile {
Latch::Latch(std::ptrdiff_t count) : count_(count) {}

void
Latch::CountDown(std::ptrdiff_t update)
{
    TILE_DCHECK_GT(update, 0);

    {
        UniqueLock<Mutex> _(m_);
        TILE_CHECK_GE(count_, update);
        count_ -= update;

        if (count_ == 0) { cv_.NotifyAll(); }
    }
}

bool
Latch::TryWait() const noexcept
{
    UniqueLock<Mutex> _(m_);
    TILE_CHECK_GE(count_, 0);
    return !count_;
}

void
Latch::Wait() const
{
    UniqueLock<Mutex> _(m_);
    TILE_CHECK_GE(count_, 0);
    cv_.Wait(_, [&] { return count_ == 0; });
}

void
Latch::ArriveAndWait(std::ptrdiff_t update)
{
    CountDown(update);
    Wait();
}

}// namespace tile
