2015-07-12 8 views
5

Sto tentando di scrivere un'applicazione gtkmm che utilizza il multithreading C++ 11. Tuttavia, continuo a correre nell'errore Fatal IO error 11 (Resource temporarily unavailable) on X server.Come combattere "Errore IO irreversibile 11 (risorsa temporaneamente non disponibile) su X server" in un'applicazione gtkmm multithread?

Ho diversi oggetti Gtk::Image sulla mia finestra. Ognuno è nel suo Gtk::EventBox e periodicamente devo cambiare l'immagine. Per farlo ho creato una classe che contiene la casella dell'evento per il blocco specifico e ha una funzione che rimuove l'immagine precedente, genera quella nuova e la posiziona lì.

Ecco un blocco di codice:

while (lock_flag.test_and_set()) {} // std::atomic_flag lock 
// ... 
std::cerr << 1; 
eventBox->foreach(
    [eb = this->eventBox](Gtk::Widget& w) 
    { 
     eb->Gtk::Container::remove(w); 
    } 
); 
std::cerr << 2; 
eventBox->add(*im); 
std::cerr << 3; 
eventBox->show_all_children(); 
std::cerr << 4; 
// ... 
lock_flag.clear(); 

Quando error 11 verifica alcuni dei numeri non si ottiene stampate a std::cerr, ma dove il problema accade è diverso ogni volta (ho recentemente osservato che schiantarsi dopo il 12 e dopo il 123). Così arrivo alla conclusione che la risorsa che viene utilizzata da qualche parte non è l'immagine, ma lo eventBox. Tuttavia, dopo l'inizializzazione del programma, non è accessibile da nessuna parte al di fuori di questa funzione e questa funzione è inclusa nel blocco std::atomic_flag.

Domande: quale può essere una ragione per tale comportamento? Posso assicurarmi che non accada? O posso prendere questo errore e mi aspetto di recuperare da esso?

Modifiche:

ho tentato

  1. Ho provato a cambiare da utilizzare std::thread-Glib::Threads::Thread, ma senza alcun risultato, ancora ottenere lo stesso errore.
  2. Dopo aver letto this ho tentato di aggiungere GDK_SYNCHRONIZE all'ambiente, questo ha generato l'errore [xcb] Unknown request in queue while dequeuing/[xcb] Most likely this is a multi-threaded client and XInitThreads has not been called. Questo mi ha portato a this post, dopo di che ho tentato di chiamare XInitThreads() prima di iniziare il nuovo thread (sia tramite Glib::Threads::Thread e std::thread), ma questo non ha fatto nulla di positivo; tranne che una volta per caso il thread ha effettivamente eseguito l'intera funzione (visualizzato '4' sullo schermo), ma poi è comunque riuscito a morire con lo stesso messaggio error 11.

risposta

2

Alla fine ecco come ho risolto tutti i problemi.

Passando attraverso il collegamento fornito da Phillip ho scoperto circa Glib::signal_timeout() e questo mi ha permesso di ripensare completamente il concetto di parallelismo nel mio codice.

Ecco quello che ho dovuto iniziare con:

if(running) return; 
running = true; 

static bool firstTime = true; 
if(firstTime) 
{ 
    XInitThreads(); 
    firstTime=false; 
} 

std::function<void()> f = [this]() -> void 
{ 
    while(running) 
    { 
     this->takeStep(); 
     std::this_thread::sleep_for(std::chrono::milliseconds(300)); 
    } 
}; 

std::thread(f).detach(); 

e questo potrebbe facilmente essere riscritto come:

if(running) return; 
running = true; 

runningHandle = Glib::signal_timeout().connect(sigc::mem_fun(*this, &ArtificialIntelligence::takeStep), 300); 

Poi ho solo bisogno di aggiungere runningHandle.disconnect(); alla mia funzione di pausa, e tutto è cominciato funziona meravigliosamente. In effetti, la velocità della risposta della GUI è aumentata.

Quindi se qualcun altro sta tentando di eseguire un processo di "azione, quindi sospensione", questa è un'alternativa molto migliore. Esistono naturalmente applicazioni in cui non è prevista una periodicità, e quindi si dovrebbe cercare qualche altra soluzione.

Problemi correlati