1 /* Copyright (c) 2015. The SimGrid Team.
2 * All rights reserved. */
4 /* This program is free software; you can redistribute it and/or modify it
5 * under the terms of the license (GNU LGPL) which comes with this package. */
7 #ifndef SIMGRID_XBT_LIB_HPP
8 #define SIMGRID_XBT_LIB_HPP
17 /** A Facetable is an object that you can extend with external facets.
19 * Facets are similar to the concept of mixins, that is, a set of behavior that is injected into a class without derivation.
21 * Imagine that you want to write a plugin dealing with the energy in SimGrid.
22 * You will have to store some information about each and every host.
24 * You could modify the Host class directly (but your code will soon become messy).
25 * You could create a class EnergyHost deriving Host, but it is not easily combinable
26 * with a notion of Host extended with another concept (such as mobility).
27 * You could completely externalize these data with an associative map Host->EnergyHost.
28 * It would work, provided that you implement this classical feature correctly (and it would induce a little performance penalty).
29 * Instead, you should add a new facet to the Host class, that happens to be Facetable.
36 static std::vector<void(*)(void*)> deleters_;
38 std::vector<void*> facets_;
40 static std::size_t add_level(void (*deleter)(void*))
42 std::size_t res = deleters_.size();
43 deleters_.push_back(deleter);
46 template<class U> static
47 std::size_t add_level()
49 return add_level([](void* p){ delete (U*)p; });
51 Facetable() : facets_(deleters_.size(), nullptr) {}
54 for (std::size_t i = 0; i < facets_.size(); ++i)
55 if (facets_[i] != nullptr)
56 deleters_[i](facets_[i]);
59 // TODO, make type-safe versions of this
60 void* facet(std::size_t level)
62 if (level >= facets_.size())
65 return facets_.at(level);
67 void set_facet(std::size_t level, void* value, bool use_dtor = true)
69 if (level >= facets_.size())
70 facets_.resize(level + 1, nullptr);
71 void* old_value = this->facet(level);
72 facets_.at(level) = value;
73 if (use_dtor && old_value != nullptr && deleters_[level])
74 deleters_[level](old_value);
79 std::vector<void(*)(void*)> Facetable<T>::deleters_ = {};