+#include "simgrid/s4u/storage.hpp"
+
+xbt_dict_t host_list = nullptr; // FIXME: move it to Engine
+
+int MSG_HOST_LEVEL = -1;
+int USER_HOST_LEVEL = -1;
+
+namespace simgrid {
+
+namespace xbt {
+template class Extendable<simgrid::s4u::Host>;
+}
+
+namespace s4u {
+
+simgrid::xbt::signal<void(Host&)> Host::onCreation;
+simgrid::xbt::signal<void(Host&)> Host::onDestruction;
+simgrid::xbt::signal<void(Host&)> Host::onStateChange;
+
+Host::Host(const char* name)
+ : name_(name)
+{
+ xbt_assert(sg_host_by_name(name) == nullptr, "Refusing to create a second host named '%s'.", name);
+ xbt_dict_set(host_list, name, this, nullptr);
+}
+
+Host::~Host()
+{
+ xbt_assert(currentlyDestroying_, "Please call h->destroy() instead of manually deleting it.");
+
+ delete pimpl_cpu;
+ delete pimpl_netcard;
+ delete mounts;
+}
+
+/** @brief Fire the required callbacks and destroy the object
+ *
+ * Don't delete directly an Host, call h->destroy() instead.
+ *
+ * This is cumbersome but there is the simplest solution to ensure that the
+ * onDestruction() callback receives a valid object (because of the destructor
+ * order in a class hierarchy).
+ */
+void Host::destroy()
+{
+ if (!currentlyDestroying_) {
+ currentlyDestroying_ = true;
+ xbt_dict_remove(host_list, name().c_str());
+ onDestruction(*this);
+ delete this;
+ }
+}
+
+Host* Host::by_name(std::string name)
+{
+ Host* host = Host::by_name_or_null(name.c_str());
+ // TODO, raise an exception instead?
+ if (host == nullptr)
+ xbt_die("No such host: '%s'", name.c_str());
+ return host;
+}
+Host* Host::by_name_or_null(const char* name)
+{
+ if (host_list == nullptr)
+ host_list = xbt_dict_new_homogeneous(nullptr);
+ return (Host*) xbt_dict_get_or_null(host_list, name);
+}
+
+Host *Host::current(){
+ smx_actor_t smx_proc = SIMIX_process_self();
+ if (smx_proc == nullptr)
+ xbt_die("Cannot call Host::current() from the maestro context");
+ return smx_proc->host;
+}
+
+void Host::turnOn() {
+ if (isOff()) {
+ simgrid::simix::kernelImmediate([&]{
+ this->extension<simgrid::simix::Host>()->turnOn();
+ this->extension<simgrid::surf::HostImpl>()->turnOn();
+ });
+ }
+}
+
+void Host::turnOff() {
+ if (isOn()) {
+ simgrid::simix::kernelImmediate(std::bind(SIMIX_host_off, this, SIMIX_process_self()));
+ }
+}
+
+bool Host::isOn() {
+ return this->pimpl_cpu->isOn();
+}
+
+int Host::pstatesCount() const {
+ return this->pimpl_cpu->getNbPStates();
+}
+
+boost::unordered_map<std::string, Storage*> const& Host::mountedStorages() {
+ if (mounts == nullptr) {
+ mounts = new boost::unordered_map<std::string, Storage*> ();