#define SIMGRID_XBT_LIB_HPP
#include <cstddef>
-
+#include <limits>
#include <vector>
namespace simgrid {
namespace xbt {
+template<class T, class U> class FacetLevel;
+template<class T> class Facetable;
+
+template<class T, class U>
+class FacetLevel {
+ static const std::size_t INVALID_ID = std::numeric_limits<std::size_t>::max();
+ std::size_t id_;
+ friend class Facetable<T>;
+ constexpr FacetLevel(std::size_t id) : id_(id) {}
+public:
+ constexpr FacetLevel() : id_(INVALID_ID) {}
+ std::size_t id() const { return id_; }
+ bool valid() { return id_ != INVALID_ID; }
+};
+
/** A Facetable is an object that you can extend with external facets.
*
* Facets are similar to the concept of mixins, that is, a set of behavior that is injected into a class without derivation.
* Instead, you should add a new facet to the Host class, that happens to be Facetable.
*
*/
-
template<class T>
class Facetable {
private:
protected:
std::vector<void*> facets_;
public:
- static std::size_t add_level(void (*deleter)(void*))
+ static size_t add_level(void (*deleter)(void*))
{
std::size_t res = deleters_.size();
deleters_.push_back(deleter);
return res;
}
+ template<class U>
+ static FacetLevel<T,U> add_level(void (*deleter)(void*))
+ {
+ return FacetLevel<T,U>(add_level(deleter));
+ }
template<class U> static
- std::size_t add_level()
+ FacetLevel<T,U> add_level()
{
- return add_level([](void* p){ delete (U*)p; });
+ return add_level([](void* p){ delete static_cast<U*>(p); });
}
Facetable() : facets_(deleters_.size(), nullptr) {}
~Facetable()
deleters_[i](facets_[i]);
}
- // TODO, make type-safe versions of this
+ // Type-unsafe versions of the facet access methods:
void* facet(std::size_t level)
{
if (level >= facets_.size())
if (use_dtor && old_value != nullptr && deleters_[level])
deleters_[level](old_value);
}
+
+ // Type safe versions of the facet access methods:
+ template<class U>
+ U* facet(FacetLevel<T,U> level)
+ {
+ return static_cast<U*>(facet(level.id()));
+ }
+ template<class U>
+ void set_facet(FacetLevel<T,U> level, U* value, bool use_dtor = true)
+ {
+ set_facet(level.id(), value, use_dtor);
+ }
+
+ // Convnience facet access when the type has a associated LEVEL:
+ template<class U> U* facet() { return facet<U>(U::LEVEL); }
+ template<class U> void set_facet(U* p) { set_facet<U>(U::LEVEL, p); }
};
template<class T>
xbt_dict_cursor_t cursor = NULL;
simgrid_Host* host = NULL;
xbt_dict_foreach(host_list, cursor, name, host){
- surf_Host* surf_host = (surf_Host*) sg_host_get_facet(host, SURF_HOST_LEVEL);
+ surf_Host* surf_host = (surf_Host*) surf_host_resource_priv(host);
if (surf_host != NULL)
__SD_workstation_create(surf_host, NULL);
}
int SD_HOST_LEVEL;
int SIMIX_HOST_LEVEL;
int ROUTING_HOST_LEVEL;
-int SURF_CPU_LEVEL;
int USER_HOST_LEVEL;
#include "src/msg/msg_private.h" // MSG_host_priv_free. FIXME: killme
});
SD_HOST_LEVEL = simgrid::Host::add_level(__SD_workstation_destroy);
SIMIX_HOST_LEVEL = simgrid::Host::add_level(SIMIX_host_destroy);
- SURF_CPU_LEVEL = simgrid::Host::add_level(surf_cpu_free);
+ simgrid::surf::Cpu::init();
ROUTING_HOST_LEVEL = simgrid::Host::add_level(routing_asr_host_free);
USER_HOST_LEVEL = simgrid::Host::add_level(NULL);
}
// ========== SURF CPU ============
surf_cpu_t sg_host_surfcpu(sg_host_t host) {
- return (surf_cpu_t) host->facet(SURF_CPU_LEVEL);
+ return host->facet<simgrid::surf::Cpu>();
}
void sg_host_surfcpu_set(sg_host_t host, surf_cpu_t cpu) {
- host->set_facet(SURF_CPU_LEVEL, cpu);
+ host->set_facet(simgrid::surf::Cpu::LEVEL, cpu);
}
void sg_host_surfcpu_register(sg_host_t host, surf_cpu_t cpu)
{
sg_host_surfcpu_set(host, cpu);
}
void sg_host_surfcpu_destroy(sg_host_t host) {
- host->set_facet(SURF_CPU_LEVEL, nullptr);
+ host->set_facet<simgrid::surf::Cpu>(nullptr);
}
// ========== RoutingEdge ============
surf_RoutingEdge *sg_host_edge(sg_host_t host) {
namespace simgrid {
namespace surf {
+simgrid::xbt::FacetLevel<simgrid::Host, Cpu> Cpu::LEVEL;
+
+void Cpu::init()
+{
+ if (!LEVEL.valid())
+ LEVEL = simgrid::Host::add_level<simgrid::surf::Cpu>();
+}
+
/*************
* Callbacks *
*************/
*/
XBT_PUBLIC_CLASS Cpu : public simgrid::surf::Resource {
public:
+ static simgrid::xbt::FacetLevel<simgrid::Host, Cpu> LEVEL;
+ static void init();
Cpu();
/**
netElm, cpu);
surf_callback_emit(hostCreatedCallbacks, host);
XBT_DEBUG("Create host %s with %ld mounted disks", name, xbt_dynar_length(host->p_storage));
- simgrid::Host::by_name_or_null(name)->set_facet(SURF_HOST_LEVEL, host);
+ simgrid::Host::by_name_or_null(name)->set_facet(host);
return host;
}
#include "host_interface.hpp"
+#include <simgrid/Host.hpp>
+
#include "src/simix/smx_private.h"
#include "cpu_cas01.hpp"
#include "simgrid/sg_config.h"
namespace simgrid {
namespace surf {
-
+
+simgrid::xbt::FacetLevel<simgrid::Host, Host> Host::LEVEL;
+
surf_callback(void, simgrid::surf::Host*) hostCreatedCallbacks;
surf_callback(void, simgrid::surf::Host*) hostDestructedCallbacks;
surf_callback(void, simgrid::surf::Host*, e_surf_resource_state_t, e_surf_resource_state_t) hostStateChangedCallbacks;
/************
* Resource *
************/
+
+void Host::init()
+{
+ if (!LEVEL.valid()) {
+ LEVEL = simgrid::Host::add_level<simgrid::surf::Host>();
+ SURF_HOST_LEVEL = LEVEL.id();
+ }
+}
+
Host::Host(simgrid::surf::Model *model, const char *name, xbt_dict_t props,
xbt_dynar_t storage, RoutingEdge *netElm, Cpu *cpu)
: Resource(model, name, props)
*/
class Host : public simgrid::surf::Resource {
public:
+ static simgrid::xbt::FacetLevel<simgrid::Host, Host> LEVEL;
+ static void init();
/**
* @brief Host constructor
*
HostL07 *host = new HostL07(this, name, NULL, netElm, cpu);
surf_callback_emit(hostCreatedCallbacks, host);
- simgrid::Host::by_name_or_create(name)->set_facet(SURF_HOST_LEVEL, host);
+ simgrid::Host::by_name_or_create(name)->set_facet<Host>(host);
return host;
}
surf_host_model_t surf_host_get_model(sg_host_t host)
{
simgrid::surf::Host* surf_host =
- (simgrid::surf::Host*) host->facet(SURF_HOST_LEVEL);
+ (simgrid::surf::Host*) host->facet<simgrid::surf::Host>();
return (surf_host_model_t) surf_host->getModel();
}
sg_host_surfcpu_destroy(resource);
sg_host_edge_destroy(resource,1);
// TODO, use backlink from simgrid::surf::Host to simgrid::Host
- simgrid::Host::by_name_or_null(name)->set_facet(SURF_HOST_LEVEL, nullptr);
+ simgrid::Host::by_name_or_null(name)->set_facet((simgrid::surf::Host*)nullptr);
/* TODO: comment out when VM storage is implemented. */
// host->set_facet(SURF_STORAGE_LEVEL, nullptr);
//xbt_dict_free(&elm); FIXME: leaking in some case? That's a sometimes double-free with AsCluster::~AsCluster
}
-static XBT_INLINE void surf_host_free(void *r)
-{
- delete static_cast<simgrid::surf::Host*>(r);
-}
-
static XBT_INLINE void surf_storage_free(void *r)
{
delete static_cast<simgrid::surf::Storage*>(r);
ROUTING_PROP_ASR_LEVEL = xbt_lib_add_level(as_router_lib,routing_asr_prop_free);
XBT_DEBUG("Add SURF levels");
- SURF_HOST_LEVEL = simgrid::Host::add_level(surf_host_free);
+ simgrid::surf::Host::init();
SURF_STORAGE_LEVEL = xbt_lib_add_level(storage_lib,surf_storage_free);
xbt_init(argc, argv);
: Host(model, name, props, NULL, netElm, cpu)
{
VMModel::ws_vms.push_back(*this);
- simgrid::Host::by_name_or_create(name)->set_facet(SURF_HOST_LEVEL, this);
+ simgrid::Host::by_name_or_create(name)->set_facet<simgrid::surf::Host>(this);
}
/*