X-Git-Url: https://git.llucax.com/z.facultad/75.42/plaqui.git/blobdiff_plain/6e0194f46ac77c18bfeabf84ef94a32f23e41073..4472e0afab063b00af9301e85a8d9083e6261c4f:/Server/include/plaqui/server/runnable.h diff --git a/Server/include/plaqui/server/runnable.h b/Server/include/plaqui/server/runnable.h index 39a221f..97b3785 100644 --- a/Server/include/plaqui/server/runnable.h +++ b/Server/include/plaqui/server/runnable.h @@ -29,27 +29,173 @@ #define PLAQUI_RUNNABLE_H #include +#include -namespace Plaqui { +namespace PlaQui { - /// ealizauna tarea (generalmente en un thread). +namespace Server { + + /** + * Objeto cuya función principal es realizar una tarea puntual. + * + * Esta es la clase base para todos objetos que realizan una tarea, ya sea + * en un hilo (thread) propio o no. Al tener esta flexibilidad hay + * dos formas típicas de usarlo cuyo punto en común es implementar una + * subclase (ya que esta clase es abstracta) y sobreescribir el método + * privado real_run(). Una vez hecho esto hay dos opciones más comunes + * según se lo corra en un thread o no: + * - Para correrlo en el hilo principal (esperando que termine de + * ejecutarse) generalmente basta con crear el objeto de forma estática y + * llamar a su método run(): + * \code + * #include "runnable.h" + * #include + * + * // Mi objeto que realiza la tarea. + * class MiRunnable: public Runnable { + * void real_run(void) { std::cout << "Corriendo." << std::endl; } + * } + * + * // Programa principal. + * int main(void) { + * MiRunnable runner; + * runner.run(false); // Corre en el hilo principal + * return 0; + * } + * \endcode + * - Para correrlo en el hilo propio el proceso es un poco más complejo, en + * especial si se necesita saber cuando finalizó. Si esto no fuera + * necesario, basta con crear el objeto dinámicamente y correr su método + * run(). El objeto se libera automáticamente cuando termina su tarea. + * Si es necesario saber cuando termina, se puede usar la señal + * signal_finished(). El caso típico sería: + * \code + * #include "runnable.h" + * #include + * #include + * + * // Mi objeto que realiza la tarea. + * class MiRunnable: public Runnable { + * void real_run(void) { std::cout << "Corriendo." << std::endl; } + * } + * + * // Puntero al objeto que realiza la tarea. + * MiRunnable* runner; + * + * // Atiende la señal que indica que el objeto terminó su tarea. + * void on_finished(void) { + * runner = 0; + * } + * + * // Programa principal. + * int main(void) { + * runner = new MiRunnable(); + * // Conecta la señal finished para saber cuando terminó. + * runner->signal_finished().connect(SigC::slot(on_finished)); + * runner->run(); // Corre en un hilo propio + * // Espera a que termine la tarea. + * while (runner) { + * sleep(1); + * } + * // No necesito liberar su memoria, se libera automáticamente. + * return 0; + * } + * \endcode + * + * Nótese que al correr la tarea en un hilo propio no se pueden capturar + * errores con un bloque try;catch. Para reportar errores se provee + * de la señal signal_error(). + */ class Runnable { + ///////////////////////////////////////////////////////////////////// + // Tipos. + + public: + + /// Error. + typedef unsigned Error; + + ///////////////////////////////////////////////////////////////////// + /// \name Señales + //@{ + + public: + + /// Tipo de señal para indicar que se finalizó la tarea. + typedef SigC::Signal0 SignalFinished; + + /// Tipo de señal para indicar que hubo un error. + typedef SigC::Signal2 + SignalError; + + /// Obtiene la señal que avisa cuando la tarea es finalizada. + SignalFinished& signal_finished(void); + + /// Obtiene la señal que avisa que hubo un error. + SignalError& signal_error(void); + + //@} + + ///////////////////////////////////////////////////////////////////// + // Atributos. + + private: + + /// Thread en el cual correr la tarea. + Glib::Thread* _thread; + + /// Señal que indica que se finalizó la tarea. + SignalFinished _finished; + + /// Señal que indica que hubo un error. + SignalError _error; + + /// Indica si se debe frinalizar la tarea. + bool _stop; + + /// Mutex para stop. + Glib::Mutex stop_mutex; + + ///////////////////////////////////////////////////////////////////// + // Métodos. + private: - // Thread en el cual correr la tarea. - Glib::Thread* thread; + + /** + * Corre la tarea controlando cuando termina. + * + * \param runner Objeto con la tarea a realizar. + */ + static void static_run(Runnable* runner); protected: - /// Realiza la terea. - virtual void real_run(void) = 0; + /** + * Indica si la tarea debe finalizar. + */ + bool stop(void); + + /** + * Establece si la tarea debe finalizar. + * + * \param stop Nuevo valor. + * + * \return Valor anterior. + */ + bool stop(bool stop); + + /** + * Realiza la terea. + */ + virtual void real_run(void) throw() = 0; public: /** * Destructor. */ - virtual ~Runnable(void) {} + virtual ~Runnable(void); /** * Constructor. @@ -57,15 +203,26 @@ namespace Plaqui { Runnable(void); /** - * Comienza la tares. + * Comienza la tarea. * * \param detach Si es true se corre en un thread propio. Si no no * retorna hasta que finaliza. */ virtual void run(bool detach = true); + /** + * Finaliza la tarea. + * + * \note Para saber cuando la tarea fue finalizada puede utilizar + * la señal signal_finished(). + */ + virtual void finish(void); + + }; } +} + #endif // PLAQUI_RUNNABLE_H