Program Listing for File sorting_status.hpp

Return to documentation for file (src/sorting_status.hpp)

/* This file is part of brille.

Copyright © 2020 Greg Tucker <greg.tucker@stfc.ac.uk>

brille is free software: you can redistribute it and/or modify it under the
terms of the GNU Affero General Public License as published by the Free
Software Foundation, either version 3 of the License, or (at your option)
any later version.

brille is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License
along with brille. If not, see <https://www.gnu.org/licenses/>.            */
#ifndef BRILLE_SORTING_STATUS_HPP_
#define BRILLE_SORTING_STATUS_HPP_
namespace brille {
class SortingStatus{
public:
  using status_t = unsigned int;
private:
  status_t status;
  static const status_t s_mask{1u};
  static const status_t l_mask{2u};
  static const status_t q_mask{4u};
  static const status_t c_mask{8u};
  static const status_t v_mask{static_cast<status_t>(-1)^15u};
  static const status_t v_shift{4u};
public:
  explicit SortingStatus(status_t s=0u): status{s} {};
  SortingStatus(bool s, bool f, unsigned int v): status{0} {
    this->sorted(s);
    this->locked(f);
    this->visits(v);
  }
  bool sorted() const { return status & s_mask; }
  bool locked() const { return status & l_mask; }
  bool queued() const { return status & q_mask; }
  bool claimed() const { return status & c_mask; }
  bool visited() const { return (status & v_mask) > 0; }
  status_t visits() const { return status>>v_shift; }
  bool sorted(bool s) {
    if (this->sorted() != s) {
      status_t rem = this->status & (l_mask + q_mask + c_mask + v_mask);
      this->status = rem + (s ? s_mask : 0u);
    }
    return this->sorted();
  }
  bool locked(bool l){
    if (this->locked() != l){
      status_t rem = this->status & (s_mask + q_mask + c_mask + v_mask);
      this->status = rem + (l ? l_mask : 0u);
    }
    return this->locked();
  }
  bool queued(bool q){
    if (this->queued() != q){
      status_t rem = this->status & (s_mask + l_mask + c_mask + v_mask);
      this->status = rem + (q ? q_mask : 0u);
    }
    return this->queued();
  }
  bool claimed(bool c){
    if (this->claimed() != c){
      status_t rem = this->status & (s_mask + l_mask + q_mask + v_mask);
      this->status = rem + (c ? c_mask : 0u);
    }
    return this->claimed();
  }
  template<typename T>
  status_t visits(T v) {
    if (v <= static_cast<status_t>(-1) >> v_shift){
      this->status ^= v_mask; // keep everything but the number of visits
      this->status += v << v_shift; // add the offset visits value
    }
    else
      throw std::overflow_error("SortingStatus can not hold more than 2^29-1 visits.");
    return this->visits();
  }
  status_t addvisit() {
    if (this->status < v_mask)
      this->status += (1u << v_shift);
    else
      throw std::overflow_error("SortingStatus can not hold more than 2^29-1 visits.");
    return this->visits();
  }
  template<class T>
  status_t addvisit(const T max_visits){
    if (this->visits() < max_visits) return this->addvisit();
    this->locked(true);
    return this->visits();
  }
  template<class T>
  bool unlocked_addvisit_unsorted(const T max_visits){
    if (this->locked()) return false;
    this->addvisit(max_visits);
    if (this->sorted()) return false;
    return true;
  }
  std::string to_string() const {
    std::string str;
    bool s{this->sorted()}, l{this->locked()};
    if (s) str += "sorted";
    if (l){
      if (s) str += " and ";
      str += "locked";
    }
    if (l||s) str += " in ";
    str += std::to_string(this->visits()) + " visits";
    return str;
  }

  bool is_queable() const {
    return !(this->locked() || this->sorted() || this->queued() || this->claimed());
    // only queable if not locked, sorted, queued, or claimed
    // 15u == 1u + 2u + 4u + 8u
    // return 15u == (this->status&15u)^15u;
  }

};

}
#endif