#pragma once #include "defs.h" #include #include #include using TCpuId = ui32; // Simple data structure to operate with set of cpus struct TCpuMask { TStackVec Cpus; // Creates empty mask TCpuMask() {} // Creates mask with single cpu set explicit TCpuMask(TCpuId cpuId) { Set(cpuId); } // Initialize mask from raw boolean array template TCpuMask(const T* cpus, TCpuId size) { Cpus.reserve(size); for (TCpuId i = 0; i != size; ++i) { Cpus.emplace_back(bool(cpus[i])); } } // Parse a numerical list of processors. The numbers are separated by commas and may include ranges. For example: 0,5,7,9-11 explicit TCpuMask(const TString& cpuList) { try { for (TStringBuf s : StringSplitter(cpuList).Split(',')) { TCpuId l, r; if (s.find('-') != TString::npos) { StringSplitter(s).Split('-').CollectInto(&l, &r); } else { l = r = FromString(s); } if (r >= Cpus.size()) { Cpus.resize(r + 1, false); } for (TCpuId cpu = l; cpu <= r; cpu++) { Cpus[cpu] = true; } } } catch (...) { ythrow TWithBackTrace() << "Exception occured while parsing cpu list '" << cpuList << "': " << CurrentExceptionMessage(); } } // Returns size of underlying vector TCpuId Size() const { return Cpus.size(); } // Returns number of set bits in mask TCpuId CpuCount() const { TCpuId result = 0; for (bool value : Cpus) { result += value; } return result; } bool IsEmpty() const { for (bool value : Cpus) { if (value) { return false; } } return true; } bool IsSet(TCpuId cpu) const { return cpu < Cpus.size() && Cpus[cpu]; } void Set(TCpuId cpu) { if (cpu >= Cpus.size()) { Cpus.resize(cpu + 1, false); } Cpus[cpu] = true; } void Reset(TCpuId cpu) { if (cpu < Cpus.size()) { Cpus[cpu] = false; } } void RemoveTrailingZeros() { while (!Cpus.empty() && !Cpus.back()) { Cpus.pop_back(); } } explicit operator bool() const { return !IsEmpty(); } TCpuMask operator &(const TCpuMask& rhs) const { TCpuMask result; TCpuId size = Max(Size(), rhs.Size()); result.Cpus.reserve(size); for (TCpuId cpu = 0; cpu < size; cpu++) { result.Cpus.emplace_back(IsSet(cpu) && rhs.IsSet(cpu)); } return result; } TCpuMask operator |(const TCpuMask& rhs) const { TCpuMask result; TCpuId size = Max(Size(), rhs.Size()); result.Cpus.reserve(size); for (TCpuId cpu = 0; cpu < size; cpu++) { result.Cpus.emplace_back(IsSet(cpu) || rhs.IsSet(cpu)); } return result; } TCpuMask operator -(const TCpuMask& rhs) const { TCpuMask result; result.Cpus.reserve(Size()); for (TCpuId cpu = 0; cpu < Size(); cpu++) { result.Cpus.emplace_back(IsSet(cpu) && !rhs.IsSet(cpu)); } return result; } };