lunes, 13 de mayo de 2013

C++ 11's new style, explained by Bjarne Stroustrup

In a series of very interesting presentations in Microsoft's GoingNative2012 event, C++'s main creator, Bjarne Stroustrup himself, talked about the programming style introduced by the brand new C++11 standard.

The main focus of Bjarne's presentation was not the new language features, but how to use them correctly; that's what he calls "style". Up next, a summary of the key points raised:

  • Type-rich interfaces: Programmer-defined suffixes can now be used to indicate measuring units (see the new constexpr keyword).
  • Use RAII to handle resources: memory, files, sockets, hardware, operating system resources (threads, mutexes, semaphores, etc).
  • Avoid raw pointer usage, specially in public interfaces (restrict those usages to single method implementation scope). Use smart pointers classes such as unique_ptr and shared_ptr. Don't use the latter if the resource needs to be shared. And before considering pointers, consider references, or even better, create objetos on stack. All this discussion pertains to using pointers to express possession of a resource. If we just want to point to an object which does not belong to us and we can't use a reference, a pointer is acceptable.
  • Avoid native arrays; use STL containers. If passing a native array to a third-party API is necessary, an std::vector can be used, since it is guaranteed by the standard to use contiguous memory, just like a native array does. The API function should then be passed &v[0], where v is an std::vector.
  • When managing large objects (for instance, a Matrix class which we use to represent 10000 x 10000 matrices), and we want to write a method which returns an instance of that class (say, an operator+), we are forced to create a local instance and return a copy. That's a lot of overhead; a new, essential feature of C++11 is "move semantics". Instead of copying, we "move". In the previous example, we return a Matrix by value and implement a "move constructor", which defines how the "move" operation should be performed. Details on this will be left to future posts. Suffice it to say that all STL containers implement this, with the exception of std::array. This implies a significant performance boost just by compiling existing STL-using code with a C++11 compiler.
  • Use whenever possible.
  • Low level code isn't always more efficient. (for instance: C's sort function is orders of mangnitude slower than C++'s qsort). Always measure (profile) when in doubt and avoid complex premature optimizations. Low level usually means more code, which increases the chance of bugs and manteinance cost.
  • C++ 11 offers new classes for handling concurrency: std::thread and std::mutex, among others. Even better: std::async lets the runtime decide whether to use a separate thread or not, letting the programmer forget about many complexities of concurrence handling involved when handling theads manually.
  • También se agrega soporte para expresiones lambda.

Finally, here's a chart that lists which C++ 11 features are implemented by which compiler (MSVC = Visual Studio)

C++ 11 y su nuevo estilo, explicado por Bjarne Stroustrup

En una serie de charlas muy interesantes del evento GoingNative2012 organizado por Microsoft, el mísmisimo creador de C++, Bjarne Stroustrup, dio una charla sobre el nuevo estilo de programación introducido por el nuevo estándar C++ 11.

El tema de la charla no son las nuevas funcionalidades del lenguaje, sino cómo usarlas correctamente; eso es lo que Bjarne denomina "estilo". A continuación, un resumen de los puntos esenciales:

  • Type-rich interfaces: Se puede usar sufijos para indicar unidades, por ejemplo (ver la nueva keyword constexpr).
  • Usar RAII para recursos: memoria, archivos, sockets, hardware, recursos del sistema operativo (threads, mutexes, semáforos, etc).
  • Evitar el uso de punteros, especialmente en interfaces (mantener esos usos acotados a implementaciones de funciones). Usar smart pointers como unique_ptr y shared_ptr. No usar este último si no se está compartiendo el recurso. Y antes de considerar usar punteros, considerar usar referencias, o aún mejor, crear los objetos en stack. Todo esto cuando hablamos de usar punteros para expresar la pertenencia de un recurso. Si sólo queremos apuntar a un objeto que no es nuestro y no podemos usar una referencia, usar un puntero es aceptable.
  • Evitar arrays nativos; usar contenedores STL. Si es necesario pasar un array nativo a una API de terceros, por ejemplo, se puede usar un std::vector, que garantiza que toda la memoria sea contigua, igual que en un array nativo. A la función de la API se le pasa &v[0], donde v es el std::vector.
  • Cuando tenemos objetos grandes (por ejemplo, una clase Matrix que usamos para matrices de 10000 x 10000), y queremos hacer una función que devuelva una instancia de esa clase (un operator+, por ejemplo), tenemos el problema de que creamos una matriz local y devolvemos una copia. Es mucho overhead; una nueva funcionalidad clave de C++ 11 son las "move semantics". En vez de copiar, "muevo". En el ejemplo dado, devolvemos una Matrix por valor e implementamos un "move constructor", que define cómo se hace el "move". Más detalles sobre esto en un post futuro. Baste con aclarar que todos los contenedores de la STL implementan esto (excepto std::array), con lo cual la performance sube sólo por compilar para C++11 si ya usábamos contenedores STL.
  • Usar siempre que sea posible.
  • El código de bajo nivel no siempre es más eficiente (por ej: el sort de C es más lento que el qsort de C++). Siempre medir ante la duda y evitar micro-optimizaciones prematuras. Bajo nivel implica escribir más código, lo cual implica mayor posibilidad de bugs y mayor costo de mantenimiento.
  • C++ 11 ofrece clases para manejo de concurrencia: std::thread y std::mutex, entre ellas. Incluso mejor, std::async permite decidir al runtime si usar otro thread o no, dejándole toda la complejidad del manejo de la concurrencia.
  • También se agrega soporte para expresiones lambda.

Por último, acá hay un cuadro con qué funcionalidades de C++ 11 implementa cada compilador (MSVC = Visual Studio)

miércoles, 24 de abril de 2013

Visual Studio 2010 SP1 and C++/CLI strong naming bug

This particular Visual Studio version has a bug which breaks strong naming signing for C++/CLI assemblies. Said bug is documented and has a workaround which requires editing a .Targets file. Details here. In case the link dies, I'll copy the steps below:
  1. Go to %ProgramFiles(x86)%\MSBuild\Microsoft.Cpp\v4.0\Platforms\Win32
  2. Open Microsoft.Cpp.Win32.targets with a text editor (this might require administrator rights)
  3. Search for <Target Name="LinkEmbedManifest"
  4. Inside that tag, in the DelaySign attribute value, change % to $, and Link.DelaySign to LinkDelaySign (delete the period)
  5. Do the same for the KeyFile attribute (don't forget to change Link.KeyFile to LinkKeyFile)

Visual Studio 2010 SP1 y strong naming para C++/CLI

Este Visual tiene un bug que rompe la firma de assemblies C++/CLI con strong naming. Dicho bug está documentado y tiene una solución que requiere tocar un archivo .Targets del Visual Studio. Los detalles aquí. Por si el link se muere, copio los pasos a seguir:
  1. Ir a %ProgramFiles(x86)%\MSBuild\Microsoft.Cpp\v4.0\Platforms\Win32
  2. Abrir Microsoft.Cpp.Win32.targets con un editor de texto (esto puede requerir derechos de administrador)
  3. Buscar el texto <Target Name="LinkEmbedManifest"
  4. Dentro de ese tag, en el valor de la property DelaySign, cambiar % por $, y Link.DelaySign por LinkDelaySign (borrar el punto)
  5. Lo mismo para la property KeyFile (no olvidar borrar el punto para que Link.KeyFile pase a ser LinkKeyFile)

jueves, 29 de noviembre de 2012

The Horror: Uninstalling SQL Server 2008 R2 and his friends

It's common knowledge that even though Microsoft claims it's possible to have multiple versions of SQL Server Express side by side, that's generally considered a bad idea. So I set out to remove every trace of SQL Server in order to later install the latest R2 version.

After many visits to Control Panel->Add or Remove Programs, in which I removed anything which had SQL Server in its name, four (4) creatures were left standing:

  • Microsoft SQL Server 2008
  • Microsoft SQL Server 2008 Setup Files
  • Microsoft SQL Server 2008 R2
  • Microsoft SQL Server 2008 R2 Setup Files

If I tried to remove the setup files, I was told that I had to remove 2008 or 2008 R2 before. If I tried removing one of those, after running the whooooooole process without a hitch, the entry was still there. On a closer examination, R2 was always saying it was going to delete Microsoft Sync Framework, but it didn't do so (silently). So I tried nuking the sync framework myself, but then I was warned that many programs needed it, including Visual Studio 2010. Since I use that every day, I ran away in terror.

At this point, I realized I should have followed some guide when nuking the various SQL components and helper. But it was too late, so I decided to destroy all traces of SQL Server with a vengeance. This implied deleting the whole C:\Program Files\Microsoft SQL Server directory, and deleting every registry key associated, as explained in the answer to this question on Social MSDN.

But even after all that, there were still three entries on Add or Remove Programs (2008 Common Files, 2008 and some other I don't remember). After another long and fruitless look at the registry, I stumbled upon a Microsoft Fixit that saved my life..

After running it thrice, once per zombie entry, every trace of SQL had seemingly vanished. Then, I ran the SQL Server 2008 R2 installer, and I got several errors. But then I just ran the uninstaller from Add or Remove Programs and tried again, as suggested in this post. And I finally succeeded.

Horror: Desinstalando SQL Server Express 2008 y sus amigos

Es sabido que esto siempre trae problemas. En mi caso, me vi obligado a meterme en este infierno porque no podía hacer restore de una base de datos porque el backp había sido hecho con una versión más nueva de SQL Server 2008 Express R2 SP1 (10.50.sarasa, yo tenía 10.0.sarasa).

Es sabido también que aunque Microsoft dice que es posible tener varias versiones de SQL Server Express side by side, eso está conceptuado como una mala idea. Así que me dispuse a eliminar todo rastro de todo SQL Server para luego instalar la última versión del 2008 R2.

Luego de varias visitas a Panel de Control->Agregar o quitar Programas, durante las cuales fui eliminando todo lo que tuviera SQL Server en su nombre, quedaron cuatro (4) criaturas en pie:

  • Microsoft SQL Server 2008
  • Microsoft SQL Server 2008 Setup Files
  • Microsoft SQL Server 2008 R2
  • Microsoft SQL Server 2008 R2 Setup Files

Si intentaba eliminar los setup files, me decía que debía eliminar 2008 o 2008 R2 primero. Si intentaba eliminar uno de esos, corría tooodo el proceso a la perfección pero la entrada seguía ahí. Mirando más de cerca a R2, cada vez que corría decía que iba a eliminar el Microsoft Sync Framework pero no lo hacía. Cuando fui a borrar ese bicho a mano, Windows me avisó que varios programas lo necesitaban, incluyendo Visual Studio 2010. A ése último lo uso todos los días, así que huí despavorido.

Fue en este punto donde me percaté de que debería haber seguido alguna guía al eliminar los otros componentes. Llegado este punto, me decidí por borrar todo violentamente, lo cual implicó borrar el directorio C:\Program Files\Microsoft SQL Server y toda clave del registro asociada a SQL Server, como explican en la respuesta de este thread de Social MSDN.

Pero incluso luego de hacer todo eso, seguía habiendo tres entradas en Agregar o Quitar Programas (2008 Common Files, 2008 y otra que no recuerdo). Luego de una búsqueda minuciosa e inútil en el registry, me topé con un Fixit de Microsoft que me salvó la vida.

Luego de correrlo tres veces, realmente todo rastro de SQL había desaparecido. Luego de eso, corrí el instalador y me tiró errores, pero como recomiendan en este post, corrí el desinstalador de 2008 R2 desde Agregar o quitar Programas, corrí el instalador de nuevo y finalmente tuve éxito.

miércoles, 27 de junio de 2012

Parse enums and convert them to other types elegantly

Quite often, we need to to read a value from some source (file, socket, database) and convert it to an enum. In order to define the conversion in a single place, in C++, we usually define a function like this one:


//enum MyEnum{ VALUE_A, VALUE_B, VALUE_C };

MyEnum ParseMyEnum( const std::string& sMyEnum ){
    //Conversion
}

But where do we define this function? Our first idea is to make it a private method of the class which uses the enum, but this is not possible if the enum is used by more than one class. In those cases, we have no choice but to define the function as a free function inside a namespace.

C#'s enums can have methods and extension methods, which would be the most natural and object oriented solution. Nevertheless, since we're talking C++ now, we can use templates to solve this problem in a generic way, for every enum, and use template specialization to define the specific mapping for each enum. This can be done by defining the following template class:

#pragma once

#include <map>
#include <string>

template <typename EnumType, typename TypeToParse=std::string>
class EnumParser{
 std::map<TypeToParse, EnumType> m_EnumMap;
public:
 EnumParser(){}

 EnumType ParseSomeEnum( const TypeToParse &value ){
  std::map<TypeToParse, EnumType>::const_iterator iValue = m_EnumMap.find(value);
  if ( iValue  == m_EnumMap.end() )
    throw std::runtime_error("");
  return iValue->second;
 }
};

When we run into an enum we wish to parse, we specialize EnumParser's constructor and fill m_EnumMap with the desired mapping:

EnumParser<CSerialPort::StopBits, int>::EnumParser(){
        //Windows convention (see DCB structure)
 m_EnumMap[0] = CSerialPort::STOP_BITS_ONE;
 m_EnumMap[1] = CSerialPort::STOP_BITS_ONEPOINTFIVE;
 m_EnumMap[2] = CSerialPort::STOP_BITS_TWO;
}

EnumParser<GeneratorLib::EFilter>::EnumParser(){
 m_EnumMap["Molybdenum"] = GeneratorLib::FLT_MOL;
 m_EnumMap["Rhodium_25"] = GeneratorLib::FLT_ROD_25;
 m_EnumMap["Rhodium_50"] = GeneratorLib::FLT_ROD_50;
}

Finally, when we wish to perform the parsing, we instantiate EnumParser and invoke ParseSomeEnum:


EnumParser<CSerialPort::StopBits,int> enumParser;
 CSerialPort::SConfig sConfig( iBaudRate, enumParser.ParseSomeEnum(iStopBits), iParity, iDataBits );

If we wanted to implement the reverse mapping, that is, convert the enum to a certain type (usually std::string), we can add a second std::map with the inverse mapping to EnumParse (or define it in a subclass of EnumParser). That would make sense if the mapping were asymmetrical; if it's symmetrical, using just a boost::bimap (like a std::map but values can be used as keys to get the keys) would be ideal.