/*******************************************************************************
 *
 * File:     SystemBase.hpp
 *
 * Contents: Declaration of the base implementation of the System interface.
 *
 * Copyright 2017
 *
 * Author: David Juhasz (david.juhasz@tuwien.ac.at)
 *
 ******************************************************************************/

#ifndef ROSA_CORE_SYSTEMBASE_HPP
#define ROSA_CORE_SYSTEMBASE_HPP

#include "rosa/core/System.hpp"

#include <atomic>

namespace rosa {

// Base implementation of the System interface, that provides only the name of
// the System, identifiers for Units, and marking the System cleaned for
// destruction.
// NOTE: Actual implementations of the System and derived interfaces are
// supposed to inherit from this base implementation.
class SystemBase : public System {
protected:
  // Protected ctor, only subclasses can instantiate.
  SystemBase(const std::string &Name) noexcept;

public:
  // Dtor.
  // PRE: isSystemCleaned()
  ~SystemBase(void);

protected:
  // The textual name of the System.
  const std::string Name;

private:
  // Number of Units constructed in the system.
  // NOTE: Should never be decremented!
  std::atomic<size_t> CountUnits;

  // Indicates that the System has been cleaned and is ready for destruction.
  // The field is initialized as 'false' and can be set by the member function
  // markCleaned.
  // Subclasses must set the flag upon destroying the System instance, which
  // indicates to the destructor of the base-class that all the managed
  // resources has been properly released.
  std::atomic<bool> SystemCleaned;

public:
  // Returns a referene to the Name field.
  const std::string &name(void) const noexcept override;

protected:
  // Tells the next Id to be used for a newly created Unit while
  // incrementing the value in field CountUnits.
  // NOTE: This is the only function modifying the member field CountUnits.
  id_t nextId(void) noexcept override;

  // Returns the value of SystemCleaned flag.
  bool isSystemCleaned(void) const noexcept override;

  // Sets SystemCleaned flag.
  // PRE: !isSystemCleaned() && empty()
  // POST: isSystemCleaned
  void markCleaned(void) noexcept override;

  // Returns the number of Units constructed in the System so far,
  // including those being already destroyed.
  size_t numberOfConstructedUnits(void) const noexcept override;
};

} // End namespace rosa

#endif // ROSA_LIB_CORE_SYSTEMBASE_HPP

