Come si fa a creare una classe che avverte correttamente uno sviluppatore in futuro di aver commesso un errore da qualche parte nella loro implementazione che ha portato a un oggetto che viene decostruito in uno stato che impedisce il rilascio delle sue risorse?
Sfondo:
Recentemente ho aggiornato a Visual Studio 2015 e ho iniziato a ricaricare e compilare il codice per un motore di gioco su cui sto lavorando e ho lanciato una nuova serie di avvertimenti "avviso C4297: '*': funzione presupposta per non generare un'eccezione ma ". Una rapida ricerca ha rivelato una convenzione C ++ che mi era sfuggita e le ragioni alla base di detta convenzione: i distruttori non dovrebbero lanciare eccezioni. Inoltre non posso davvero discutere delle ragioni, ma non sono nemmeno sicuro su come aggirare il problema.
All'interno di OpenGL un contesto contiene sostanzialmente tutte le informazioni di stato per il motore OpenGL. Solo un thread può avere un contesto in un dato momento e ogni thread può avere solo un contesto corrente. All'avvio del motore, crea il contesto e poi lascia il controllo sul contesto e avvia un altro thread che lo preleva e procede a gestire il rendering grafico per il motore. Per gestire tutto ciò, ho creato una classe del motore grafico che utilizza la semantica simile a un mutex per rivendicare e abbandonare il motore grafico e assicurarsi che non si commettano errori che potrebbero portare un giorno a qualcuno a tentare di fare cose con un contesto che non possiede.
Durante la distruzione, il motore grafico e un certo numero di altre classi che fanno affidamento su di esso controllano tutti per assicurarsi che il thread corrente abbia richiesto il motore grafico prima di eseguire le azioni necessarie alla loro distruzione. Se il thread non ha avuto il contesto grafico richiesto, il distruttore stava lanciando. Il mio obiettivo era in realtà quello di fornire una protezione di base contro la classe utilizzata in modo improprio in caso di incidente in futuro, per non rendere il motore grafico sicuro per i thread. Ora ... non sono sicuro del modo migliore per gestirlo.
Ho pensato solo di passare ad un approccio basato su mutex che potrei usare per bloccare l'accesso al contesto grafico fino a quando un thread è stato fatto, forse rendendo la classe del motore grafico pienamente capace di multi-threading (non che io possa capire perché dovresti eseguire il multithreading con un contesto OpenGL, poiché le chiamate necessarie per farlo sono abbastanza costose da vanificare qualsiasi vantaggio tu possa ottenere da ciò che ho capito).
L'opzione più allettante è stata quella di registrare un errore e terminare qualsiasi thread che tenta di utilizzare in modo errato la classe. Sfortunatamente, non riesco a trovare un modo indipendente dal sistema operativo di terminare solo il thread corrente. Se dovessi seguire questa strada, dovrei cercare modi appropriati per OS per terminare i thread attuali.
Inoltre non sono sicuro di non essere eccessivamente paranoico. Forse dovrei solo documentare l'uso corretto della classe e se qualcuno abusa, lasciali e spero che siano in grado di capire perché la loro applicazione non sta facendo quello che dovrebbe. Sono anche preoccupato che io sia il pazzo che abusa un giorno della classe in futuro.