Saturday, February 21, 2015

Horsepower!!

My new Dell C6100 has arrived.

This is a 4 blade blade-server type setup. It's got 4 blades, which operate as completely independent computers with some shared hardware, like the harddrive back-plain, shared power supplies, and cooling infrastructure.

Each blade has 6 2.5 inch harddrive bays, for a total of 24.
Each blade has 2 Intel Xeon processors. Each processor has 6 full cores, supporting 12 simultaneous hyper-threads, for a total of 24 cores per blade.
Each blade supports a maximum of 96 gigs of ram, with this particular server populated with 48 GB of ram per blade via 6x 8GB chips.
Each blade supports 1 small form-factor PCI expansion card. Not sure what I'll be adding.

Front view.
 Top view

 Side view

 Back
Interestingly, each of the four blades can be individually ejected, even while the others are powered on and in use. Same with the power supplies, allowing for continuity of service

First view of the inside.
 Popped out one of the power supplies. Upside down view of the label.
 The connector supplies power to the motherboard.
 Power cable goes here! They provide a nice little handle that you can use to pop it out.
 Each blade can be pulled out individually, and here's how it looks.
 Two x two blades
 Here's the connectors for the power supplies.
Power supplies just hanging out.
Motherboard connection to the shared power bus.
Cleaned up the cable management a bit after I took the other pictures.



Sunday, February 1, 2015

Pointer conversion between C++ template instantiations

A follow up to my prior entry : http://cogito.jonesmz.com/2015/01/type-conversion-between-c-template.html

That entry detailed template meta-programming techniques to allow for two otherwise not related template classes to be converted from one to another. Sadly, that technique doesn't allow for the C++ type system to convert from, say, Foo<T>* to Foo<U>*. Despite having the appropriate conversion functions to construct new instances of Foo<T> out of Foo<U>, this doesn't give us the ability to treat an existing pointer to Foo<T> as a pointer to Foo<U>, the two classes might have completely different implementations, different v-tables, different memory layouts, and in general be incompatible. Thus, trying to convert a pointer to Foo<T> to a pointer to Foo<U> is impossible, as the C++ type system simply isn't designed to make that a possibility, no matter how many conversion functions you try to apply.

But there is one trick that can help in some situations, by having a template class inherit from a different instantiation of itself!

A quick example, which uses some template metaprogramming techniques.
template<typename T>
class Foo : public boost::conditional<  boost::is_const<T>::value
                                                            , boost::mpl::empty_base
                                                            , Foo<const T>    >::type
{
}
boost::mpl::empty_base is simply a POD struct that contains nothing, making inheriting from it a non-issue.

Any instantiation of Foo, Foo<T> where T is non const will be legal, and the resulting class will contain all of the members of both instantiations (with the appropriate inheritance rules), just as if the public foo<const T> were instead bar<const T>.

Any instantiation of Foo, Foo<T> where T is const will be legal, but will inherit from boost::mpl::empty_base, which contains no data or member functions, and will not inherit from any other instantation of Foo.

This technique provides us with a mechanism to allow in-place conversion of pointers between the two template instantiation.

In other words

Foo<T> * bar = new Foo<T>();
Foo<const T> * baz = bar;
Is fully legal, because any Foo<T> IS-A Foo<const T> by virtue of inheritance!

Of course, this doesn't then permit
Foo<const T> * bar = new Foo<T>();
Foo<T> * baz = bar; // WRONG
Without a cast, just like we normally need when going from a base-class to a derived-class.


If you're willing to introduce a few specializations, we can get some much more interesting behavior, such as the non-const version delegating to the const-version's methods if and only if we have both.

template<typename T, typename = void>
class Foo
{
    bar   function1(T) = 0;
    void function2(baz) = 0;
}
template<typename T, typename boost::enable_if<  boost::is_const<T>::value >::type >
class Foo
{
    bar   function1(T) = 0;
    T function2(baz) = 0;
}
template<typename T, typename boost::disable_if<  boost::is_const<T>::value >::type >
class Foo : public Foo<const T>
{
    bar   function1(T)
    { return Foo<const T>::function1(T); }
    T function2(baz)
    { return Foo<const T>::function2(baz); }
}
With that pattern, pointer conversion from non-const->const will work properly, and classes that use the non-const version of functions will delegate to the const version of functions