X-Git-Url: https://git.llucax.com/z.facultad/75.42/plaqui.git/blobdiff_plain/00cffd5f7c35a915c09d55e6292775e9e01bdeec..4472e0afab063b00af9301e85a8d9083e6261c4f:/Server/include/plaqui/server/runnable.h?ds=inline diff --git a/Server/include/plaqui/server/runnable.h b/Server/include/plaqui/server/runnable.h index 7896090..97b3785 100644 --- a/Server/include/plaqui/server/runnable.h +++ b/Server/include/plaqui/server/runnable.h @@ -35,35 +35,129 @@ namespace PlaQui { namespace Server { - /// ealizauna tarea (generalmente en un thread). + /** + * 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; + Glib::Thread* _thread; /// Señal que indica que se finalizó la tarea. - SignalFinished finished; + SignalFinished _finished; - protected: + /// Señal que indica que hubo un error. + SignalError _error; - /** - * Indica si se debe frinalizar la tarea. - * - * \todo Poner como privado y poner get() set() con locks. - */ - bool stop; + /// Indica si se debe frinalizar la tarea. + bool _stop; + + /// Mutex para stop. + Glib::Mutex stop_mutex; + ///////////////////////////////////////////////////////////////////// // Métodos. private: @@ -77,8 +171,24 @@ namespace Server { 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: @@ -103,20 +213,11 @@ namespace Server { /** * Finaliza la tarea. * - * \param attach Si es true, la función no retorna hasta que no - * finalice la tearea (no recomendable). - * * \note Para saber cuando la tarea fue finalizada puede utilizar * la señal signal_finished(). */ - virtual void finish(bool attach = false); + virtual void finish(void); - /** - * Obtiene la señal que avisa cuando la tarea es finalizada. - * - * \see finish(). - */ - SignalFinished& signal_finished(void); };