#pragma once #include #include #include #include #include #include namespace ksys::util { template class AtomicLongBitFlag { public: using Word = sead::Atomic; void makeAllZero() { mStorage.fill(0); } void makeAllOne() { mStorage.fill(~Word(0)); } Word& getWord(Enum bit); const Word& getWord(Enum bit) const; bool isZero() const; bool setBit(Enum bit); bool resetBit(Enum bit); bool changeBit(Enum bit, bool on); bool isOnBit(Enum bit) const; bool isOffBit(Enum bit) const; protected: static constexpr s32 BitsPerWord = 8 * sizeof(Word); static_assert(N % BitsPerWord == 0, "N must be a multiple of the number of bits per word"); sead::SafeArray mStorage{}; }; template inline typename AtomicLongBitFlag::Word& AtomicLongBitFlag::getWord(Enum bit) { return mStorage[s32(bit) / BitsPerWord]; } template inline const typename AtomicLongBitFlag::Word& AtomicLongBitFlag::getWord(Enum bit) const { return mStorage[s32(bit) / BitsPerWord]; } template inline bool AtomicLongBitFlag::setBit(Enum bit) { return getWord(bit).setBitOn(s32(bit) % BitsPerWord); } template inline bool AtomicLongBitFlag::resetBit(Enum bit) { return getWord(bit).setBitOff(s32(bit) % BitsPerWord); } template inline bool AtomicLongBitFlag::changeBit(Enum bit, bool on) { if (on) return setBit(bit); else return resetBit(bit); } template inline bool AtomicLongBitFlag::isOnBit(Enum bit) const { return getWord(bit).isBitOn(s32(bit) % BitsPerWord); } template inline bool AtomicLongBitFlag::isOffBit(Enum bit) const { return !isOnBit(bit); } template inline bool AtomicLongBitFlag::isZero() const { for (const auto& word : mStorage) { if (word != 0) return false; } return true; } } // namespace ksys::util