Program Listing for File object_identifier.h

Return to documentation for file (include/shad/data_structures/object_identifier.h)

//===------------------------------------------------------------*- C++ -*-===//
//
//                                     SHAD
//
//      The Scalable High-performance Algorithms and Data Structure Library
//
//===----------------------------------------------------------------------===//
//
// Copyright 2018 Battelle Memorial Institute
//
// 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.
//
//===----------------------------------------------------------------------===//

#ifndef INCLUDE_SHAD_DATA_STRUCTURES_OBJECT_IDENTIFIER_H_
#define INCLUDE_SHAD_DATA_STRUCTURES_OBJECT_IDENTIFIER_H_

#include <atomic>
#include <limits>
#include "shad/runtime/runtime.h"

namespace shad {
template <typename T>
class ObjectIdentifier {
 public:
  static const ObjectIdentifier<T> kNullID;

  static constexpr uint8_t kLocalityIdBitsize = 16u;

  static constexpr uint8_t kIdentifierBitsize = 48u;

  explicit constexpr ObjectIdentifier(uint64_t id) : id_(id) {}

  ObjectIdentifier(const rt::Locality &locality, uint64_t localID) {
    id_ = static_cast<uint32_t>(locality);
    id_ <<= kIdentifierBitsize;
    id_ |= localID;
  }

  ObjectIdentifier(const ObjectIdentifier &oid) = default;

  ObjectIdentifier(ObjectIdentifier &&) noexcept = default;

  ObjectIdentifier &operator=(ObjectIdentifier &&) noexcept = default;

  friend bool operator<(const ObjectIdentifier &lhs,
                        const ObjectIdentifier &rhs) {
    return lhs.id_ < rhs.id_;
  }

  ObjectIdentifier &operator=(const ObjectIdentifier &rhs) = default;

  explicit operator uint64_t() const { return static_cast<uint64_t>(id_); }

  rt::Locality GetOwnerLocality() const {
    return rt::Locality(uint32_t(id_ >> kIdentifierBitsize));
  }

  size_t GetLocalID() const { return id_ & kIdentifierBitMask; }

 private:
  static constexpr uint64_t kIdentifierBitMask =
      ((uint64_t(1) << kIdentifierBitsize) - 1);

  uint64_t id_;
};

template <typename T>
const ObjectIdentifier<T> ObjectIdentifier<T>::kNullID =
    ObjectIdentifier<T>(std::numeric_limits<uint64_t>::max());

template <typename T>
constexpr uint8_t ObjectIdentifier<T>::kIdentifierBitsize;

template <typename T>
constexpr uint64_t ObjectIdentifier<T>::kIdentifierBitMask;

template <typename T>
inline bool operator>(const ObjectIdentifier<T> &lhs,
                      const ObjectIdentifier<T> &rhs) {
  return rhs < lhs;
}

template <typename T>
inline bool operator<=(const ObjectIdentifier<T> &lhs,
                       const ObjectIdentifier<T> &rhs) {
  return !(lhs > rhs);
}

template <typename T>
inline bool operator>=(const ObjectIdentifier<T> &lhs,
                       const ObjectIdentifier<T> &rhs) {
  return !(lhs < rhs);
}

template <typename T>
inline bool operator==(const ObjectIdentifier<T> &lhs,
                       const ObjectIdentifier<T> &rhs) {
  return !(rhs < lhs) && !(lhs < rhs);
}

template <typename T>
inline bool operator!=(const ObjectIdentifier<T> &lhs,
                       const ObjectIdentifier<T> &rhs) {
  return !(lhs == rhs);
}

template <typename T>
std::ostream &operator<<(std::ostream &out, const ObjectIdentifier<T> &rhs) {
  auto node = rhs.GetOwnerLocality();
  size_t objectId = rhs.GetLocalID();
  return out << "NodeOwner[" << node << "] id = " << objectId;
}

template <typename T>
class ObjectIdentifierCounter {
 public:
  static ObjectIdentifierCounter<T> &Instance() {
    static ObjectIdentifierCounter<T> instance;
    return instance;
  }
  ObjectIdentifier<T> operator++(int) {
    uint64_t value = counter_.fetch_add(1);
    return ObjectIdentifier<T>(value);
  }

  explicit operator uint64_t() const { return static_cast<uint64_t>(counter_); }

 private:
  ObjectIdentifierCounter() {
    // note that in the following, the cast to uint32_t invokes the conversion
    // operator of the rt::thisLocality object, but we need a uint64_t.
    counter_ = static_cast<uint64_t>(static_cast<uint32_t>(rt::thisLocality()))
               << ObjectIdentifier<T>::kIdentifierBitsize;
  }

  std::atomic<uint64_t> counter_;
};

template <typename T>
std::ostream &operator<<(std::ostream &out,
                         const ObjectIdentifierCounter<T> &rhs) {
  uint64_t objectIdentifier = static_cast<uint64_t>(rhs);
  uint64_t node = objectIdentifier >> ObjectIdentifier<T>::kIdentifierBitsize;
  uint64_t objectId =
      ObjectIdentifier<T>::kIdentifierBitMask & objectIdentifier;
  return out << "NodeOwner[" << node << "] id = " << objectId;
}

}  // namespace shad

#endif  // INCLUDE_SHAD_DATA_STRUCTURES_OBJECT_IDENTIFIER_H_