Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
[xbt] Type-safe Facetable levels
authorGabriel Corona <gabriel.corona@loria.fr>
Thu, 17 Dec 2015 10:07:40 +0000 (11:07 +0100)
committerGabriel Corona <gabriel.corona@loria.fr>
Thu, 17 Dec 2015 11:05:57 +0000 (12:05 +0100)
For compatibility with C, the type-safety is currently not strongly
enforced.

12 files changed:
include/xbt/Facetable.hpp
src/simdag/sd_global.c
src/simgrid/host.cpp
src/surf/cpu_interface.cpp
src/surf/cpu_interface.hpp
src/surf/host_clm03.cpp
src/surf/host_interface.cpp
src/surf/host_interface.hpp
src/surf/host_ptask_L07.cpp
src/surf/surf_c_bindings.cpp
src/surf/surf_interface.cpp
src/surf/virtual_machine.cpp

index 08be86e..84fe635 100644 (file)
@@ -8,12 +8,27 @@
 #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.
@@ -29,7 +44,6 @@ namespace xbt {
  * Instead, you should add a new facet to the Host class, that happens to be Facetable.
  *
  */
-
 template<class T>
 class Facetable {
 private:
@@ -37,16 +51,21 @@ 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()
@@ -56,7 +75,7 @@ public:
         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())
@@ -73,6 +92,22 @@ public:
     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>
index dad96a3..b625857 100644 (file)
@@ -211,7 +211,7 @@ void SD_create_environment(const char *platform_file)
     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);
     }
index d7ec5f1..f2d53f3 100644 (file)
@@ -58,7 +58,6 @@ int MSG_HOST_LEVEL;
 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
@@ -81,7 +80,7 @@ void sg_host_init()
   });
   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);
 }
@@ -131,10 +130,10 @@ void sg_host_simix_destroy(sg_host_t host) {
 
 // ========== 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)
 {
@@ -143,7 +142,7 @@ 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) {
index a8d80c7..17029db 100644 (file)
@@ -20,6 +20,14 @@ simgrid::surf::CpuModel *surf_cpu_model_vm;
 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 *
  *************/
index c74e737..79bc81d 100644 (file)
@@ -100,6 +100,8 @@ public:
 */
 XBT_PUBLIC_CLASS Cpu : public simgrid::surf::Resource {
 public:
+  static simgrid::xbt::FacetLevel<simgrid::Host, Cpu> LEVEL;
+  static void init();
   Cpu();
 
   /**
index a54d733..fd7e445 100644 (file)
@@ -53,7 +53,7 @@ Host *HostCLM03Model::createHost(const char *name,RoutingEdge *netElm, Cpu *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;
 }
 
index 737583b..81037bc 100644 (file)
@@ -6,6 +6,8 @@
 
 #include "host_interface.hpp"
 
+#include <simgrid/Host.hpp>
+
 #include "src/simix/smx_private.h"
 #include "cpu_cas01.hpp"
 #include "simgrid/sg_config.h"
@@ -28,7 +30,9 @@ void host_add_traces(){
 
 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;
@@ -76,6 +80,15 @@ void HostModel::adjustWeightOfDummyCpuActions()
 /************
  * 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)
index 70b7c1c..915c14a 100644 (file)
@@ -96,6 +96,8 @@ public:
  */
 class Host : public simgrid::surf::Resource {
 public:
+  static simgrid::xbt::FacetLevel<simgrid::Host, Host> LEVEL;
+  static void init();
   /**
    * @brief Host constructor
    *
index 82a0951..6d92e97 100644 (file)
@@ -275,7 +275,7 @@ Host *HostL07Model::createHost(const char *name,RoutingEdge *netElm, Cpu *cpu)
   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;
 }
index fb4004a..740ed9d 100644 (file)
@@ -171,7 +171,7 @@ void routing_get_route_and_latency(sg_routing_edge_t src, sg_routing_edge_t dst,
 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();
 }
 
@@ -396,7 +396,7 @@ void surf_vm_destroy(sg_host_t resource){
   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);
index e5cee41..0f43bcf 100644 (file)
@@ -269,11 +269,6 @@ static XBT_INLINE void routing_asr_prop_free(void *p)
   //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);
@@ -321,7 +316,7 @@ void surf_init(int *argc, char **argv)
   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);
index 9be8a78..9fc07fc 100644 (file)
@@ -38,7 +38,7 @@ VirtualMachine::VirtualMachine(Model *model, const char *name, xbt_dict_t props,
 : 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);
 }
 
 /*