thread_local in global scope



  • Hallo.

    Ich habe folgenden Code-Schnipsel:

    namespace network{
        namespace detail{
            struct ssl_initializer{
                ssl_initializer(){
    ...
                }
    
                ~ssl_initializer(){
    ...
                }
            };
    
            thread_local static const ssl_initializer ssl_init;
        }
    }
    

    Das static ist laut dem Standard redundant. Aber darum gehts hier nicht. Das Problem ist, ich binde den Header ein, wo dieser Code steht, aber es wird keine Instanz von ssl_initializer instanziert. Wenn ich das thread_local weglasse, klappt es dann. Laut Standard steht da aber folgendes:

    The storage for these entities shall last for the duration of the thread in which they are created

    Also, das impliziert für mich, dass die Instanz vom Thread-Beginn aus, bis zum Thread-Ende lebt. Wenn ich das Programm starte, habe ich doch einen Main Thread! Also warum wird die Instanz dann nicht instanziert? Ich habe auch schon folgendes versucht, um mögliche Compiler-Optimierungen auszuschließen:

    thread_local static const volatile ssl_initializer ssl_init;
    

    Keine Chance.
    Wenn ich nun jedoch in die main() -Funktion hingehe, und folgendes in die erste Zeile schreibe:

    (void)network::detail::ssl_init;
    

    Dann klappt es, dann ist die Variable erstellt worden. Aber andersrum nicht. Wie ist das zu verstehen?
    Wo ist mein Fehler?



  • Wie stellst du das fest?



  • manni66 schrieb:

    Wie stellst du das fest?

    Mit dem Debugger.
    Außerdem bekomme ich SSL-Errors, weil die Library nicht initialisiert worden ist.





  • snipps schrieb:

    The storage for these entities shall last for the duration of the thread in which they are created

    Ein paar Zeilen später steht im Standard noch das hier:

    [basic.stc.thread] schrieb:

    A variable with thread storage duration shall be initialized before its first odr-use and, if constructed, shall be destroyed on thread exit.

    Zumindest der Konstruktor-Aufruf des TLS-Objekts darf also auch erst unmittelbar vor der ersten Benutzung passieren, der genaue Zeitpunkt ist undefiniert.

    Den von dir zitierten Satz würde ich so interpretieren, daß nur der Speicher für das Objekt schon ab Thread-Erzeugung alloziert sein muß. Keine Ahnung, ob das dann noch wirklich eine Rolle spielt.


  • Mod

    snipps schrieb:

    The storage for these entities shall last for the duration of the thread in which they are created

    Also, das impliziert für mich, dass die Instanz vom Thread-Beginn aus, bis zum Thread-Ende lebt.

    Es bedeutet nur, dass der Speicherbereich von Beginn an reserviert ist, wann die Initialisierung erfolgt, ergibt sich daraus nicht. Es ist der Implementation überlassen, diese irgendwann vor der ersten ODR-nutzung durchzuführen.
    z.B.

    #include <iostream>
    
    struct beispiel{
        beispiel(){
            std::cout << __PRETTY_FUNCTION__ << std::endl;
        }
    };
    
    thread_local beispiel bsp;
    auto& foo = bsp;
    
    int main(){
    }
    

    wäre möglich, erledigt aber nat. nur die frühzeitige Initialisierung im Hauptthread.



  • Ok, danke euch.
    Dann mach ich halt noch so ne Dummy-Referenz.


Log in to reply