~ubuntu-branches/ubuntu/wily/ginkgocadx/wily-proposed

« back to all changes in this revision

Viewing changes to src/cadxcore/main/controllers/controladorcomandos.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Andreas Tille
  • Date: 2011-05-02 08:09:26 UTC
  • Revision ID: james.westby@ubuntu.com-20110502080926-bql5wep49c7hg91t
Tags: upstream-2.4.1.1
Import upstream version 2.4.1.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *  
 
3
 *  $Id: controladorcomandos.cpp 3526 2011-03-16 19:56:19Z carlos $
 
4
 *  Ginkgo CADx Project
 
5
 *
 
6
 *  Copyright 2008-10 MetaEmotion S.L. All rights reserved.
 
7
 *  http://ginkgo-cadx.com
 
8
 *
 
9
 *  This file is licensed under LGPL v3 license.
 
10
 *  See License.txt for details
 
11
 *
 
12
 *
 
13
 */
 
14
//#define _GINKGO_TRACE
 
15
 
 
16
#include <api/globals.h>
 
17
#include <api/icomando.h>
 
18
 
 
19
#include <main/controllers/controladorlog.h>
 
20
#include <main/controllers/controladoreventos.h>
 
21
#include <eventos/eventosginkgo.h>
 
22
 
 
23
#include <wx/wx.h>
 
24
#include <wx/thread.h>
 
25
 
 
26
#include "controladorcomandos.h"
 
27
#include <main/gui/mainwindow/ventanaprincipal.h>
 
28
 
 
29
//#undef GTRACE
 
30
//#define GTRACE(expr) std::cout << expr << std::endl
 
31
 
 
32
#if defined (_WINDOWS)
 
33
#define MS_VC_EXCEPTION 0x406D1388
 
34
 
 
35
#pragma pack(push,8)
 
36
typedef struct tagTHREADNAME_INFO
 
37
{
 
38
   DWORD dwType; // Must be 0x1000.
 
39
   LPCSTR szName; // Pointer to name (in user addr space).
 
40
   DWORD dwThreadID; // Thread ID (-1=caller thread).
 
41
   DWORD dwFlags; // Reserved for future use, must be zero.
 
42
} THREADNAME_INFO;
 
43
#pragma pack(pop)
 
44
 
 
45
void GNC::GCS::Threading::SetThreadName( long threadID, const std::string& threadName)
 
46
{
 
47
   //Sleep(10);
 
48
   THREADNAME_INFO info;
 
49
   info.dwType = 0x1000;
 
50
   info.szName = threadName.c_str();
 
51
   info.dwThreadID = threadID;
 
52
   info.dwFlags = 0;
 
53
 
 
54
   __try
 
55
   {
 
56
      RaiseException( MS_VC_EXCEPTION, 0, sizeof(info)/sizeof(ULONG_PTR), (ULONG_PTR*)&info );
 
57
   }
 
58
   __except(EXCEPTION_EXECUTE_HANDLER)
 
59
   {
 
60
   }
 
61
}
 
62
#elif defined(__WXOSX__)
 
63
#include <pthread.h>
 
64
#include <sys/signal.h>
 
65
 
 
66
void GNC::GCS::Threading::SetThreadName( long /*threadID*/, const std::string& threadName)
 
67
{
 
68
        //pthread_setname_np(threadName.c_str());
 
69
}
 
70
 
 
71
void FooSignalHandler(int sig)
 
72
{
 
73
        GTRACE("SIGUSR1 recibido");
 
74
}
 
75
#else
 
76
#include <pthread.h>
 
77
#include <sys/signal.h>
 
78
 
 
79
void GNC::GCS::Threading::SetThreadName( long threadID, const std::string& threadName)
 
80
{
 
81
}
 
82
 
 
83
void FooSignalHandler(int sig)
 
84
{
 
85
        GTRACE("SIGUSR1 recibido");
 
86
}
 
87
 
 
88
#endif
 
89
GNC::LanzadorComandos::LanzadorComandos(GNC::GCS::IComando* pComando)
 
90
{
 
91
        //std::cout << "LanzadorComandos::LanzadorComandos()" << this << std::endl;
 
92
        m_idThreadGinkgo = 0;
 
93
        m_pComando = pComando;
 
94
        m_Abortar = false;
 
95
        //this->Create();
 
96
        m_pComando->SetNotificadorProgreso(this);
 
97
        //NotificarProgreso(0.0f, m_pComando->GetName());
 
98
}
 
99
 
 
100
GNC::LanzadorComandos::~LanzadorComandos()
 
101
{
 
102
        GTRACE("<< LanzadorComandos::~LanzadorComandos() " << m_idThreadGinkgo);
 
103
}
 
104
 
 
105
void* GNC::LanzadorComandos::Entry()
 
106
{
 
107
        GTRACE(">> LanzadorComandos::Entry() " << m_idThreadGinkgo << " " << m_pComando->GetName());
 
108
        this->IniciarUnlocker();
 
109
 
 
110
        GNC::GCS::Threading::SetThreadName( GetId(), m_pComando->GetName());
 
111
 
 
112
        if (m_pComando != NULL && !m_pComando->EstaAbortado() && m_Dependencias.Size(GLOC()) > 0) {
 
113
                GTRACE(">> LanzadorComandos::Entry() " << m_idThreadGinkgo << " " << m_pComando->GetName() << ") espera " << m_Dependencias.Size(GLOC()) << " tareas");
 
114
                while (m_Dependencias.NotEmpty(GLOC())) {
 
115
                        if (!m_Dependencias.Wait(1000, GLOC())) {
 
116
                                //std::cout << "Timeout de espera para " << m_pComando->GetName() << "(" << m_idThreadGinkgo << ") " << m_Dependencias.Size(GLOC()) << " pendientes" << std::endl;
 
117
                                m_Dependencias.TerminarPendientes(GLOC());
 
118
                        }
 
119
                }
 
120
                GTRACE(">> LanzadorComandos::Entry() " << m_idThreadGinkgo << " " << m_pComando->GetName() << " espera terminada");
 
121
        }
 
122
 
 
123
        wxWindow* w = GNC::GCS::ControladorComandos::Instance()->GetVentanaRegistrada();
 
124
 
 
125
        bool iniciado = false;
 
126
 
 
127
        if (m_pComando != NULL && !m_pComando->EstaAbortado()) {
 
128
 
 
129
                if (w != NULL) {
 
130
                        iniciado = true;
 
131
                        EventoProgreso ce(EventoProgreso::ComandoIniciado, m_idThreadGinkgo);
 
132
                        w->AddPendingEvent(ce);
 
133
                }
 
134
 
 
135
                try {
 
136
                        m_pComando->Execute();
 
137
                }
 
138
                catch (GNC::GCS::ControladorComandosException& ) {
 
139
                        //comando abortado
 
140
                }
 
141
                catch (const std::bad_alloc& ) {
 
142
                        //comando ha cascado por un bad alloc
 
143
                }
 
144
                catch (const std::exception& ) {
 
145
                        //comando abortado
 
146
                }
 
147
                catch (...) {
 
148
                        LOG_ERROR("LanzadorComandos", "Error interno ejecutando el comando con id = " << m_pComando->GetId());
 
149
                }
 
150
 
 
151
        }
 
152
 
 
153
 
 
154
 
 
155
 
 
156
        GTRACE("<< LanzadorComandos::Entry(): "  << m_idThreadGinkgo << " " << m_pComando->GetName());
 
157
        return NULL;
 
158
}
 
159
 
 
160
bool GNC::LanzadorComandos::RecalcularDependencias()
 
161
{
 
162
        //revisamos la lista de "aborta si" ya que en ese caso no arrancamos
 
163
 
 
164
        if(m_Abortar){
 
165
                return false;
 
166
        }
 
167
 
 
168
        //GTRACE(">> comprobando el ''AbortaSi'' y el ''CancelaA'' : " << m_idThreadGinkgo);
 
169
        GNC::GCS::ControladorComandos::MapaComandos* mapaComandosLanzados = &(GNC::GCS::ControladorComandos::Instance()->m_ComandosLanzados);
 
170
        for(GNC::GCS::ControladorComandos::MapaComandos::iterator it = mapaComandosLanzados->begin(); it!= mapaComandosLanzados->end(); ++it){
 
171
                LanzadorComandos* pLanzador = (*it).second;
 
172
                if (pLanzador == this) {
 
173
                        continue;
 
174
                }
 
175
 
 
176
                for(GNC::GCS::TipoListaIdComandos::iterator it1 = m_pComando->m_Conflictos.begin(); it1 != m_pComando->m_Conflictos.end(); ++it1){
 
177
                        if(pLanzador->GetComando()->GetId() == (*it1) && pLanzador->m_idThreadGinkgo != m_idThreadGinkgo){
 
178
                                GTRACE("\tNo se registra espera: " << m_pComando->GetName() << "(" << m_idThreadGinkgo << ") aborta_si " << pLanzador->m_pComando->GetName() << "(" << pLanzador->m_idThreadGinkgo << ") = " << this);
 
179
                                //GTRACE(">> encontrado un comando de ''AbortaSi'' => NO SE EJECUTA " << m_idThreadGinkgo);
 
180
                                return false;
 
181
                        }
 
182
                }
 
183
        }
 
184
 
 
185
        for(GNC::GCS::ControladorComandos::MapaComandos::iterator it = mapaComandosLanzados->begin(); it!= mapaComandosLanzados->end(); ++it){
 
186
                LanzadorComandos* pLanzador = (*it).second;
 
187
                if (pLanzador == this) {
 
188
                        continue;
 
189
                }
 
190
 
 
191
                for(GNC::GCS::TipoListaIdComandos::iterator it1 = m_pComando->m_Reemplazos.begin(); it1 != m_pComando->m_Reemplazos.end(); ++it1){
 
192
                        if(pLanzador->GetComando()->GetId() == (*it1) && pLanzador->m_idThreadGinkgo != m_idThreadGinkgo){
 
193
                                //GTRACE(">> encontrado un comando de ''CancelaA'' => El hilo " << m_idThreadGinkgo<< " cancelara a "<<pLanzador->m_idThreadGinkgo);
 
194
                                if (pLanzador != NULL) { //
 
195
                                        m_Dependencias.RegistrarEspera(pLanzador, GLOC());
 
196
                                        GTRACE("\tRegistrada espera: " << m_pComando->GetName() << "(" << m_idThreadGinkgo << ") cancela_a " << pLanzador->m_pComando->GetName() << "(" << pLanzador->m_idThreadGinkgo << ") = " << this);
 
197
                                        pLanzador->Terminar();
 
198
                                }
 
199
                                else {
 
200
                                        std::cerr << "Detectada inconsistencia en el controlador de comandos: Comando lanzado desreferenciado. Flujo de comando perdido." << std::endl;
 
201
                                }
 
202
                        }
 
203
                }
 
204
 
 
205
                for(GNC::GCS::TipoListaIdComandos::iterator it1 = m_pComando->m_Dependencias.begin(); it1 != m_pComando->m_Dependencias.end(); ++it1){
 
206
                        if(pLanzador != NULL && pLanzador->GetComando()->GetId() == (*it1) && pLanzador->m_idThreadGinkgo != m_idThreadGinkgo){
 
207
                                //GTRACE(">> encontrado un comando de ''Espera a'' => El hilo " << m_idThreadGinkgo<< " esprerara a "<<pLanzador->m_idThreadGinkgo);
 
208
                                //nos aseguramos de que el no esta esperando por nosostros... en tal caso habría un bloqueo mutuo!!!
 
209
                                //solo se permite en caso de que los dos comandos tengan el mismo id por ejemplo comandos que se tienen que ejecutar en serie,
 
210
                                //en tal caso solo le esperamos si su id es menor que el nuestro
 
211
                                if(pLanzador->GetComando()->GetId() != this->GetComando()->GetId() ||
 
212
                                        (pLanzador->GetComando()->GetId() == this->GetComando()->GetId() && m_idThreadGinkgo > pLanzador->m_idThreadGinkgo))
 
213
                                {
 
214
                                        m_Dependencias.RegistrarEspera(pLanzador, GLOC());
 
215
                                        GTRACE("\tRegistrada espera: " << m_pComando->GetName() << "(" << m_idThreadGinkgo << ") espera_a " << pLanzador->m_pComando->GetName() << "(" << pLanzador->m_idThreadGinkgo << ") = " << this);
 
216
                                }
 
217
                        }
 
218
                }
 
219
        }
 
220
        return true;
 
221
}
 
222
 
 
223
void GNC::LanzadorComandos::OnExit()
 
224
{
 
225
        GTRACE(/*"LanzadorComandos",*/ ">> Comando Terminado");
 
226
        {
 
227
                GNC::GCS::ILocker pLocker(GNC::GCS::ControladorComandos::Instance(), GLOC());
 
228
 
 
229
                GTRACE(">> LanzadorComandos::OnExit() " << m_idThreadGinkgo << " " << m_pComando->GetName());
 
230
 
 
231
                //region "Region sincrona con ControladorComandos"
 
232
                m_pComando->SetNotificadorProgreso(NULL);
 
233
 
 
234
                GNC::GCS::ControladorComandos::MapaComandos::iterator it = GNC::GCS::ControladorComandos::Instance()->m_ComandosLanzados.find(m_idThreadGinkgo);
 
235
                if (it != GNC::GCS::ControladorComandos::Instance()->m_ComandosLanzados.end()) {
 
236
                        GNC::GCS::ControladorComandos::Instance()->m_ComandosLanzados.erase(it);
 
237
                }
 
238
 
 
239
                GTRACE("  LanzadorComandos::OnExit(): Notificando pendientes. threadId = " << m_idThreadGinkgo);
 
240
 
 
241
                //avisa a los que estan esperando
 
242
 
 
243
                wxWindow* w = GNC::GCS::ControladorComandos::Instance()->GetVentanaRegistrada();
 
244
 
 
245
                if (w != NULL) {
 
246
                        GNC::GCS::ControladorComandos::Instance()->m_ComandosTerminados[m_idThreadGinkgo] = m_pComando;
 
247
                        GTRACE(/*"LanzadorComandos::OnExit()", */"Propagando evento de finalizacion a la ventana principal");
 
248
                        EventoProgreso ce(EventoProgreso::ComandoFinalizado, m_idThreadGinkgo);
 
249
                        w->AddPendingEvent(ce);
 
250
                }
 
251
                else {
 
252
                        LOG_WARN("LanzadorComandos::OnExit()", "Error: No se invocara el evento de finalizacion del comando. El sistema puede quedar bloqueado o inestable");
 
253
                        if (m_pComando != NULL) {
 
254
                                m_pComando->Abort(); // Notificamos al comando de que va a abortar.
 
255
                                delete m_pComando;
 
256
                                m_pComando = NULL;
 
257
                        }
 
258
                }
 
259
        }
 
260
 
 
261
        GTRACE(">> LanzadorComandos::OnExit() " << m_idThreadGinkgo << " Notificación a " << m_ListaNotificacion.size() << " tareas que esperan");
 
262
 
 
263
 
 
264
        Signal(GLOC());
 
265
 
 
266
        //LOG_TRACE("LanzadorComandos", "<< Comando Terminado");
 
267
 
 
268
        //endregion
 
269
 
 
270
        GTRACE("<< LanzadorComandos::OnExit() " << m_idThreadGinkgo);
 
271
}
 
272
 
 
273
void GNC::LanzadorComandos::IniciarUnlocker()
 
274
{
 
275
        #if defined(_WINDOWS)
 
276
 
 
277
        #else
 
278
        /*
 
279
        struct sigaction action;
 
280
        memset(&action, 0, sizeof(action));
 
281
        sigemptyset(&action.sa_mask);
 
282
        action.sa_flags = 0;
 
283
        action.sa_handler = FooSignalHandler;
 
284
        sigaction(SIGUSR2, &action, NULL);
 
285
        */
 
286
        #endif
 
287
}
 
288
 
 
289
void GNC::LanzadorComandos::DoTerminar()
 
290
{
 
291
        this->m_Abortar = true;
 
292
        if (m_pComando != NULL) {
 
293
                //std::cout << "LanzadorComandos::DoTerminar(): Abortando comando:" << std::endl;
 
294
                m_pComando->Abort();
 
295
        }
 
296
        #if defined(_WINDOWS)
 
297
 
 
298
        #else
 
299
        //pthread_kill((pthread_t)this->GetId(), SIGUSR2);
 
300
 
 
301
        #endif
 
302
}
 
303
 
 
304
bool GNC::LanzadorComandos::NotificarProgreso(float progresoNormalizado, const std::string& texto)
 
305
{
 
306
        //GNC::GCS::ILocker pLocker(this, GLOC());
 
307
        if(m_Abortar){
 
308
                //std::cout << "Comando abortado: No se notificara el progreso" << std::endl;
 
309
                return false;
 
310
        }
 
311
        //GTRACE(">> LanzadorComandos::NotificarProgreso(): " << m_idThreadGinkgo);
 
312
        LockProgreso(GLOC());
 
313
        SetProgresoNormalizado(std::max<float>(0, std::min<float>(progresoNormalizado,1.0f)));
 
314
        SetTextoProgreso(texto);
 
315
        UnLockProgreso(GLOC());
 
316
 
 
317
 
 
318
        wxWindow* w = GNC::GCS::ControladorComandos::Instance()->GetVentanaRegistrada();
 
319
        if(w!=NULL) {
 
320
                EventoProgreso ce(EventoProgreso::ComandoEjecutando, m_idThreadGinkgo);
 
321
                //std::cout << "AddPendingEvent EventoProgreso::ComandoEjecutando " << m_idThreadGinkgo << std::endl;
 
322
                w->GetEventHandler()->AddPendingEvent(ce);
 
323
        }
 
324
        //GTRACE("<< LanzadorComandos::NotificarProgreso(): " << m_idThreadGinkgo);
 
325
        return true;
 
326
 
 
327
}
 
328
 
 
329
//----------------------------------------------------------------------------------------------------
 
330
//----------------------------------------------------------------------------------------------------
 
331
 
 
332
//region Controlador de comandos
 
333
 
 
334
GNC::GCS::ControladorComandos* GNC::GCS::ControladorComandos::m_psInstancia = NULL;
 
335
 
 
336
GNC::GCS::ControladorComandos::ControladorComandos()
 
337
{
 
338
        m_Destroying = false;
 
339
        m_pWin = NULL;
 
340
        m_pProgreso = NULL;
 
341
        m_idThreads = 1;
 
342
}
 
343
 
 
344
GNC::GCS::ControladorComandos::~ControladorComandos()
 
345
{
 
346
        GTRACE(">> ControladorComandos::~ControladorComandos() ");
 
347
        AbortarComandosDeOwner(NULL);
 
348
        GTRACE("<< ControladorComandos::~ControladorComandos() ");
 
349
}
 
350
 
 
351
GNC::GCS::ControladorComandos* GNC::GCS::ControladorComandos::Instance()
 
352
{
 
353
        if (m_psInstancia == NULL) {
 
354
                m_psInstancia = new ControladorComandos();
 
355
        }
 
356
        return m_psInstancia;
 
357
}
 
358
 
 
359
void GNC::GCS::ControladorComandos::FreeInstance()
 
360
{
 
361
        if (m_psInstancia != NULL) {
 
362
                delete m_psInstancia;
 
363
                m_psInstancia = NULL;
 
364
        }
 
365
 
 
366
}
 
367
 
 
368
void GNC::GCS::ControladorComandos::Process(GNC::GCS::IComando * cmd)
 
369
{
 
370
        cmd->Execute();
 
371
        cmd->Update();
 
372
        delete cmd;
 
373
}
 
374
 
 
375
void GNC::GCS::ControladorComandos::ProcessAsync(std::string str, GNC::GCS::IComando* cmd, void * owner)
 
376
{
 
377
        cmd->SetOwner(owner);
 
378
        cmd->SetNotificadorProgreso(NULL);
 
379
        LanzadorComandos* thread = new LanzadorComandos(cmd);
 
380
        //thread->SetPriority(WXTHREAD_MAX_PRIORITY);
 
381
 
 
382
        GNC::GCS::ILocker locker(this, GLOC());
 
383
 
 
384
        long threadId = m_idThreads++;
 
385
        thread->m_idThreadGinkgo = threadId;
 
386
 
 
387
        int res = -1;
 
388
        int creado = -1;
 
389
        try {
 
390
                if (thread->RecalcularDependencias()) {
 
391
                        creado = thread->Create();
 
392
                        res = thread->Run();
 
393
                }
 
394
                else {
 
395
                        delete cmd;
 
396
                        if(creado == wxTHREAD_NO_ERROR)
 
397
                        {
 
398
                                thread->Delete();
 
399
                        } else {
 
400
                                delete thread;
 
401
                        }
 
402
                        thread = NULL;
 
403
                }
 
404
        }
 
405
        catch (GNC::GCS::ControladorComandosException& ex) {
 
406
                LOG_ERROR("ControladorComandos", "Error al lanzar el comando: " << ex);
 
407
                delete cmd;
 
408
                if(creado == wxTHREAD_NO_ERROR)
 
409
                {
 
410
                        thread->Delete();
 
411
                } else {
 
412
                        delete thread;
 
413
                }
 
414
                thread = NULL;
 
415
        }
 
416
        catch (...) {
 
417
                LOG_ERROR("ControladorComandos", "Error interno al lanzar el comando");
 
418
                delete cmd;
 
419
                if(creado == wxTHREAD_NO_ERROR)
 
420
                {
 
421
                        thread->Delete();
 
422
                }
 
423
                else {
 
424
                        delete thread;
 
425
                }
 
426
                thread = NULL;
 
427
        }
 
428
        if ( res == wxTHREAD_NO_ERROR && creado == wxTHREAD_NO_ERROR)
 
429
        {
 
430
                m_ComandosLanzados[threadId] = thread;
 
431
                MapaOwners::iterator it = m_MapaOwners.find(owner);
 
432
                if (it != m_MapaOwners.end())
 
433
                {
 
434
                        (*it).second.push_back(threadId);
 
435
                }
 
436
                else
 
437
                {
 
438
                        ListaHilos l;
 
439
                        l.push_back(threadId);
 
440
                        m_MapaOwners[owner] = l;
 
441
                }
 
442
        }
 
443
}
 
444
 
 
445
//este metodo es un poco malo porque la busqueda iterada...
 
446
void GNC::GCS::ControladorComandos::AbortarComando(IComando* pComando, bool sincrono)
 
447
{
 
448
        GNC::GCS::WaitQueue wqueue;
 
449
        GNC::GCS::ILocker locker(this, GLOC());
 
450
        GTRACE(">> GNC::GCS::ControladorComandos::AbortarComando(pComando) ");
 
451
        // Recorremos la lista de threads_ids de la vista
 
452
        for(MapaComandos::iterator it = m_ComandosLanzados.begin(); it!= m_ComandosLanzados.end(); ++it){
 
453
                LanzadorComandos* pLanzador = (*it).second;
 
454
                if(pLanzador == NULL || (*it).second->GetComando() != pComando){
 
455
                        continue;
 
456
                }
 
457
                GTRACE("\t\t Localizado: " << pLanzador->m_pComando->GetName() << "(" << pLanzador->m_idThreadGinkgo << ")");
 
458
                if (sincrono ) {
 
459
                        wqueue.RegistrarEspera(pLanzador, GLOC());
 
460
                        std::cerr << "Registrando espera para tarea: ptr = " << pLanzador << std::endl;
 
461
                }
 
462
                pLanzador->Terminar();
 
463
        }
 
464
        GTRACE("<< ControladorComandos::AbortarComandos(pComando)");
 
465
}
 
466
 
 
467
void GNC::GCS::ControladorComandos::AbortarComando(long threadId, bool sincrono)
 
468
{
 
469
        GNC::GCS::WaitQueue wqueue;
 
470
 
 
471
        //---------------------------------------------------------------------
 
472
        // REGION CRITICA
 
473
        //---------------------------------------------------------------------
 
474
        { // BEGIN Modificación del estado interno del controlador de comandos.
 
475
                GNC::GCS::ILocker locker(this, GLOC());
 
476
                GTRACE(">> ControladorComandos::AbortarComando(long) : CS");
 
477
                // Recorremos la lista de threads_ids de la vista
 
478
                MapaComandos::iterator it = m_ComandosLanzados.find(threadId);
 
479
                if (it != m_ComandosLanzados.end()) {
 
480
                        LanzadorComandos* pLanzador = (*it).second;
 
481
                        if (pLanzador != NULL) { //
 
482
                                if (sincrono ) {
 
483
                                        wqueue.RegistrarEspera(pLanzador, GLOC());
 
484
                                        std::cerr << "Registrando espera para tarea: threadId = " << (unsigned long) threadId << " ptr = " << pLanzador << std::endl;
 
485
                                }
 
486
                                pLanzador->Terminar();
 
487
                        } else {
 
488
                                std::cerr << "Detectada inconsistencia en el controlador de comandos: Comando lanzado desreferenciado. Flujo de comando perdido." << std::endl;
 
489
                        }
 
490
                } else { // Buscamos el id en la lista de comandos terminados
 
491
                        MapaComandosTerminados::iterator it3 = m_ComandosTerminados.find(threadId);
 
492
                        if (it3 != m_ComandosTerminados.end()) {
 
493
                                IComando* pComando = (*it3).second;
 
494
                                if (pComando != NULL) {
 
495
                                        std::cerr << "Anulando comando terminado: threadId = " << (unsigned long) threadId << std::endl;
 
496
                                        pComando->Abort();
 
497
                                        delete pComando;
 
498
                                } else {
 
499
                                        std::cerr << "Detectada inconsistencia en el controlador de comandos: Comando terminado nulo." << std::endl;
 
500
                                }
 
501
                                m_ComandosTerminados.erase(it3);
 
502
                        } else {
 
503
                                std::cerr << "Detectada inconsistencia en el controlador de comandos: Comando desreferenciado. Flujo de comando perdido." << std::endl;
 
504
                        }
 
505
                }
 
506
 
 
507
                GTRACE("<< ControladorComandos::AbortarComandos(long) : CS");
 
508
        }
 
509
        // END Modificación del estado interno del controlador de comandos.
 
510
        //---------------------------------------------------------------------
 
511
        //---------------------------------------------------------------------
 
512
        GTRACE("GNC::GCS::ControladorComandos::AbortarComando( " << threadId << ") : Esperando " << wqueue.Size(GLOC()) << " tareas");
 
513
        while (wqueue.NotEmpty()) {
 
514
                if (!wqueue.Wait(500, GLOC())) {
 
515
                        wqueue.TerminarPendientes(GLOC() );
 
516
                }
 
517
        }
 
518
        GTRACE("GNC::GCS::ControladorComandos::AbortarComando( " << threadId << ") : Espera terminada");
 
519
 
 
520
}
 
521
 
 
522
void GNC::GCS::ControladorComandos::AbortarComandosDeOwner(void * owner)
 
523
{
 
524
 
 
525
        GNC::GCS::WaitQueue wqueue;
 
526
 
 
527
        {
 
528
                GNC::GCS::ILocker locker(this, GLOC());
 
529
                GTRACE(">> ControladorComandos::AbortarComandosDeOwner(owner) : CS");
 
530
                // Recorremos la lista de threads_ids de la vista
 
531
                MapaOwners::iterator it1 = m_MapaOwners.find(owner);
 
532
                MapaComandos::iterator itcl;
 
533
                if (it1 != m_MapaOwners.end()) {
 
534
                        for (ListaHilos::iterator it2 = (*it1).second.begin(); it2 != (*it1).second.end(); it2++) {
 
535
                                long threadId = (*it2);
 
536
                                // Buscamos el id en la lista de comandos lanzados
 
537
                                itcl = m_ComandosLanzados.find(threadId);
 
538
                                if (itcl != m_ComandosLanzados.end()) { // El comando esta lanzado
 
539
                                        LanzadorComandos* pLanzador = (*itcl).second;
 
540
                                        if (pLanzador != NULL) { //
 
541
 
 
542
                                                wqueue.RegistrarEspera(pLanzador, GLOC());
 
543
                                                pLanzador->Terminar();
 
544
 
 
545
                                                std::cerr << "Registrando espera para tarea: threadId = " << (unsigned long) threadId << " ptr = " << pLanzador << std::endl;
 
546
                                        } else {
 
547
                                                std::cerr << "Detectada inconsistencia en el controlador de comandos: Comando lanzado desreferenciado. Flujo de comando perdido." << std::endl;
 
548
                                        }
 
549
                                } else { // Buscamos el id en la lista de comandos terminados
 
550
                                        MapaComandosTerminados::iterator it3 = m_ComandosTerminados.find(threadId);
 
551
                                        if (it3 != m_ComandosTerminados.end()) {
 
552
                                                IComando* pComando = (*it3).second;
 
553
                                                if (pComando != NULL) {
 
554
                                                        std::cerr << "Anulando comando terminado: threadId = " << (unsigned long) threadId << std::endl;
 
555
                                                        pComando->Abort();
 
556
                                                        delete pComando;
 
557
                                                } else {
 
558
                                                        std::cerr << "Detectada inconsistencia en el controlador de comandos: Comando terminado nulo." << std::endl;
 
559
                                                }
 
560
                                                m_ComandosTerminados.erase(it3);
 
561
                                        } else {
 
562
                                                std::cerr << "Detectada inconsistencia en el controlador de comandos: Comando desreferenciado. Flujo de comando perdido." << std::endl;
 
563
                                        }
 
564
                                }
 
565
                        }
 
566
                        m_MapaOwners.erase(it1);
 
567
                }
 
568
                GTRACE("<< ControladorComandos::AbortarComandosDeOwner(owner) : CS");
 
569
        }
 
570
 
 
571
        GTRACE("GNC::GCS::ControladorComandos::AbortarComandosDeOwner( " << owner << ") : Esperando " << wqueue.Size(GLOC()) << " tareas");
 
572
        while (wqueue.NotEmpty(GLOC())) {
 
573
                if (!wqueue.Wait(500, GLOC())) {
 
574
                        wqueue.TerminarPendientes(GLOC());
 
575
                }
 
576
        }
 
577
        GTRACE("GNC::GCS::ControladorComandos::AbortarComandosDeOwner( " << owner << ") : Espera terminada");
 
578
}
 
579
 
 
580
void GNC::GCS::ControladorComandos::AbortarComandosDeOwnerAsincrono(void * owner)
 
581
{
 
582
        GNC::GCS::ILocker locker(this, GLOC());
 
583
        GTRACE(">> ControladorComandos::AbortarComandosDeOwner(owner) : CS");
 
584
        // Recorremos la lista de threads_ids de la vista
 
585
        MapaOwners::iterator it1 = m_MapaOwners.find(owner);
 
586
        if (it1 != m_MapaOwners.end()) {
 
587
                for (ListaHilos::iterator it2 = (*it1).second.begin(); it2 != (*it1).second.end(); it2++) {
 
588
                        long threadId = (*it2);
 
589
                        // Buscamos el id en la lista de comandos lanzados
 
590
                        MapaComandos::iterator it = m_ComandosLanzados.find(threadId);
 
591
                        if (it != m_ComandosLanzados.end()) { // El comando esta lanzado
 
592
                                LanzadorComandos* pLanzador = (*it).second;
 
593
                                if (pLanzador != NULL) { //
 
594
                                        pLanzador->Terminar();
 
595
                                } else {
 
596
                                        std::cerr << "Detectada inconsistencia en el controlador de comandos: Comando lanzado desreferenciado. Flujo de comando perdido." << std::endl;
 
597
                                }
 
598
                        } else { // Buscamos el id en la lista de comandos terminados
 
599
                                MapaComandosTerminados::iterator it3 = m_ComandosTerminados.find(threadId);
 
600
                                if (it3 != m_ComandosTerminados.end()) {
 
601
                                        IComando* pComando = (*it3).second;
 
602
                                        if (pComando != NULL) {
 
603
                                                std::cerr << "Anulando comando terminado: threadId = " << (unsigned long) threadId << std::endl;
 
604
                                                pComando->Abort();
 
605
                                                delete pComando;
 
606
                                        } else {
 
607
                                                std::cerr << "Detectada inconsistencia en el controlador de comandos: Comando terminado nulo." << std::endl;
 
608
                                        }
 
609
                                        m_ComandosTerminados.erase(it3);
 
610
                                } else {
 
611
                                        std::cerr << "Detectada inconsistencia en el controlador de comandos: Comando desreferenciado. Flujo de comando perdido." << std::endl;
 
612
                                }
 
613
                        }
 
614
                }
 
615
                m_MapaOwners.erase(it1);
 
616
        }
 
617
        GTRACE("GNC::GCS::ControladorComandos::AbortarComandosDeOwnerAsincrono( " << owner << ")");
 
618
        GTRACE("<< ControladorComandos::AbortarComandosDeOwner(owner) : CS");
 
619
}
 
620
 
 
621
void GNC::GCS::ControladorComandos::OnComandoLanzado(long threadId)
 
622
{
 
623
 
 
624
        GNC::GCS::ILocker locker(this, GLOC());
 
625
 
 
626
        MapaComandos::iterator it = m_ComandosLanzados.find(threadId);
 
627
        if (it != m_ComandosLanzados.end()) {
 
628
                LanzadorComandos* pLanzador = (*it).second;
 
629
                pLanzador->m_pComando->SetNotificadorProgreso(pLanzador);
 
630
                if (m_pProgreso) {
 
631
                        m_pProgreso->InsertarTarea(threadId, pLanzador->m_pComando->GetName());
 
632
                }
 
633
                GNC::GCS::ControladorEventos::Instance()->ProcesarEvento(new GNC::GCS::Eventos::EventoProgresoComando(pLanzador->m_pComando, GNC::GCS::Eventos::EventoProgresoComando::TEP_Iniciado, 0.0f, pLanzador->m_pComando->GetName()));
 
634
        }
 
635
        else {
 
636
                MapaComandosTerminados::iterator it = m_ComandosTerminados.find(threadId);
 
637
                if (it != m_ComandosTerminados.end()) {
 
638
                        IComando* pComando = (*it).second;
 
639
                        if (m_pProgreso) {
 
640
                                m_pProgreso->InsertarTarea(threadId, pComando->GetName());
 
641
                        }
 
642
                        GNC::GCS::ControladorEventos::Instance()->ProcesarEvento(new GNC::GCS::Eventos::EventoProgresoComando(pComando, GNC::GCS::Eventos::EventoProgresoComando::TEP_Iniciado, 1.0f, pComando->GetName()));
 
643
                }
 
644
                else
 
645
                {
 
646
                        LOG_WARN("ControladorComandos", "Error al iniciar comunicacion de progreso del comando. Thread Id no encontrado.");
 
647
                        //std::cout << "OnComandoLanzado: Thread Id not found: " << threadId << std::endl;
 
648
                }
 
649
        }
 
650
}
 
651
 
 
652
void GNC::GCS::ControladorComandos::OnComandoProgreso(long threadId)
 
653
{
 
654
        GNC::GCS::ILocker locker(this, GLOC());
 
655
 
 
656
        MapaComandos::iterator it = m_ComandosLanzados.find(threadId);
 
657
        if (it != m_ComandosLanzados.end()) {
 
658
                LanzadorComandos* pLanzador = (*it).second;
 
659
                pLanzador->LockProgreso(GLOC());
 
660
                float progreso = pLanzador->GetProgresoNormalizado();
 
661
                std::string texto = pLanzador->GetTextoProgreso();
 
662
                pLanzador->UnLockProgreso(GLOC());
 
663
                m_pProgreso->SetProgresoTarea(threadId, progreso, texto);
 
664
                GNC::GCS::ControladorEventos::Instance()->ProcesarEvento(new GNC::GCS::Eventos::EventoProgresoComando(pLanzador->m_pComando, GNC::GCS::Eventos::EventoProgresoComando::TEP_Progreso, progreso, texto));
 
665
        }
 
666
        else {
 
667
                //std::cout << "OnComandoProgreso: Thread Id not found: " << threadId << std::endl;
 
668
        }
 
669
 
 
670
}
 
671
 
 
672
void GNC::GCS::ControladorComandos::OnComandoFinalizado(long threadId, bool lock)
 
673
{
 
674
        IComando* pComando = NULL;
 
675
 
 
676
        bool actualizar=false;
 
677
 
 
678
        GNC::GCS::ILocker* pLocker = NULL;
 
679
 
 
680
        //LOG_TRACE("ControladorComandos", "OnComandoFinalizado(" << threadId << ")");
 
681
 
 
682
        {
 
683
                if (lock) {
 
684
                        pLocker = new GNC::GCS::ILocker(this, GLOC());
 
685
                }
 
686
                if(m_pProgreso != NULL){
 
687
                        m_pProgreso->EliminarTarea(threadId);
 
688
                }
 
689
 
 
690
                MapaComandosTerminados::iterator it1 = m_ComandosTerminados.find(threadId);
 
691
                if (it1 != m_ComandosTerminados.end()) {
 
692
                        actualizar = true;
 
693
                        pComando = (*it1).second;
 
694
                        m_ComandosTerminados.erase(it1);
 
695
                }
 
696
                else {
 
697
                        //LOG_TRACE("ControladorComandos", "Id thread no encontrado en finalizados");
 
698
                }
 
699
 
 
700
 
 
701
                // TODO: Añadir un diccionario inverso o usar un set
 
702
                for (MapaOwners::iterator it2 = m_MapaOwners.begin(); it2 != m_MapaOwners.end(); it2++) {
 
703
                        ListaHilos::iterator it3 = (*it2).second.begin();
 
704
                        bool found = false;
 
705
                        while (!found && it3 != (*it2).second.end()) {
 
706
                                if ((*it3) == threadId) {
 
707
                                        found = true;
 
708
                                }
 
709
                                else {
 
710
                                        it3++;
 
711
                                }
 
712
                        }
 
713
                        if (found) {
 
714
                                GTRACE("ControladorComandos::OnComandoFinalizado(): threadId " << (unsigned long) threadId << " eliminado de la lista de owners");
 
715
                                (*it2).second.erase(it3);
 
716
                        }
 
717
                }
 
718
 
 
719
                if (pLocker != NULL)
 
720
                {
 
721
                        delete pLocker;
 
722
                        pLocker = NULL;
 
723
                }
 
724
        }
 
725
 
 
726
        if (pComando != NULL)
 
727
        {
 
728
                if (actualizar && !pComando->EstaAbortado()) {
 
729
                        pComando->Update();
 
730
                }
 
731
                else {
 
732
                        LOG_DEBUG("ControladorComandos" , "IComando::Update no invocado");
 
733
                }
 
734
                //LOG_TRACE("ControladorComandos", "Procesando evento de comando finalizado");
 
735
                GNC::GCS::ControladorEventos::Instance()->ProcesarEvento(new GNC::GCS::Eventos::EventoProgresoComando(pComando, GNC::GCS::Eventos::EventoProgresoComando::TEP_Finalizado));
 
736
                GTRACE(/*"ControladorComandos", */"Eliminando comando...");
 
737
                delete pComando;
 
738
                GTRACE(/*"ControladorComandos", */"Comando eliminado");
 
739
        }
 
740
        else {
 
741
                LOG_WARN("ControladorComandos", "Comando nulo. no se propagara el evento de fin de comando ni se actualizara");
 
742
                //std::cout << "ControladorComandos>> pComando = NULL!!!!" << std::endl;
 
743
        }
 
744
 
 
745
}
 
746
 
 
747
GNC::GCS::ControladorComandos::ListaNombreComandos GNC::GCS::ControladorComandos::GetComandosActivos()
 
748
{
 
749
        ListaNombreComandos lista;
 
750
        GNC::GCS::ILocker locker(this, GLOC());
 
751
        for(MapaComandos::iterator it = m_ComandosLanzados.begin(); it!=m_ComandosLanzados.end(); it++) {
 
752
                std::stringstream strstream;
 
753
                strstream << (*it).second->m_pComando->GetName() << ": " << (*it).second->GetTextoProgreso();
 
754
                lista.push_back( strstream.str());
 
755
        }
 
756
        return lista;
 
757
}
 
758
 
 
759
//endregion