Otros sitios...

Búsqueda

Antispam

SnapShoot: Hilos en C++ a la boost

November 12th, 2008 by Jorge Machin

Boost es una excelente librería con todo lo que un buen programador de C++ pudiera necesitar. Además está desarrollada para hacer la programación sencilla, elegante y rápida.

#include <iostream>

#include <boost/bind.hpp>
#include <boost/thread/thread.hpp>

class Hilo {

   public:

      Hilo() : keepgoing( true ), thread( boost::bind( &Hilo::do_work, this ) ) { };

      ~Hilo() {

         keepgoing = false;

         // Necesitamos esperar a que el hilo se acabe :)

         thread.join();

      }

   private:

      bool keepgoing;

      boost::thread thread;

      void do_work() {

          // Aquí es donde se lleva a cabo toda la acción.

          while( keepgoing ) {

             std::cout <<"Hilo" << std::endl;
             sleep(1);

          }

       }

};

int main( void ) {

   Hilo *hilo = new Hilo();

   sleep(20);

   delete hilo;

   return EXIT_SUCCESS;

}

El programa lo podemos compilar con:

g++ -O2 -o main main.cpp -lboost_thread-mt

Notas:

- Como se puede ver esta aproximación es más parecida a como le hace C# que Java.

- El hilo comienza al crearse el objeto.

- No hay manera de controlar manualmente el tamaño del stack

- Si no hay recursos suficientes se lanza una excepción y el objeto no se crea.

Posteado en C/C++, Snapshots | No hay comentarios »

Ciudad Konec-t

November 11th, 2008 by Jorge Machin

Ciudad Konec-t fué uno de los proyectos en el cual participé por mi paso por Interalia (8 años).

Así era en un principio
Así era en un principioFue creciendoUno de los cuartos populares

Posteado en Adobe Flash, Arqueología Machinesca, C/C++, Personal, Programación, Videojuegos | No hay comentarios »

Snapshot: Hilos en C++ (Windows)

September 26th, 2008 by Jorge Machin

Una clase "quick and dirty" para crear hilos en cajas windows.

Encabezado:

#pragma once

class CThread {

   public:

      // Constructor por defecto:

      CThread(void);

      // Destructor virtual
   
      virtual ~CThread(void);

      // Esta función inicia el hilo:

      bool start();

      // Esta función se debe sobrecargar con lo que tiene que hacer el hilo:

      virtual void run() = 0;

      // Esta función espera a que el hilo se detenga. Se debe llamar en el destructor de la clase derivada.

      void join();

   private:

      unsigned long id;

      void *threadHandle;

      static DWORD WINAPI entryPoint( void *pthis );

};

Archivo cpp:

#include "StdAfx.h"
#include "thread.h"

CThread::CThread(void) : threadHandle( NULL ) {

   MessageBox( NULL, "CThread::CThread", "Aviso", MB_OK );

}

DWORD WINAPI CThread::entryPoint( void *pthis ) {

   CThread *pt = ( CThread * ) pthis;
   pt -> run();
   return 0;

}

bool CThread::start() {

   threadHandle = CreateThread( NULL, 0, ( LPTHREAD_START_ROUTINE ) entryPoint, this, 0, &id );
   return true;

}

void CThread::join() {

   if ( threadHandle != NULL )

      WaitForSingleObject( threadHandle, INFINITE );

}

CThread::~CThread(void) {

   MessageBox( NULL, "CThread::~CThread", "Aviso", MB_OK );

   if ( threadHandle != NULL )   

      CloseHandle( threadHandle );

}

Posteado en C/C++, Programación, Snapshots, Windows | No hay comentarios »

Snapshot: Obteniendo archivos HTTP en C++

September 25th, 2008 by Jorge Machin

Ya es común para un programador, no solamente el tener que leer archivos del disco duro local, sino también leerlos desde un sitio web; Ya sea un web service, una imagen o un XML. Afortunadamente la libreria libcurl resuelve el problema con muy pocas líneas de código.

En este post, pongo un pequeño ejemplo de como se usaría en C++ para pequeños programas de apoyo:

#include <string>
#include <iostream>

#include "curl/curl.h" 

class URLFile {

   public:

      std::string get( const std::string &URL ) {

         // Inicialización:

         CURL *curl = curl_easy_init();
         curl_easy_setopt( curl, CURLOPT_URL, URL.c_str() );
         curl_easy_setopt( curl, CURLOPT_WRITEFUNCTION, &URLImage::write_data);
         curl_easy_setopt( curl, CURLOPT_WRITEDATA, &data);

         // Obtén el archivo:
                       
         CURLcode result = curl_easy_perform(curl)

         // Al final hay que limpiar todo:

         curl_easy_cleanup(curl);

         if (result != CURLE_OK)  {

            return "";

         }

         return data;

      }

   private:
 
      // Variable que usamos para guardar el contenido del archivo:

      std::string data;

      // Callback que utiliza curl:

      static size_t write_data( char *buffer, size_t size, size_t nmemb, void *userp ) {

         int len = size * nmemb;
 
         if ( buffer != NULL ) 

            ( ( std::string * )  userp )->append( buffer, len )

         return len;

      }
 
};

int main() {

   URLFile file;

   std::string test = file.get( "www.machin.com.mx" );

   std::cout <<"Test:" <<std::endl <<test <<std::endl;

   return 0;

}

Posteado en C/C++, Programación, Snapshots | No hay comentarios »

Functores en C++

May 26th, 2008 by Jorge Machin

Los functores o functors en C++ son una construcción del lenguaje que nos permite usar objetos como si fueran funciones. Esto es muy útil cuando se esta programando callbacks, interpretes, compiladores y metaprogración.

Una forma de usarlos es encapsulandolos en una clase:

class Function1 {

  public:

    // Default constructor

    Function1() { std::cout <<"Function1 constructor" <<std::endl; }

    // Virtual destructor

    ~Function1() { std::cout <<"Function1 destructor" <<std::endl; }

    //  Function call:

    void operator() (int a) const {
        std::cout <<"operator(): " <<a <<std::endl;
    }
};

La cual podemos usar así:

Function1 function1;
function1();

El lector se puede imaginar que una de las propiedades de los functores es que al agregarle miembros a la clase, estos pueden mantener su estado entre cada una de las llamadas. Sin embargo, es muy probable que la utilidad de los functores se pueda apreciar más con un ejemplo práctico:

Manejador de eventos usando functores

Un manejador de eventos es un subprograma que al recibir un evento, lo comunica a todas los subprogramas que estén subscritos a él. El código fuente es el siguiente:

#include <iostream>
#include <list>
#include <string>

// Una clase base para hacer clases con callbacks:

class callbackbase {

   public:

      virtual void operator()() const { std::cout <<"callbackbase()" <<std::endl; };
      virtual ~callbackbase() { };

};

// El functor que implementa la funcionalidad del callback:

template <class T> class callback : public callbackbase {

   public:

      typedef void (T::*Func)();

      callback( T& t, Func func ) : object(&t), f(func) { }

      void operator()() const { (object->*f)(); }

   private:

      T* object;

      Func f;
};

template<typename T> callback<T> *make_callback( T& t, void (T::*f) () ) {

  return new callback<T>( t, f );

}

// Los tipos de eventos que soportamos:

enum notifications {

   NOTIFICATION_ONE,
   NOTIFICATION_TWO,
   NOTIFICATION_MAX

};

// Nuestro Manejador de Eventos:

class EventManager {

   public:

      void registerHandler( callbackbase *function, enum notifications notification) {

         functions[notification].push_back( function );

      }

      void notifyHandlers( enum notifications notification ) {

         for ( std::list<callbackbase*>::iterator iter = functions[notification].begin(); iter != functions[notification].end(); iter++ ) {

            (*(*iter))();

         }

      }

   private:

      std::list<callbackbase *> functions[NOTIFICATION_MAX];

};

// Clases de ejemplo

class Class1 {

   public:

      Class1( const std::string &instance ) : instance( instance ) { };

      void function1() { std::cout <<"class1::function1: " <<instance <<std::endl; };

      void function2() { std::cout <<"class1::function2: " <<instance <<std::endl; };

   private:

      std::string instance;

};

class Class2 {

   public:

      void function1() { std::cout <<"class2::function1" <<std::endl; };

};

class Class3 : public callbackbase {

   public:

     virtual void operator()() const { std::cout <<"class3::function1" <<std::endl; };

};

//

int main() {

   // Clases que van a recibir los eventos:

   Class1 class1a("1a");
   Class1 class1b("1b");
   Class2 class2;
   Class3 class3;

   // Creamos nuestro manejador de eventos:

   EventManager eventManager;

   // Creamos al vuelo callbacks a funciones de clases que no heredan de callbackbase:

   eventManager.registerHandler( make_callback( class1a, &Class1::function1 ), NOTIFICATION_ONE );

   eventManager.registerHandler( make_callback( class1a, &Class1::function2 ), NOTIFICATION_ONE );

   eventManager.registerHandler( make_callback( class1b, &Class1::function1 ), NOTIFICATION_ONE );

   eventManager.registerHandler( make_callback( class2, &Class2::function1 ), NOTIFICATION_ONE );

   // Registramos una clase que hereda callbackbase:

   eventManager.registerHandler( &class3, NOTIFICATION_ONE );

   // Lanzamos un evento a nuestras funciones:

   eventManager.notifyHandlers( NOTIFICATION_ONE  );

   return 1;

}

Al ejecutarlo, obtenemos la siguiente salida:

class1::function1: 1a
class1::function2: 1a
class1::function1: 1b
class2::function1
class3::function1

Obviamente al programa le falta poder retirar callbacks del manejador de eventos y su administración de memoria, pero sólo busca servir como ejemplo del funcionamiento de los functores.

Hay que aclarar que este mismo programa se puede implementar usando apuntadores a funciones aunque se disminuye un poco el enfoque orientado a objetos.

Posteado en C/C++ | No hay comentarios »

« Anteriores