Multiset recipiente parece parar de classificação
Pergunta
Eu gostaria de ajudar a depurar alguns comportamentos estranhos por um multiset recipiente.Ocasionalmente, o recipiente aparece para interromper a classificação.Este é um erro frequente, aparente em algumas simulações, depois de um longo tempo, e eu sou curto em idéias.(Eu sou um amador programador--sugestões de todos os tipos são bem-vindas.)
O meu é um recipiente std::multiset
que detém Event
estruturas:
typedef std::multiset< Event, std::less< Event > > EventPQ;
com o Event
estruturas ordenadas pelo seu double time
membros:
struct Event {
public:
explicit Event(double t) : time(t), eventID(), hostID(), s() {}
Event(double t, int eid, int hid, int stype) : time(t), eventID( eid ), hostID( hid ), s(stype) {}
bool operator < ( const Event & rhs ) const {
return ( time < rhs.time );
}
double time;
...
};
O programa repete-se através de períodos de adicionar eventos com desordenada vezes para EventPQ currentEvents
e, em seguida, puxando eventos em ordem.Raramente, depois de alguns eventos foram adicionados (perfeitamente legal " vezes), os eventos começam a ficar executadas fora de ordem.
O que poderia fazer os eventos já não conseguir ordenar corretamente?(Ou o que poderia atrapalhar o iterador?) Tenho verificado que todas as adicionado evento vezes são legítimas (por exemplo, todos exceder o tempo de simulação atual), e eu também confirmou que o erro não ocorrer devido a dois eventos acontecem para obter agendadas para o mesmo horário.
Gostaria de sugestões sobre como trabalhar com isso.
O código para a execução e a adição de eventos é abaixo para os curiosos:
double t = 0.0;
double nextTimeStep = t + EPID_DELTA_T;
EventPQ::iterator eventIter = currentEvents.begin();
while ( t < EPID_SIM_LENGTH ) {
// Add some events to currentEvents
while ( ( *eventIter ).time < nextTimeStep ) {
Event thisEvent = *eventIter;
t = thisEvent.time;
executeEvent( thisEvent );
eventCtr++;
currentEvents.erase( eventIter );
eventIter = currentEvents.begin();
}
t = nextTimeStep;
nextTimeStep += EPID_DELTA_T;
}
void Simulation::addEvent( double et, int eid, int hid, int s ) {
assert( currentEvents.find( Event(et) ) == currentEvents.end() );
Event thisEvent( et, eid, hid, s );
currentEvents.insert( thisEvent );
}
Devo acrescentar que, ocasionalmente, um evento, quando executado, irá excluir outros eventos de currentEvents
.Isso é feito com
double oldRecTime = 10.0; // gets defined legitimately in simulation
EventPQ::iterator epqItr = currentEvents.find( Event(oldRecTime) );
assert( currentEvents.count( Event(oldRecTime) ) == 1 );
currentEvents.erase( epqItr );
Mesmo se esse código parece bem, eu gostaria de saber outras maneiras que eu posso examinar o que está acontecendo--eu estou usando atualmente um monte de declarações() e cout << verifica.
Solução 3
Na simulação, onde eu comentei
// Add some events to currentEvents
Os eventos estavam sendo adicionados ao CurrentEvents. (Espero que estivesse claro.) Se foi adicionado um evento que pertencia ao topo da fila, acredito que isso atrapalhou o iterador apontando para o currentEvents.Begin (). Eu redefini o iterador imediatamente antes do interior enquanto o loop e as coisas parecem funcionar.
Atualizarei essa pergunta se isso não for a solução ou se houver outros problemas no que tenho aqui.
Obrigado a todos aqueles que comentaram; Isso me ajuda a aprender como eu deveria estar abordando esses problemas.
Outras dicas
O evento ciclo de processamento de falha para verificar se a fila está vazia.Caso contrário, tudo parece bem (mais ou menos).
Mas se você correr para fora de eventos em sua currentEvents
fila, o comportamento é indefinido.Ele provavelmente poderia se manifestar como algo que aparece como evento a ser processado fora de ordem.
Na verdade, algumas implementações do associativa recipientes eu vi representou-os por "praticamente circular" estruturas de dados, no sentido de que se você ignorar o fim da sequência controlado e continuar a repetir, o iterador que vai surgir no início da sequência.Pode ser que algo como o que está acontecendo no seu caso?
Outra pergunta que imediatamente surge em conexão com o seu código:o que acontece se o novo evento chega na fila com o time
valor que é menor do que o "atual" tempo?Eu não vejo qualquer verifica que iria capturar esta situação em seu código.Obviamente, se isso acontece, por exemplo,se alguns eventos chegar "tarde demais", eles podem facilmente obter processadas fora de ordem independentemente de como implementá-lo.
Se possível, eu aconselho a mudar o double
Você está usando como chave para algum tipo inteiro. A chave para um set
ou multiset
requer uma ordem fraca estrita - e um double
faz não (Normalmente) atenda a esse requisito (nem qualquer outro tipo de ponto flutuante IEEE).