concorrenza tramite code di messaggi: come evitare la ricorsione?

1

Sto lavorando su un sistema di concorrenza basato su code di messaggi con un pool di thread sottostante. Una coda può indirizzare altre code. Inoltre, una coda può essere indirizzata da più code (ad es. Bambini) per creare una gerarchia ad albero e dare la priorità ad alcune code.

Voglio evitare di segnalare i thread ogni volta che un messaggio viene accodato mentre la coda (ei suoi figli) sono già stati svuotati.

Quindi la coda sa se è sleeping o running . La transizione da sleeping a running è facile. Ciò può essere fatto quando un nuovo messaggio è in coda.

Sono più preoccupato per il contrario. Come posso evitare di perdere messaggi / eventi quando eseguo la transizione da running a sleeping ? Per chiarire: questo non è un passo atomico. Anche la coda non può andare a dormire quando i suoi figli hanno ancora bisogno di attenzione.

Al momento nella funzione sleep imposto lo stato a sleeping , quindi controlla se la coda corrente oi suoi figli hanno eventi in sospeso che sono stati persi. Se è così, mi riattivo la coda. Ma ciò non può potenzialmente causare una ricorsione infinita di svegli - sonno - sveglio - sonno - ...?

Come posso evitarlo, o qual è il modo corretto per configurare un sistema di code di questo tipo?

In pseudo codice:

atomic state = sleeping
target = anotherQueue
children = queues that target this queue

func Async(event)
{
   get lock
   push event onto queue (i.e. array/fifo/...)
   release lock
   this.wakeup()
}


func wakeup()
{
    If (state == running) { return }
    state = running     
    !target ? drain() : target.wakeup()
}


func drain()
{
     while (event = next() )
     {
        event.run()
     }
     sleep()
}


func sleep()
{
  state = sleeping

  *** what if an event is posted during the transition from running to sleeping? ***

  //check if events have been missed
  If (event.count > 0)  
  {
    this.wakeup()
  }

  //check children: don't sleep if they have pending events
  If (children.haveEvents) { this.wakeup }

}


func next()
{
   get lock
   nextEvent = pop event from queue
   release lock

   If (!nextEvent)
   {
      //check each child queue for an event
      children.nextEvent
   }
   return nextEvent
}
    
posta user965972 06.09.2017 - 21:32
fonte

0 risposte

Leggi altre domande sui tag