/// <summary>
 /// Método responsável por retirar da lista todos os semáforos que existem para que um nova seja criada.
 /// </summary>
 /// <param name="oidCronograma">Oid do cronograma</param>
 /// <param name="excluirSemaforos">Atributo que autoriza a exclusão de todos os semáforos.</param>
 public static void ExcluirSemaforosInativosPorCronograma(Guid oidCronograma, bool excluirSemaforos)
 {
     if (excluirSemaforos)
     {
         if (semaforosPorCronograma.ContainsKey(oidCronograma))
         {
             //lock na lista de semáforos daquele cronograma para que nenhuma outra thread adicione mais semáforos a esta lista.
             lock (semaforosPorCronograma[oidCronograma].semaforos)
             {
                 if (semaforosPorCronograma[oidCronograma].semaforos.Count > 0)
                 {
                     semaforosPorCronograma[oidCronograma] = new SemaforosControle()
                     {
                         lockerSemaforos = new ReaderWriterLockSlim(), semaforos = new List <SemaforoPorIntervalo>()
                     }
                 }
                 ;
             }
         }
     }
 }
        /// <summary>
        /// Método responsável por consultar os semáforos que uma determinada thread de reordenação deverá esperar para então executar sua própria reordenação.
        /// </summary>
        /// <param name="oidCronograma">Oid do cronograma (índice do dicionário de cronogramas)</param>
        /// <param name="inicio">Início do intervalo</param>
        /// <param name="final">Final do intervalo</param>
        /// <returns>Retorna uma lista contendo os semáforos que deve-se esperar</returns>
        public Hashtable ConsultarSemaforosImpactadosPorCronograma(Guid oidCronograma, short inicio, short final, Hashtable semaforos)
        {
            List <SemaforoPorIntervalo> semaforosImpactadosAguardar = new List <SemaforoPorIntervalo>();
            List <SemaforoPorIntervalo> semaforosImpactadosNovos    = new List <SemaforoPorIntervalo>();

            lock (semaforosPorCronograma[oidCronograma].semaforos)
            {
                EsperarLeituraSemaforos(oidCronograma);

                if (semaforosPorCronograma[oidCronograma].semaforos.Count == 0)
                {
                    semaforosImpactadosNovos.Add(new SemaforoPorIntervalo(inicio, final));
                }
                else
                {
                    for (int i = 0; i < semaforosPorCronograma[oidCronograma].semaforos.Count; i++)
                    {
                        SemaforoPorIntervalo.VerificarSemaforosImpactados(ref semaforosImpactadosAguardar, ref semaforosImpactadosNovos, ref semaforosImpactadosNovos,
                                                                          semaforosPorCronograma[oidCronograma].semaforos[i], inicio, final);

                        if (semaforosImpactadosNovos.Count > 0)
                        {
                            if (semaforosImpactadosAguardar.Count > 0)
                            {
                                for (int indice = 0; indice < semaforosImpactadosAguardar.Count; indice++)
                                {
                                    SemaforoPorIntervalo.DecrementarContadorSemaforoEmEspera(semaforosImpactadosAguardar[indice]);
                                }
                            }
                            break;
                        }
                    }
                }

                LiberarLeituraSemaforos(oidCronograma);

                if (semaforosImpactadosNovos.Count > 0)
                {
                    EsperarEscritaSemaforos(oidCronograma);

                    semaforosImpactadosAguardar.Clear();
                    semaforosImpactadosNovos.Clear();

                    List <SemaforoPorIntervalo> semaforosExistentes = semaforosPorCronograma[oidCronograma].semaforos;

                    if (semaforosPorCronograma[oidCronograma].semaforos.Count == 0)
                    {
                        SemaforoPorIntervalo novoSemaforo = new SemaforoPorIntervalo(inicio, final);

                        semaforosPorCronograma[oidCronograma].semaforos.Add(novoSemaforo);

                        semaforosImpactadosNovos.Add(novoSemaforo);
                    }
                    else
                    {
                        for (int i = 0; i < semaforosPorCronograma[oidCronograma].semaforos.Count; i++)
                        {
                            if (semaforosPorCronograma[oidCronograma].semaforos[i].semaforo != null)
                            {
                                SemaforoPorIntervalo.IncrementarContadorSemaforoEmEspera(semaforosPorCronograma[oidCronograma].semaforos[i]);

                                SemaforoPorIntervalo.VerificarSemaforosImpactados(ref semaforosImpactadosAguardar, ref semaforosImpactadosNovos, ref semaforosExistentes,
                                                                                  semaforosPorCronograma[oidCronograma].semaforos[i], inicio, final);

                                SemaforoPorIntervalo.DecrementarContadorSemaforoEmEspera(semaforosPorCronograma[oidCronograma].semaforos[i]);
                            }
                            else
                            {
                                semaforosPorCronograma[oidCronograma] = new SemaforosControle()
                                {
                                    lockerSemaforos = new ReaderWriterLockSlim(), semaforos = new List <SemaforoPorIntervalo>()
                                };

                                //cria um semáforo
                                SemaforoPorIntervalo novoSemaforo = new SemaforoPorIntervalo(inicio, final);

                                semaforosImpactadosNovos.Add(novoSemaforo);

                                semaforosPorCronograma[oidCronograma].semaforos.Add(novoSemaforo);
                            }
                        }
                    }

                    LiberarEscritaSemaforos(oidCronograma);
                }
            }

            semaforos.Add(SEMAFOROS_AGUARDAR, semaforosImpactadosAguardar);
            semaforos.Add(SEMAFOROS_NOVOS, semaforosImpactadosNovos);

            return(semaforos);
        }
        /// <summary>
        /// Método responsável controlar o acesso de threads simultaneamente enquanto leem e escrevem tanto no dicionário de cronogramas quanto na lista de semáforos de cada cronograma.
        /// Valida o acesso por cronograma e intervalo.
        /// </summary>
        /// <param name="oidCronograma">Oid cronograma</param>
        /// <param name="inicio">Início do intervalo</param>
        /// <param name="final">Final do intervalo</param>
        public virtual Hashtable ControlarSemaforos(Guid oidCronograma, short inicio, short final)
        {
            Hashtable semaforos = new Hashtable();

            ControlarIncrementacaoContadorAcessoPorCronograma(oidCronograma);

            ControlarExclusaoSemaforosInativosPorCronograma(oidCronograma);

            if (ValidarCronograma(oidCronograma))
            {
                semaforos = ConsultarSemaforosImpactadosPorCronograma(oidCronograma, inicio, final, semaforos);

                ControlarExclusaoCronogramasInexistentes();
            }
            else
            {
                EsperarEscritaCronogramas();

                if (semaforosPorCronograma.ContainsKey(oidCronograma))
                {
                    LiberarEscritaCronogramas();

                    semaforos = ConsultarSemaforosImpactadosPorCronograma(oidCronograma, inicio, final, semaforos);

                    ControlarExclusaoCronogramasInexistentes();

                    ControlarDecrementacaoContadorAcessoPorCronograma(oidCronograma);

                    return(semaforos);
                }
                else
                {
                    //cria um objeto SemaforoPorCronograma que armazena um semáforo e a lista de semáforos de um cronograma
                    SemaforosControle semaforosControle = new SemaforosControle()
                    {
                        lockerSemaforos = new ReaderWriterLockSlim(), semaforos = new List <SemaforoPorIntervalo>()
                    };

                    //cria um semáforo
                    SemaforoPorIntervalo novoSemaforo = new SemaforoPorIntervalo(inicio, final);

                    //cria uma lista para retornar na Hash
                    List <SemaforoPorIntervalo> semaforosNovos = new List <SemaforoPorIntervalo>();

                    semaforosNovos.Add(novoSemaforo);

                    //Adiciona o semáforo novo criado para retornar na hash
                    semaforos.Add(SEMAFOROS_NOVOS, semaforosNovos);

                    //adiciona o semáforo à lista de semáforo por cronograma.
                    semaforosControle.semaforos.Add(novoSemaforo);

                    //adiciona o cronograma e sua lista ao dicionário de cronogramas ativos.
                    semaforosPorCronograma.Add(oidCronograma, semaforosControle);
                }

                ControlarExclusaoCronogramasInexistentes();

                LiberarEscritaCronogramas();
            }

            ControlarDecrementacaoContadorAcessoPorCronograma(oidCronograma);

            return(semaforos);
        }