Loksim3D Developer Stories – Part 2 – C++ template magic

In Loksim a rail track can have a lot of associated properties. Properties like maximum speed, signals, illumination characteristics, name, stops and so on, which can be seen in the following screenshot:
props

So far the internal implementation of this system heavily depends on constants. For example, if you want to get the maximum speed on a track ‘t’ at position ‘pos’ you would use a function call similar to this:

auto& propSpeed = t.GetProperty(PROPERTY_MAXIMUM_SPEED, pos);

However, ‘p’ does not contain the actual maximum speed: A maximum speed is not a single value, it e.g. contains information if this maximum speed is different for trains with tilt technology or if it is shown in the timetable of the train operator. So a second query – again using a constant – is needed:

float maxSpeed = propSpeed.GetPropertyFloat(PROPERTY_MAXIMUM_SPEED_NORMAL_TRAIN);

This also shows, that one has to know the data type of the actual property when retrieving it. In fact, at the moment all these properties are stored as strings and converted to the requested type when they are queried by the GetPropertyType functions.

This system has two main advantages:

  • It can be extended quite easily: One just has to introduce a new constant PROPERTY_XXX
  • It can be serialized and deserialized to XML in a straightforward way: The values are just written out using the PROPERTY_XXX constants as attribute names

However, working with this system for some years also showed some disadvantages:

  • There does not exist any static check if the property that is queried really makes sense. E.g. in the example above, one could easily write the line propSpeed.GetPropertyString(PROPERTY_STOP_NAME). The compiler can never recognize this error and you would just get an empty property (string) back
  • It can be hard to find the appropriate constant for a property of a rail track. In fact I often end up checking the name in the GUI, searching for it in GUI resource file, than searching for the resource identifier in the code of the editor. There you find the connection between the constant and the GUI name, since there exists some kind of data binding between the GUI and the properties store
  • There exists no IntelliSense that could help to find the existing properties.
  • The data values are converted when they are retrieved and not stored in the original format

One additional characteristic of the system is, that there exist properties which are the same for both directions (e.g. illumination of the rail track) and other ones which are different depending if you are driving forwards or backwards on the track (e.g. stops and names). So far the developer has to know which properties are valid for both directions and which ones depend on the direction on the track. The GetProperty funktion takes an additional argument which determines if the property for the forward or for the backward direction is retrieved.

In the process of rewriting the system for generation of 3D models for the rail tracks I need to access some of these properties. I decided this would be a good occasion to experiment with a new system for such properties. My main design goals were the following:

  • Design system in a way, that the compiler can check for invalid usage of properties and allow the IDE to offer IntelliSense
  • Available properties and the types of the properties should be represented in some way in the source code
  • Static differentation between properties that are the same in both directions and ones where different properties for both directions exist
  • Values should be stored in a typesafe way and not needed to be converted each time properties are accessed
  • Allow fast access and filtering of properties, which means the property lists should store the properties by value and not allocate space on the heap for each single property

First of all I decided to use structures to store the different types of properties. Since every property has at least a position (relative to the track it is associated with), I created a base class for all different kind of properties:

template <bool TBothDirections>
struct RailProperty
{
	static const bool BothDirections = TBothDirections;

	RailProperty() : RailProperty(0.0f * units::meter) { }
	explicit RailProperty(units::distance_m position) :
		position_(position)
	{
	}

	units::distance_m position_;
};

The template parameter TBothDirections is used to differentiate between properties that are valid for both directions and one where different properties for forward and backward exist.

Each type of property is a subclass of the RailProperty struct. In the following two examplary properties are shown:

struct PropLimit : public RailProperty<true>
{
	PropLimit(units::distance_m position, l3d::units::speed_kph limitNormal = units::speed_kph::from_value(100.0f));
	PropLimit(units::distance_m position, l3d::units::speed_kph limitNormal, l3d::units::speed_kph limitNeigetechnik);

	units::speed_kph limitNormal_;
	units::speed_kph limitNeigetechnik_;
};

struct PropUeberhoehung : public RailProperty<false>
{
	PropUeberhoehung(/* ctor parameters */);

	// Properties
};

So how can these properties now be accessed? The user of the interface accesses them through a RailDescription class, which stores information about one rail. Each type of property is stored in an own custom list class. The lists itself are organized in a map[1], where std::type_index is used as a key. The type_index class is new in C++11, can be constructed from std::type_info (which is returned by the typeid operator) and can be used in (hash) maps.
The RailDescription class contains a Properties() function which provides access to a list of properties of the specified type. Since the type of the property is given as a template parameter, the concrete type of the return value is determined at compile time and can be used by IDEs for IntelliSense.

class RailDescription
{
public:
	/* other stuff */

	template <class Prop>
	railprops::PositionedPropertyList<Prop>& Properties()
	{
		auto& l = propLists_[typeid(Prop)];
		if (l.get() == nullptr) {
			l = std::make_unique<railprops::PositionedPropertyList<Prop>>();
		}
		return static_cast<railprops::PositionedPropertyList<Prop>&>(*l);
	}

private:
	std::map<std::type_index, std::unique_ptr<railprops::PositionedPropertyListBase>> propLists_;
	/* other stuff */
};

So what about the PositionedPropertyList class?

template <class Prop>
class PositionedPropertyList : 
	public std::conditional<Prop::BothDirections, PositionedPropertyListWithDir<Prop>, PositionedPropertyListWithoutDir<Prop>>::type
{
};

This class has only one purpose: If the properties that are stored in the list are handled differently for the two directions, PositionedPropertyList is a subclass of PositionedPropertyListWithDir, otherwise of PositionedPropertyListWithoutDir

The PositionedPropertyListWithDir class is responsible to provide two lists itself: One for the forward and one for the backward direction:

template <class Prop>
class PositionedPropertyListWithDir : public PositionedPropertyListBase
{
public:
	PositionedPropertyListWithDir();

	// forward
	PositionedPropertyListWithoutDir<Prop>& Fwd() { return *forwards_; }
	// backwards
	PositionedPropertyListWithoutDir<Prop>& Bwd() { return *backwards_; }
private:
	std::unique_ptr<PositionedPropertyListWithoutDir<Prop>> forwards_;
	std::unique_ptr<PositionedPropertyListWithoutDir<Prop>> backwards_;
};

The class in which the properties are actually stored is the PositionedPropertyListWithoutDir class:

template <class Prop>
class PositionedPropertyListWithoutDir : public PositionedPropertyListBase
{
public:
	// Property with position_ <= position
	// Returns nullptr if there does not exist such property
	const Prop* At(units::distance_m position) const
	{
		auto it = std::upper_bound(cbegin(orderedProps_), cend(orderedProps_), position);
		if (it != cbegin(orderedProps_)) {
			return &(*(it - 1));
		}
		else {
			return nullptr;
		}
	}

	/* Implementation of functions omitted */
	Prop* At(units::distance_m position);
	Prop& Add(const Prop& v);
	Prop& Emplace(units::distance_m position);		
	template<class... Args>
	Prop& Emplace(units::distance_m position, Args&&... args);
	bool DeleteAt(units::distance_m position);
	
private:
	std::vector<Prop> orderedProps_;
};

In this class the properties are stored in a std::vector and a handful of methods to retrieve, add new and delete properties exist. For some use cases probably more advanced methods to retrieve a range of properties are needed, which are not yet implemented.

In the end, the user can access the properties in the following way:

RailDescription rd;

rd.Properties<PropLimit>().Fwd().Add(PropLimit(10.0f * l3d::units::meter, 100.0f * units::kilometer_per_hour));
rd.Properties<PropLimit>().Fwd().Emplace(50.6f * l3d::units::meter, 100.0f * units::kilometer_per_hour);
auto& p1 = rd.Properties<PropLimit>().Fwd().At(4.0f * l3d::units::meter)

rd.Properties<PropUeberhoehung>().Emplace(100.0f * units::meter, UeberhoehungType::FesterWert, 45.0f * units::degrees);
auto& a = rps.Properties<PropUeberhoehung>().At(100.0f * l3d::units::meter)->angle_;

Everything is type checked at compile time and the IDE can provide full IntelliSense. I always knew that C++ templates are a real nice technique to work with. However, I really had a lot of fun creating this system for storing properties. I still think that it offers a nice interface forusers of this part of the code and can be easily used even by people who do not know anything about the way it is implemented. The main reason for this is, that it is statically typed and therefore prevents a lot of careless mistakes.

So far I did not think a lot about serialization of this new property store. I have a few options in mind, but at the moment I do not need it and writing code that is not needed at the moment is… unnecessary 😉

[1] Accoring to a talk by Chandler Carruth both std::map and std::unordered_map are not really optimal data structures. Maybe I will exchange the usage of std::map with a better map sometime, but this is not really relevant for this post.

This entry was posted in Development and tagged , . Bookmark the permalink.

0 Responses to Loksim3D Developer Stories – Part 2 – C++ template magic

  1. LarryinduM says:
    Your comment is awaiting moderation. This is a preview, your comment will be visible after it has been approved.

    Thanks. Ample knowledge.

    keyword viagra viagra in the water chords
    generic viagra 100mg
    viagra generic drug – https://genericviagrantx.com

    Geraldfek
    DwayneTum
    Kevinnok

  2. LarryinduM says:
    Your comment is awaiting moderation. This is a preview, your comment will be visible after it has been approved.

    Very good postings, Thank you.

    discount viagra red viagra aanbieding
    generic viagra 100mg
    united states discount viagra – https://genericviagramsl.com

    Geraldfek
    DwayneTum
    Kevinnok

  3. LarryinduM says:
    Your comment is awaiting moderation. This is a preview, your comment will be visible after it has been approved.

    You revealed this wonderfully!

    taking viagra and alcohol men on viagra tubes
    viagra 100mg
    dont mix viagra wih steroids photo – https://genericviagrarcp.com

    Geraldfek
    DwayneTum
    Kevinnok

  4. LarryinduM says:
    Your comment is awaiting moderation. This is a preview, your comment will be visible after it has been approved.

    Seriously many of terrific data.

    mexico price viagra nogales pulmonary hypertension viagra
    viagra online
    viagra kopen – https://genericviagramsl.com

    Geraldfek
    DwayneTum
    Kevinnok

  5. LarryinduM says:
    Your comment is awaiting moderation. This is a preview, your comment will be visible after it has been approved.

    Thanks a lot, An abundance of forum posts!

    viagra and celis stories of viagra
    buy viagra
    old man and viagra – https://genericviagrantx.com

    Geraldfek
    DwayneTum
    Kevinnok

  6. LarryinduM says:
    Your comment is awaiting moderation. This is a preview, your comment will be visible after it has been approved.

    Thanks. I appreciate this.

    c-pill generic viagra viagra t shirt
    viagra 100mg
    viagra home recipe – https://genericviagrantx.com

    Geraldfek
    DwayneTum
    Kevinnok

  7. LarryinduM says:
    Your comment is awaiting moderation. This is a preview, your comment will be visible after it has been approved.

    Truly a good deal of terrific advice!

    sub for viagra viagra insomnia
    buy viagra online
    amature videos viagra sleep – https://genericviagramsl.com

    Geraldfek
    DwayneTum
    Kevinnok

  8. LarryinduM says:
    Your comment is awaiting moderation. This is a preview, your comment will be visible after it has been approved.

    Regards! A lot of info.

    sun viagra perscriptions marajuana and viagra
    generic viagra
    grapefruit juice and viagra – https://genericviagrantx.com

    Geraldfek
    DwayneTum
    Kevinnok

  9. LarryinduM says:
    Your comment is awaiting moderation. This is a preview, your comment will be visible after it has been approved.

    Wonderful forum posts. Cheers!

    viagra tastes different need a prescription for viagra
    viagra for women
    generic viagra buy sildenafil citrate – https://genericviagrantx.com

    Geraldfek
    DwayneTum
    Kevinnok

  10. LarryinduM says:
    Your comment is awaiting moderation. This is a preview, your comment will be visible after it has been approved.

    Fine postings. Cheers!

    viagra users reviews rapid viagra
    viagra pills
    buy viagra com – https://genericviagrarcp.com

    Geraldfek
    DwayneTum
    Kevinnok

  11. LarryinduM says:
    Your comment is awaiting moderation. This is a preview, your comment will be visible after it has been approved.
  12. LarryinduM says:
    Your comment is awaiting moderation. This is a preview, your comment will be visible after it has been approved.
  13. LarryinduM says:
    Your comment is awaiting moderation. This is a preview, your comment will be visible after it has been approved.

    You actually said this really well.

    viagra marketing campaign availability of viagra
    viagra generic
    civil suits against phizer viagra – https://genericviagrarcp.com

    Geraldfek
    DwayneTum
    Kevinnok

  14. LarryinduM says:
    Your comment is awaiting moderation. This is a preview, your comment will be visible after it has been approved.

    Good data. Appreciate it!

    jo wang viagra bali number of viagra prescriptions
    viagra generic
    viagra kills – https://genericviagramsl.com

    Geraldfek
    DwayneTum
    Kevinnok

  15. LarryinduM says:
    Your comment is awaiting moderation. This is a preview, your comment will be visible after it has been approved.

    You actually reported it wonderfully!

    acupunture fue las viagra charles agujas vigorex or viagra
    viagra pills
    generic brands of viagra online – https://genericviagrarcp.com

    Geraldfek
    DwayneTum
    Kevinnok

  16. LarryinduM says:
    Your comment is awaiting moderation. This is a preview, your comment will be visible after it has been approved.

    Nicely put, Thanks!

    generic viagra fast shipping get viagra perscription online
    viagra 100mg
    viagra funnies – https://genericviagrantx.com

    Geraldfek
    DwayneTum
    Kevinnok

  17. LarryinduM says:
    Your comment is awaiting moderation. This is a preview, your comment will be visible after it has been approved.

    Amazing info. Thanks a lot!

    speed of viagra herbal substitutes for viagra
    buy generic viagra
    do viagra tablets go bad – https://genericviagramsl.com

    Geraldfek
    DwayneTum
    Kevinnok

  18. LarryinduM says:
    Your comment is awaiting moderation. This is a preview, your comment will be visible after it has been approved.

    Thank you, Excellent information.

    secondary pulmonary hypertension viagra viagra vs extenze
    viagra generic
    viagra discounts senators – https://genericviagrarcp.com

    Geraldfek
    DwayneTum
    Kevinnok

  19. LarryinduM says:
    Your comment is awaiting moderation. This is a preview, your comment will be visible after it has been approved.

    Thanks, A lot of data!

    viagra replacements viagra and drinking
    viagra for women
    generic viagra without a percription – https://genericviagrarcp.com

    Geraldfek
    DwayneTum
    Kevinnok

  20. LarryinduM says:
    Your comment is awaiting moderation. This is a preview, your comment will be visible after it has been approved.

    Truly a lot of great material.

    viagra marching viagra medication online
    viagra generic
    bad side effects of viagra – https://genericviagrarcp.com

    Geraldfek
    DwayneTum
    Kevinnok

  21. LarryinduM says:
    Your comment is awaiting moderation. This is a preview, your comment will be visible after it has been approved.

    This is nicely put. !

    viagra in india by mail order lyrics viagra in the water
    generic viagra online
    is viagra more effective chewed – https://genericviagrantx.com

    Geraldfek
    DwayneTum
    Kevinnok

  22. LarryinduM says:
    Your comment is awaiting moderation. This is a preview, your comment will be visible after it has been approved.

    Kudos, Lots of stuff!

    viagra is half a viagra effective
    viagra without a doctor prescription
    viagra porn photos – https://genericviagrarcp.com

    Geraldfek
    DwayneTum
    Kevinnok

  23. LarryinduM says:
    Your comment is awaiting moderation. This is a preview, your comment will be visible after it has been approved.

    You suggested that terrifically.

    viagra founder viagra for blood pressure
    buy viagra
    viagra no prescription – https://genericviagrantx.com

    Geraldfek
    DwayneTum
    Kevinnok

  24. LarryinduM says:
    Your comment is awaiting moderation. This is a preview, your comment will be visible after it has been approved.
  25. LarryinduM says:
    Your comment is awaiting moderation. This is a preview, your comment will be visible after it has been approved.

    You reported that effectively.

    viagra cialis on line erectile dysfunction 3 cheap generic substitute viagra
    viagra 100mg
    penis sensitivity description viagra – https://genericviagramsl.com

    Geraldfek
    DwayneTum
    Kevinnok

  26. LarryinduM says:
    Your comment is awaiting moderation. This is a preview, your comment will be visible after it has been approved.

    Nicely put, Thank you.

    nokia n72 buy viagra online viagras effects on woman
    generic viagra online
    viagra securemed – https://genericviagrarcp.com

    Geraldfek
    DwayneTum
    Kevinnok

  27. LarryinduM says:
    Your comment is awaiting moderation. This is a preview, your comment will be visible after it has been approved.

    Thanks, Ample tips.

    viagra in bangkok viagra cialis levitra canada
    generic viagra 100mg
    cialis viagra – https://genericviagramsl.com

    Geraldfek
    DwayneTum
    Kevinnok

  28. LarryinduM says:
    Your comment is awaiting moderation. This is a preview, your comment will be visible after it has been approved.

    Fine info. With thanks.

    what drugs interact with viagra generic viagra caverta veega generic viagra
    buy generic viagra
    pain propecia relief viagra url links – https://genericviagramsl.com

    Geraldfek
    DwayneTum
    Kevinnok

  29. LarryinduM says:
    Your comment is awaiting moderation. This is a preview, your comment will be visible after it has been approved.

    Very well expressed genuinely! !

    cialis levitra link viagra blogspot com home remedies for viagra
    generic viagra 100mg
    best results for viagra – https://genericviagrarcp.com

    Geraldfek
    DwayneTum
    Kevinnok

  30. LarryinduM says:
    Your comment is awaiting moderation. This is a preview, your comment will be visible after it has been approved.

    This is nicely put! !

    cheap viagra cialis quail eggs better han viagra
    buy viagra
    viagra for fun – https://genericviagrarcp.com

    Geraldfek
    DwayneTum
    Kevinnok

  31. LarryinduM says:
    Your comment is awaiting moderation. This is a preview, your comment will be visible after it has been approved.

    Wonderful posts, Kudos!

    regalis vs viagra buy phentermine viagra online xanax
    cheap viagra
    viva viagra ring tone – https://genericviagramsl.com

    Geraldfek
    DwayneTum
    Kevinnok

  32. LarryinduM says:
    Your comment is awaiting moderation. This is a preview, your comment will be visible after it has been approved.

    Nicely put. Regards.

    viagra sex domination viagra cost private pay
    generic viagra 100mg
    find viagra free sites – https://genericviagrarcp.com

    Geraldfek
    DwayneTum
    Kevinnok

  33. LarryinduM says:
    Your comment is awaiting moderation. This is a preview, your comment will be visible after it has been approved.

    With thanks, I like this!

    maid training story viagra canadian pharmacy viagra brand
    viagra generic
    causes of viagra being ineffective – https://genericviagramsl.com

    Geraldfek
    DwayneTum
    Kevinnok

  34. LarryinduM says:
    Your comment is awaiting moderation. This is a preview, your comment will be visible after it has been approved.

    You actually expressed this really well!

    canada viagra buy viagra and sex
    generic viagra online
    counterfiet viagra from china – https://genericviagramsl.com

    Geraldfek
    DwayneTum
    Kevinnok

  35. LarryinduM says:
    Your comment is awaiting moderation. This is a preview, your comment will be visible after it has been approved.

    Whoa many of useful advice!

    can you buy viagra in mexico cheap drugs viagra cialas
    viagra without a doctor prescription
    kamagra same as viagra – https://genericviagramsl.com

    Geraldfek
    DwayneTum
    Kevinnok

  36. LarryinduM says:
    Your comment is awaiting moderation. This is a preview, your comment will be visible after it has been approved.

    This is nicely said! !

    ed treatment without viagra type drugs orexis as good as viagra
    buy viagra online
    generic viagra sales – https://genericviagrantx.com

    Geraldfek
    DwayneTum
    Kevinnok

  37. LarryinduM says:
    Your comment is awaiting moderation. This is a preview, your comment will be visible after it has been approved.

    You stated this terrifically.

    viagra research article is there a natural viagra
    buy generic viagra
    viagra alternative zenegra – https://genericviagrantx.com

    Geraldfek
    DwayneTum
    Kevinnok

  38. LarryinduM says:
    Your comment is awaiting moderation. This is a preview, your comment will be visible after it has been approved.

    Whoa a good deal of awesome information.

    generic viagra on line 3.43 n online order viagra
    buy generic viagra
    cheapest viagra in the usa – https://genericviagrantx.com

    Geraldfek
    DwayneTum
    Kevinnok

  39. LarryinduM says:
    Your comment is awaiting moderation. This is a preview, your comment will be visible after it has been approved.

    Cheers! Loads of advice!

    viagra side effects in women can viagra cause peyronie s disease
    buy viagra
    chalis vs viagra – https://genericviagrantx.com

    Geraldfek
    DwayneTum
    Kevinnok

  40. LarryinduM says:
    Your comment is awaiting moderation. This is a preview, your comment will be visible after it has been approved.

    Whoa a lot of terrific facts.

    viagra canida will viagra make you horney
    viagra without a doctors prescription
    generic viagra soft tabs – https://genericviagrarcp.com

    Geraldfek
    DwayneTum
    Kevinnok

  41. LarryinduM says:
    Your comment is awaiting moderation. This is a preview, your comment will be visible after it has been approved.

    Beneficial material. Kudos.

    viagra operation viagra online stores
    buy viagra online
    kamagra generic viagra soft 100 – https://genericviagrantx.com

    Geraldfek
    DwayneTum
    Kevinnok

  42. LarryinduM says:
    Your comment is awaiting moderation. This is a preview, your comment will be visible after it has been approved.
  43. LarryinduM says:
    Your comment is awaiting moderation. This is a preview, your comment will be visible after it has been approved.

    Seriously quite a lot of useful data!

    when do you need viagra edinburgh uk viagra href pages computer
    viagra 100mg
    brand name viagra – https://genericviagrantx.com

    Geraldfek
    DwayneTum
    Kevinnok

  44. LarryinduM says:
    Your comment is awaiting moderation. This is a preview, your comment will be visible after it has been approved.

    You suggested that effectively.

    if viagra doesnt work what next cocaine counteract impotence with viagra
    viagra for sale uk
    find sites computer shop viagra free – https://genericviagramsl.com

    Geraldfek
    DwayneTum
    Kevinnok

  45. LarryinduM says:
    Your comment is awaiting moderation. This is a preview, your comment will be visible after it has been approved.

    You’ve made your point extremely effectively!!

    can someone with afib take viagra get viagra online in canada
    viagra 100mg
    viagra cialis generica – https://genericviagramsl.com

    Geraldfek
    DwayneTum
    Kevinnok

  46. LarryinduM says:
    Your comment is awaiting moderation. This is a preview, your comment will be visible after it has been approved.

    Thanks, A good amount of knowledge!

    keywords viagra viagra marketing effects
    buy viagra online
    c-pill cheap viagra – https://genericviagramsl.com

    Geraldfek
    DwayneTum
    Kevinnok

  47. LarryinduM says:
    Your comment is awaiting moderation. This is a preview, your comment will be visible after it has been approved.

    With thanks, Ample data.

    viagra mp3 viagra girl advertisment
    cheap viagra
    buying viagra in the caribbean – https://genericviagrarcp.com

    Geraldfek
    DwayneTum
    Kevinnok

  48. LarryinduM says:
    Your comment is awaiting moderation. This is a preview, your comment will be visible after it has been approved.

    Many thanks! Useful information.

    2003 apcalis levitra market sales viagra dissolve crush viagra
    generic viagra 100mg
    cheap sale viagra – https://genericviagrantx.com

    Geraldfek
    DwayneTum
    Kevinnok

  49. LarryinduM says:
    Your comment is awaiting moderation. This is a preview, your comment will be visible after it has been approved.

    Kudos. Useful stuff.

    healthy men viagra low cost viagra fast
    buy viagra online
    expired viagra risk – https://genericviagrantx.com

    Geraldfek
    DwayneTum
    Kevinnok

  50. LarryinduM says:
    Your comment is awaiting moderation. This is a preview, your comment will be visible after it has been approved.

    You actually stated this adequately.

    i doser viagra how old to take viagra
    cheap viagra
    viagra oil – https://genericviagramsl.com

    Geraldfek
    DwayneTum
    Kevinnok

  51. LarryinduM says:
    Your comment is awaiting moderation. This is a preview, your comment will be visible after it has been approved.

    Kudos. Lots of material!

    mariage viagra usa nhs england viagra
    viagra generic
    viagra herbal substitute – https://genericviagrantx.com

    Geraldfek
    DwayneTum
    Kevinnok

  52. LarryinduM says:
    Your comment is awaiting moderation. This is a preview, your comment will be visible after it has been approved.

    You explained this exceptionally well!

    viagra superforce canada viagra price walmart
    viagra for women
    can viagra affect the prostate gland – https://genericviagramsl.com

    Geraldfek
    DwayneTum
    Kevinnok

Leave a Reply

Your email address will not be published. Required fields are marked *