//===-- core/SystemImpl.cpp -------------------------------------*- C++ -*-===//
//
//                                 The RoSA Framework
//
//===----------------------------------------------------------------------===//
///
/// \file core/SystemImpl.cpp
///
/// \author David Juhasz (david.juhasz@tuwien.ac.at)
///
/// \date 2017
///
/// \brief Implementation for core/SystemImpl.hpp.
///
//===----------------------------------------------------------------------===//

#include "SystemImpl.hpp"

#include "rosa/core/Unit.h"

namespace rosa {

SystemImpl::SystemImpl(const std::string &Name) noexcept : SystemBase(Name) {}

SystemImpl::~SystemImpl(void) {
  if (!empty()) {
    ROSA_CRITICAL("Trying to destroy a non-empty System '" + Name + "'");
  } else {
    markCleaned();
  }
}

void SystemImpl::registerUnit(Unit &U) noexcept {
  ASSERT(!isUnitRegistered(U) && "Unit already registered!");

  // Obtain exclusive access and insert the \c rosa::Unit instance.
  std::lock_guard<std::mutex> L(RegisterMutex);
  auto R = Units.insert(&U);
  if (!R.second) {
    ROSA_CRITICAL("Could not register Unit");
  }
}

void SystemImpl::destroyUnit(Unit &U) noexcept {
  ASSERT(isUnitRegistered(U));
  LOG_TRACE("Destroying Unit '" + U.FullName + "'");
  // Scope protected container access.
  {
    // Obtain exclusive access and remove the Unit.
    std::lock_guard<std::mutex> L(RegisterMutex);
    auto R = Units.erase(&U);
    // \note This case is catched by assertion when that is enabled.
    if (!R) {
      ROSA_CRITICAL("Trying to remove unregistered Unit");
    }
  }
  delete &U;
}

bool SystemImpl::isUnitRegistered(const Unit &U) const noexcept {
  // \note Casting away constness is safe here.
  return Units.find(const_cast<Unit *>(&U)) != Units.cend();
}

size_t SystemImpl::numberOfLiveUnits(void) const noexcept {
  return Units.size();
}

bool SystemImpl::empty(void) const noexcept { return Units.empty(); }

} // End namespace rosa
