• Pre-main construction order in modules

    From Muttley@Muttley@DastardlyHQ.org to comp.lang.c++ on Sun Mar 30 08:57:54 2025
    From Newsgroup: comp.lang.c++

    I was curious about the order in which objects get constructed in modules before main gets called. It seems with both Clang and gcc its the order in which the modules were linked together to form the runnable binary so if
    the link order was m1.o m2.o then anything in m1 would get constructed first. Vice verca if you switch the order.

    Is this codified in the standard or is it left up to compiler and linker writers to decide how they order this?

    --- Synchronet 3.20c-Linux NewsLink 1.2
  • From Richard Damon@richard@damon-family.org to comp.lang.c++ on Sun Mar 30 07:21:14 2025
    From Newsgroup: comp.lang.c++

    On 3/30/25 4:57 AM, Muttley@DastardlyHQ.org wrote:
    I was curious about the order in which objects get constructed in modules before main gets called. It seems with both Clang and gcc its the order in which the modules were linked together to form the runnable binary so if
    the link order was m1.o m2.o then anything in m1 would get constructed first. Vice verca if you switch the order.

    Is this codified in the standard or is it left up to compiler and linker writers to decide how they order this?


    It is left explicitly undefined in the Standard.
    --- Synchronet 3.20c-Linux NewsLink 1.2
  • From James Kuyper@jameskuyper@alumni.caltech.edu to comp.lang.c++ on Sun Mar 30 10:38:57 2025
    From Newsgroup: comp.lang.c++

    On 3/30/25 4:57 AM, Muttley@DastardlyHQ.org wrote:
    I was curious about the order in which objects get constructed in modules before main gets called. It seems with both Clang and gcc its the order in which the modules were linked together to form the runnable binary so if
    the link order was m1.o m2.o then anything in m1 would get constructed first. Vice verca if you switch the order.

    Is this codified in the standard or is it left up to compiler and linker writers to decide how they order this?

    Section 6.9.3.3 does in fact impose many constraints on the sequence in
    which non-local objects with static storage duration get initialized.
    However, all of the sequence requirements are only between objects
    defined in the same translation unit. Also, it's implementation-defined
    which of those initializations occur before the start of main().
    --- Synchronet 3.20c-Linux NewsLink 1.2
  • From Muttley@Muttley@DastardlyHQ.org to comp.lang.c++ on Sun Mar 30 15:30:34 2025
    From Newsgroup: comp.lang.c++

    On Sun, 30 Mar 2025 10:38:57 -0400
    James Kuyper <jameskuyper@alumni.caltech.edu> wibbled:
    On 3/30/25 4:57 AM, Muttley@DastardlyHQ.org wrote:
    I was curious about the order in which objects get constructed in modules
    before main gets called. It seems with both Clang and gcc its the order in >> which the modules were linked together to form the runnable binary so if
    the link order was m1.o m2.o then anything in m1 would get constructed first.

    Vice verca if you switch the order.

    Is this codified in the standard or is it left up to compiler and linker
    writers to decide how they order this?

    Section 6.9.3.3 does in fact impose many constraints on the sequence in
    which non-local objects with static storage duration get initialized. >However, all of the sequence requirements are only between objects
    defined in the same translation unit. Also, it's implementation-defined
    which of those initializations occur before the start of main().

    Initialising global objects before main is an absolute must otherwise how
    are you expected to use them safely? They're not in the code for decoration.

    --- Synchronet 3.20c-Linux NewsLink 1.2
  • From Mr Flibble@flibble@reddwarf.jmc.corp to comp.lang.c++ on Sun Mar 30 15:59:05 2025
    From Newsgroup: comp.lang.c++

    On Sun, 30 Mar 2025 15:30:34 +0000, Muttley wrote:

    On Sun, 30 Mar 2025 10:38:57 -0400 James Kuyper <jameskuyper@alumni.caltech.edu> wibbled:
    On 3/30/25 4:57 AM, Muttley@DastardlyHQ.org wrote:
    I was curious about the order in which objects get constructed in
    modules before main gets called. It seems with both Clang and gcc its
    the order in which the modules were linked together to form the
    runnable binary so if the link order was m1.o m2.o then anything in m1
    would get constructed first.

    Vice verca if you switch the order.

    Is this codified in the standard or is it left up to compiler and
    linker writers to decide how they order this?

    Section 6.9.3.3 does in fact impose many constraints on the sequence in >>which non-local objects with static storage duration get initialized. >>However, all of the sequence requirements are only between objects
    defined in the same translation unit. Also, it's implementation-defined >>which of those initializations occur before the start of main().

    Initialising global objects before main is an absolute must otherwise
    how are you expected to use them safely? They're not in the code for decoration.

    Global variables are really bad, you are wrong to think it is OK to use
    them.

    /Flibble
    --- Synchronet 3.20c-Linux NewsLink 1.2
  • From Muttley@Muttley@DastardlyHQ.org to comp.lang.c++ on Sun Mar 30 16:09:38 2025
    From Newsgroup: comp.lang.c++

    On Sun, 30 Mar 2025 15:59:05 GMT
    Mr Flibble <flibble@reddwarf.jmc.corp> wibbled:
    On Sun, 30 Mar 2025 15:30:34 +0000, Muttley wrote:

    On Sun, 30 Mar 2025 10:38:57 -0400 James Kuyper
    <jameskuyper@alumni.caltech.edu> wibbled:
    On 3/30/25 4:57 AM, Muttley@DastardlyHQ.org wrote:
    I was curious about the order in which objects get constructed in
    modules before main gets called. It seems with both Clang and gcc its
    the order in which the modules were linked together to form the
    runnable binary so if the link order was m1.o m2.o then anything in m1 >>>> would get constructed first.

    Vice verca if you switch the order.

    Is this codified in the standard or is it left up to compiler and
    linker writers to decide how they order this?

    Section 6.9.3.3 does in fact impose many constraints on the sequence in >>>which non-local objects with static storage duration get initialized. >>>However, all of the sequence requirements are only between objects >>>defined in the same translation unit. Also, it's implementation-defined >>>which of those initializations occur before the start of main().

    Initialising global objects before main is an absolute must otherwise
    how are you expected to use them safely? They're not in the code for
    decoration.

    Global variables are really bad, you are wrong to think it is OK to use >them.

    You're entitled to your opinion. I tend to use a few global objects, often singletons that contain most of the code. Having them global means I don't have to pass a reference into every damn function in one object that requires the other object.

    --- Synchronet 3.20c-Linux NewsLink 1.2
  • From Mr Flibble@flibble@reddwarf.jmc.corp to comp.lang.c++ on Sun Mar 30 16:17:04 2025
    From Newsgroup: comp.lang.c++

    On Sun, 30 Mar 2025 16:09:38 +0000, Muttley wrote:

    On Sun, 30 Mar 2025 15:59:05 GMT Mr Flibble <flibble@reddwarf.jmc.corp> wibbled:
    On Sun, 30 Mar 2025 15:30:34 +0000, Muttley wrote:

    On Sun, 30 Mar 2025 10:38:57 -0400 James Kuyper
    <jameskuyper@alumni.caltech.edu> wibbled:
    On 3/30/25 4:57 AM, Muttley@DastardlyHQ.org wrote:
    I was curious about the order in which objects get constructed in
    modules before main gets called. It seems with both Clang and gcc
    its the order in which the modules were linked together to form the
    runnable binary so if the link order was m1.o m2.o then anything in
    m1 would get constructed first.

    Vice verca if you switch the order.

    Is this codified in the standard or is it left up to compiler and
    linker writers to decide how they order this?

    Section 6.9.3.3 does in fact impose many constraints on the sequence
    in which non-local objects with static storage duration get >>>>initialized. However, all of the sequence requirements are only
    between objects defined in the same translation unit. Also, it's >>>>implementation-defined which of those initializations occur before the >>>>start of main().

    Initialising global objects before main is an absolute must otherwise
    how are you expected to use them safely? They're not in the code for
    decoration.

    Global variables are really bad, you are wrong to think it is OK to use >>them.

    You're entitled to your opinion. I tend to use a few global objects,
    often singletons that contain most of the code. Having them global means
    I don't have to pass a reference into every damn function in one object
    that requires the other object.

    Singletons don't have to be global objects if you use the Meyers Singleton pattern.

    /Flibble
    --- Synchronet 3.20c-Linux NewsLink 1.2
  • From Mr Flibble@flibble@reddwarf.jmc.corp to comp.lang.c++ on Sun Mar 30 16:22:48 2025
    From Newsgroup: comp.lang.c++

    On Sun, 30 Mar 2025 07:21:14 -0400, Richard Damon wrote:

    On 3/30/25 4:57 AM, Muttley@DastardlyHQ.org wrote:
    I was curious about the order in which objects get constructed in
    modules before main gets called. It seems with both Clang and gcc its
    the order in which the modules were linked together to form the
    runnable binary so if the link order was m1.o m2.o then anything in m1
    would get constructed first.
    Vice verca if you switch the order.

    Is this codified in the standard or is it left up to compiler and
    linker writers to decide how they order this?


    It is left explicitly undefined in the Standard.

    No, it is *unspecified* not *undefined*.

    /Flibble
    --- Synchronet 3.20c-Linux NewsLink 1.2
  • From Muttley@Muttley@DastardlyHQ.org to comp.lang.c++ on Sun Mar 30 16:23:33 2025
    From Newsgroup: comp.lang.c++

    On Sun, 30 Mar 2025 16:17:04 GMT
    Mr Flibble <flibble@reddwarf.jmc.corp> wibbled:
    On Sun, 30 Mar 2025 16:09:38 +0000, Muttley wrote:
    You're entitled to your opinion. I tend to use a few global objects,
    often singletons that contain most of the code. Having them global means
    I don't have to pass a reference into every damn function in one object
    that requires the other object.

    Singletons don't have to be global objects if you use the Meyers Singleton >pattern.

    Never heard of it and don't particularly care. I write code to solve problems, not to subscribe to whatever structural paradigm is flavour of the month.

    --- Synchronet 3.20c-Linux NewsLink 1.2
  • From Mr Flibble@flibble@reddwarf.jmc.corp to comp.lang.c++ on Sun Mar 30 16:26:32 2025
    From Newsgroup: comp.lang.c++

    On Sun, 30 Mar 2025 16:23:33 +0000, Muttley wrote:

    On Sun, 30 Mar 2025 16:17:04 GMT Mr Flibble <flibble@reddwarf.jmc.corp> wibbled:
    On Sun, 30 Mar 2025 16:09:38 +0000, Muttley wrote:
    You're entitled to your opinion. I tend to use a few global objects,
    often singletons that contain most of the code. Having them global
    means I don't have to pass a reference into every damn function in one
    object that requires the other object.

    Singletons don't have to be global objects if you use the Meyers
    Singleton pattern.

    Never heard of it and don't particularly care. I write code to solve problems,
    not to subscribe to whatever structural paradigm is flavour of the
    month.

    The Meyers Singleton pattern has been around for decades, it certainly is
    not "flavour of the month" and your ignorance of it is quite noobish - it
    is the standard way of avoiding the global variable initialisation order fiasco.

    /Flibble
    --- Synchronet 3.20c-Linux NewsLink 1.2
  • From Bonita Montero@Bonita.Montero@gmail.com to comp.lang.c++ on Sun Mar 30 19:56:27 2025
    From Newsgroup: comp.lang.c++

    Am 30.03.2025 um 18:22 schrieb Mr Flibble:
    On Sun, 30 Mar 2025 07:21:14 -0400, Richard Damon wrote:

    On 3/30/25 4:57 AM, Muttley@DastardlyHQ.org wrote:
    I was curious about the order in which objects get constructed in
    modules before main gets called. It seems with both Clang and gcc its
    the order in which the modules were linked together to form the
    runnable binary so if the link order was m1.o m2.o then anything in m1
    would get constructed first.
    Vice verca if you switch the order.

    Is this codified in the standard or is it left up to compiler and
    linker writers to decide how they order this?


    It is left explicitly undefined in the Standard.

    No, it is *unspecified* not *undefined*.

    LOL - idiot
    --- Synchronet 3.20c-Linux NewsLink 1.2
  • From Bonita Montero@Bonita.Montero@gmail.com to comp.lang.c++ on Sun Mar 30 19:58:51 2025
    From Newsgroup: comp.lang.c++

    Am 30.03.2025 um 18:17 schrieb Mr Flibble:

    Singletons don't have to be global objects if you use the Meyers Singleton pattern.

    That nearly doesn't make a difference, everything is still in the
    BSS-segment.

    --- Synchronet 3.20c-Linux NewsLink 1.2
  • From Mr Flibble@flibble@reddwarf.jmc.corp to comp.lang.c++ on Sun Mar 30 18:00:58 2025
    From Newsgroup: comp.lang.c++

    On Sun, 30 Mar 2025 19:56:27 +0200, Bonita Montero wrote:

    Am 30.03.2025 um 18:22 schrieb Mr Flibble:
    On Sun, 30 Mar 2025 07:21:14 -0400, Richard Damon wrote:

    On 3/30/25 4:57 AM, Muttley@DastardlyHQ.org wrote:
    I was curious about the order in which objects get constructed in
    modules before main gets called. It seems with both Clang and gcc its
    the order in which the modules were linked together to form the
    runnable binary so if the link order was m1.o m2.o then anything in
    m1 would get constructed first.
    Vice verca if you switch the order.

    Is this codified in the standard or is it left up to compiler and
    linker writers to decide how they order this?


    It is left explicitly undefined in the Standard.

    No, it is *unspecified* not *undefined*.

    LOL - idiot

    Troll.

    /Flibble
    --- Synchronet 3.20c-Linux NewsLink 1.2
  • From Mr Flibble@flibble@reddwarf.jmc.corp to comp.lang.c++ on Sun Mar 30 18:02:41 2025
    From Newsgroup: comp.lang.c++

    On Sun, 30 Mar 2025 19:58:51 +0200, Bonita Montero wrote:

    Am 30.03.2025 um 18:17 schrieb Mr Flibble:

    Singletons don't have to be global objects if you use the Meyers
    Singleton pattern.

    That nearly doesn't make a difference, everything is still in the BSS-segment.

    It makes all the difference as it is the standard way to avoid the initialisation order fiasco (the subject of this thread) but I wouldn't
    expect an ignorant troll such as yourself to know this.

    /Flibble
    --- Synchronet 3.20c-Linux NewsLink 1.2
  • From Bonita Montero@Bonita.Montero@gmail.com to comp.lang.c++ on Sun Mar 30 20:05:51 2025
    From Newsgroup: comp.lang.c++

    Am 30.03.2025 um 20:02 schrieb Mr Flibble:

    It makes all the difference as it is the standard way to avoid the initialisation order fiasco (the subject of this thread) but I wouldn't expect an ignorant troll such as yourself to know this.

    It doesn't help to prevent the static initialization order
    fiasco since the initialization order of static members is
    also not guaranteed across translation units.

    --- Synchronet 3.20c-Linux NewsLink 1.2
  • From Mr Flibble@flibble@reddwarf.jmc.corp to comp.lang.c++ on Sun Mar 30 18:07:17 2025
    From Newsgroup: comp.lang.c++

    On Sun, 30 Mar 2025 20:05:51 +0200, Bonita Montero wrote:

    Am 30.03.2025 um 20:02 schrieb Mr Flibble:

    It makes all the difference as it is the standard way to avoid the
    initialisation order fiasco (the subject of this thread) but I wouldn't
    expect an ignorant troll such as yourself to know this.

    It doesn't help to prevent the static initialization order fiasco since
    the initialization order of static members is also not guaranteed across translation units.

    The Meyers Singleton does NOT involve static members; I suggest you go
    read up on what it actually involves rather than continue to make a fool
    of yourself.

    /Flibble
    --- Synchronet 3.20c-Linux NewsLink 1.2
  • From Bonita Montero@Bonita.Montero@gmail.com to comp.lang.c++ on Sun Mar 30 20:08:51 2025
    From Newsgroup: comp.lang.c++

    Am 30.03.2025 um 20:07 schrieb Mr Flibble:
    On Sun, 30 Mar 2025 20:05:51 +0200, Bonita Montero wrote:

    Am 30.03.2025 um 20:02 schrieb Mr Flibble:

    It makes all the difference as it is the standard way to avoid the
    initialisation order fiasco (the subject of this thread) but I wouldn't
    expect an ignorant troll such as yourself to know this.

    It doesn't help to prevent the static initialization order fiasco since
    the initialization order of static members is also not guaranteed across
    translation units.

    The Meyers Singleton does NOT involve static members; I suggest you go
    read up on what it actually involves rather than continue to make a fool
    of yourself.

    /Flibble

    What you mean is right, but that's not Meyers singleton: https://laristra.github.io/flecsi/src/developer-guide/patterns/meyers_singleton.html

    --- Synchronet 3.20c-Linux NewsLink 1.2
  • From Mr Flibble@flibble@reddwarf.jmc.corp to comp.lang.c++ on Sun Mar 30 18:11:53 2025
    From Newsgroup: comp.lang.c++

    On Sun, 30 Mar 2025 20:08:51 +0200, Bonita Montero wrote:

    Am 30.03.2025 um 20:07 schrieb Mr Flibble:
    On Sun, 30 Mar 2025 20:05:51 +0200, Bonita Montero wrote:

    Am 30.03.2025 um 20:02 schrieb Mr Flibble:

    It makes all the difference as it is the standard way to avoid the
    initialisation order fiasco (the subject of this thread) but I
    wouldn't expect an ignorant troll such as yourself to know this.

    It doesn't help to prevent the static initialization order fiasco
    since the initialization order of static members is also not
    guaranteed across translation units.

    The Meyers Singleton does NOT involve static members; I suggest you go
    read up on what it actually involves rather than continue to make a
    fool of yourself.

    /Flibble

    What you mean is right, but that's not Meyers singleton: https://laristra.github.io/flecsi/src/developer-guide/patterns/
    meyers_singleton.html

    No what I meant was the Meyers Singleton which involves static local
    variables NOT static member variables which is what YOU thought it meant.

    Just admit you made a fucking mistake, dear.

    /Flibble
    --- Synchronet 3.20c-Linux NewsLink 1.2
  • From Bonita Montero@Bonita.Montero@gmail.com to comp.lang.c++ on Sun Mar 30 20:17:23 2025
    From Newsgroup: comp.lang.c++

    Am 30.03.2025 um 20:11 schrieb Mr Flibble:

    No what I meant was the Meyers Singleton which involves static local variables NOT static member variables which is what YOU thought it meant.

    static local variables need double-checked locked initialization.
    That's rather slow to just get a reference.

    --- Synchronet 3.20c-Linux NewsLink 1.2
  • From Mr Flibble@flibble@reddwarf.jmc.corp to comp.lang.c++ on Sun Mar 30 18:20:19 2025
    From Newsgroup: comp.lang.c++

    On Sun, 30 Mar 2025 20:17:23 +0200, Bonita Montero wrote:

    Am 30.03.2025 um 20:11 schrieb Mr Flibble:

    No what I meant was the Meyers Singleton which involves static local
    variables NOT static member variables which is what YOU thought it
    meant.

    static local variables need double-checked locked initialization.
    That's rather slow to just get a reference.

    But that is nevertheless what the Meyers Singleton involves. Static local initialisation has been threadsafe since C++11 and if performance is a
    concern then you can always cache the result in a reference downstream in
    any hot path that needs it.

    /Flibble
    --- Synchronet 3.20c-Linux NewsLink 1.2
  • From Richard Damon@richard@damon-family.org to comp.lang.c++ on Sun Mar 30 15:01:24 2025
    From Newsgroup: comp.lang.c++

    On 3/30/25 2:20 PM, Mr Flibble wrote:
    On Sun, 30 Mar 2025 20:17:23 +0200, Bonita Montero wrote:

    Am 30.03.2025 um 20:11 schrieb Mr Flibble:

    No what I meant was the Meyers Singleton which involves static local
    variables NOT static member variables which is what YOU thought it
    meant.

    static local variables need double-checked locked initialization.
    That's rather slow to just get a reference.

    But that is nevertheless what the Meyers Singleton involves. Static local initialisation has been threadsafe since C++11 and if performance is a concern then you can always cache the result in a reference downstream in
    any hot path that needs it.

    /Flibble

    Yes, my typical implementation is a global pointer (or static member of
    a class, not significantly different in function), which code can do a
    check for zero, if it sees it zero calls the generator function which
    sets the variable to the address of the local static variable.

    The check for zero needs no guard, as redundant calls to the function
    are harmless, costing only the extra interlocking operation, and will be limited to code that reaches that pointer within the time frame needed
    to initialize the object.
    --- Synchronet 3.20c-Linux NewsLink 1.2
  • From Richard Damon@richard@damon-family.org to comp.lang.c++ on Sun Mar 30 15:05:08 2025
    From Newsgroup: comp.lang.c++

    On 3/30/25 12:23 PM, Muttley@DastardlyHQ.org wrote:
    On Sun, 30 Mar 2025 16:17:04 GMT
    Mr Flibble <flibble@reddwarf.jmc.corp> wibbled:
    On Sun, 30 Mar 2025 16:09:38 +0000, Muttley wrote:
    You're entitled to your opinion. I tend to use a few global objects,
    often singletons that contain most of the code. Having them global means >>> I don't have to pass a reference into every damn function in one object
    that requires the other object.

    Singletons don't have to be global objects if you use the Meyers Singleton >> pattern.

    Never heard of it and don't particularly care. I write code to solve problems,
    not to subscribe to whatever structural paradigm is flavour of the month.


    But it is a solution to the problem, so worth looking at.


    --- Synchronet 3.20c-Linux NewsLink 1.2
  • From Bonita Montero@Bonita.Montero@gmail.com to comp.lang.c++ on Sun Mar 30 22:15:03 2025
    From Newsgroup: comp.lang.c++

    Am 30.03.2025 um 20:20 schrieb Mr Flibble:

    But that is nevertheless what the Meyers Singleton involves. Static local initialisation has been threadsafe since C++11 and if performance is a concern then you can always cache the result in a reference downstream in
    any hot path that needs it.

    With current implemention all C++ runtimes govern all station initia- lizations through a single mutex. That hurts if you have a constructor
    that takes longer, maybe because of a socket-connection which the code
    waits for.

    --- Synchronet 3.20c-Linux NewsLink 1.2
  • From Chris M. Thomasson@chris.m.thomasson.1@gmail.com to comp.lang.c++ on Sun Mar 30 13:57:47 2025
    From Newsgroup: comp.lang.c++

    On 3/30/2025 1:15 PM, Bonita Montero wrote:
    Am 30.03.2025 um 20:20 schrieb Mr Flibble:

    But that is nevertheless what the Meyers Singleton involves.  Static
    local
    initialisation has been threadsafe since C++11 and if performance is a
    concern then you can always cache the result in a reference downstream in
    any hot path that needs it.

    With current implemention all C++ runtimes govern all station  initia- lizations through a single mutex. That hurts if you have a constructor
    that takes longer, maybe because of a socket-connection which the code
    waits for.


    Creating threads, socket-connections before main is a bad idea...? ;^o
    --- Synchronet 3.20c-Linux NewsLink 1.2
  • From Bonita Montero@Bonita.Montero@gmail.com to comp.lang.c++ on Mon Mar 31 07:37:12 2025
    From Newsgroup: comp.lang.c++

    Am 30.03.2025 um 22:57 schrieb Chris M. Thomasson:

    Creating threads, socket-connections before main is a bad idea...? ;^o

    Why ?

    --- Synchronet 3.20c-Linux NewsLink 1.2
  • From Muttley@Muttley@DastardlyHQ.org to comp.lang.c++ on Mon Mar 31 08:20:53 2025
    From Newsgroup: comp.lang.c++

    On Sun, 30 Mar 2025 16:26:32 GMT
    Mr Flibble <flibble@reddwarf.jmc.corp> wibbled:
    On Sun, 30 Mar 2025 16:23:33 +0000, Muttley wrote:

    On Sun, 30 Mar 2025 16:17:04 GMT Mr Flibble <flibble@reddwarf.jmc.corp>
    wibbled:
    On Sun, 30 Mar 2025 16:09:38 +0000, Muttley wrote:
    You're entitled to your opinion. I tend to use a few global objects,
    often singletons that contain most of the code. Having them global
    means I don't have to pass a reference into every damn function in one >>>> object that requires the other object.

    Singletons don't have to be global objects if you use the Meyers >>>Singleton pattern.

    Never heard of it and don't particularly care. I write code to solve
    problems,
    not to subscribe to whatever structural paradigm is flavour of the
    month.

    The Meyers Singleton pattern has been around for decades, it certainly is >not "flavour of the month" and your ignorance of it is quite noobish - it
    is the standard way of avoiding the global variable initialisation order >fiasco.

    Had a look. Woooo, it uses statics, how cutting edge. Done that myself plenty of times without knowing it had a special name (kind of an obvious alternative approach but hey) but now I feel blessed that I can go around saying "Meyer Pattern" and have others look at me in amazement at my knowledge.

    --- Synchronet 3.20c-Linux NewsLink 1.2
  • From Bonita Montero@Bonita.Montero@gmail.com to comp.lang.c++ on Mon Mar 31 10:46:57 2025
    From Newsgroup: comp.lang.c++

    Am 30.03.2025 um 18:26 schrieb Mr Flibble:

    The Meyers Singleton pattern has been around for decades, ..

    Decades are multiples of a decade, i.e. >= 20 years. But Meyer's
    singleton is possible since C++11, where static local initializations
    are thread-safe, that's 14 years ago.

    --- Synchronet 3.20c-Linux NewsLink 1.2
  • From Paavo Helde@eesnimi@osa.pri.ee to comp.lang.c++ on Mon Mar 31 11:49:23 2025
    From Newsgroup: comp.lang.c++

    On 30.03.2025 18:30, Muttley@DastardlyHQ.org wrote:
    On Sun, 30 Mar 2025 10:38:57 -0400
    James Kuyper <jameskuyper@alumni.caltech.edu> wibbled:
    Section 6.9.3.3 does in fact impose many constraints on the sequence in
    which non-local objects with static storage duration get initialized.
    However, all of the sequence requirements are only between objects
    defined in the same translation unit. Also, it's implementation-defined
    which of those initializations occur before the start of main().

    Initialising global objects before main is an absolute must otherwise how
    are you expected to use them safely? They're not in the code for decoration.

    Initializing global objects before main is not possible with
    demand-loaded dynamically loaded libraries.

    IIRC this clause in the standard (that it's implementation-defined which static initializations occur before the start of main()) was introduced
    in C++11 when they got around to recognize the existence of shared
    libraries. To make the global static variables usable there is now
    another clause ([basic.start.dynamic]):

    "If [initialization] is deferred, it strongly happens before any non-initialization odr-use of any non-inline function or non-inline
    variable defined in the same translation unit as the variable to be initialized."

    In practice, it means it is a bad idea to expose global static variables directly from a TU or from a shared library, because it is tricky to
    tell when and if the exported address becomes safe to use, and this may
    change on a whim by the compiler version and optimization levels, etc. I
    think I have seen a compiler optimizing away the whole TU when it only contained static data and no functions with external linkage.

    --- Synchronet 3.20c-Linux NewsLink 1.2
  • From Paavo Helde@eesnimi@osa.pri.ee to comp.lang.c++ on Mon Mar 31 11:56:35 2025
    From Newsgroup: comp.lang.c++

    On 31.03.2025 11:46, Bonita Montero wrote:
    Am 30.03.2025 um 18:26 schrieb Mr Flibble:

    The Meyers Singleton pattern has been around for decades, ..

    Decades are multiples of a decade, i.e. >= 20 years. But Meyer's
    singleton is possible since C++11, where static local initializations
    are thread-safe, that's 14 years ago.

    Before C++11 one had to just add their own synchronization for thread
    safety (assuming multi-threaded access was needed, which was not so
    often in the past).

    C++11 just made coding of a Meyer's singleton easier, that's all.

    --- Synchronet 3.20c-Linux NewsLink 1.2
  • From Muttley@Muttley@DastardlyHQ.org to comp.lang.c++ on Mon Mar 31 09:09:01 2025
    From Newsgroup: comp.lang.c++

    On Mon, 31 Mar 2025 11:49:23 +0300
    Paavo Helde <eesnimi@osa.pri.ee> wibbled:
    On 30.03.2025 18:30, Muttley@DastardlyHQ.org wrote:
    On Sun, 30 Mar 2025 10:38:57 -0400
    James Kuyper <jameskuyper@alumni.caltech.edu> wibbled:
    Section 6.9.3.3 does in fact impose many constraints on the sequence in
    which non-local objects with static storage duration get initialized.
    However, all of the sequence requirements are only between objects
    defined in the same translation unit. Also, it's implementation-defined
    which of those initializations occur before the start of main().

    Initialising global objects before main is an absolute must otherwise how
    are you expected to use them safely? They're not in the code for decoration.

    Initializing global objects before main is not possible with
    demand-loaded dynamically loaded libraries.

    Well obviously, but thats not what I'm talking about. If myobj() is constructed in a linked .o file I expect it to be available and ready in main(). If not then when? Or are you just supposed to guess or hope for the best?

    --- Synchronet 3.20c-Linux NewsLink 1.2
  • From Bonita Montero@Bonita.Montero@gmail.com to comp.lang.c++ on Mon Mar 31 11:11:58 2025
    From Newsgroup: comp.lang.c++

    Am 31.03.2025 um 10:56 schrieb Paavo Helde:

    Before C++11 one had to just add their own synchronization for thread
    safety (assuming multi-threaded access was needed, which was not so
    often in the past).
    C++11 just made coding of a Meyer's singleton easier, that's all.

    That's not that easy since it is undefined when a static local variable
    is initialized before C++11. You'd have to wrap it in a union and leave
    only member which is the object uninitialized. That's possible, but
    that's not Meyer's singleton.

    --- Synchronet 3.20c-Linux NewsLink 1.2
  • From Richard Damon@richard@damon-family.org to comp.lang.c++ on Mon Mar 31 07:22:42 2025
    From Newsgroup: comp.lang.c++

    On 3/31/25 4:46 AM, Bonita Montero wrote:
    Am 30.03.2025 um 18:26 schrieb Mr Flibble:

    The Meyers Singleton pattern has been around for decades, ..

    Decades are multiples of a decade, i.e. >= 20 years. But Meyer's
    singleton is possible since C++11, where static local initializations
    are thread-safe, that's 14 years ago.


    Prior to C++11, it was a valid method for the initialization problem for single threaded C++ code, which really was all that had C++ standard
    defined behavior.

    I seem to remember the technique being used in pre-standard C++ in the
    library to get around the initialization order problem.
    --- Synchronet 3.20c-Linux NewsLink 1.2
  • From Richard Damon@richard@damon-family.org to comp.lang.c++ on Mon Mar 31 07:25:49 2025
    From Newsgroup: comp.lang.c++

    On 3/31/25 5:11 AM, Bonita Montero wrote:
    Am 31.03.2025 um 10:56 schrieb Paavo Helde:

    Before C++11 one had to just add their own synchronization for thread
    safety (assuming multi-threaded access was needed, which was not so
    often in the past).
    C++11 just made coding of a Meyer's singleton easier, that's all.

    That's not that easy since it is undefined when a static local variable
    is initialized before C++11. You'd have to wrap it in a union and leave
    only member which is the object uninitialized. That's possible, but
    that's not Meyer's singleton.


    No, I seem to remember that static FUNCTION LOCAL variables have always
    been initialize at the moment the function is first entered, after all,
    the constructor can take arguments that might not be known till then, so
    it can't be constructed before, and it needs to be constructed before
    you pass the decleration.

    As I said elsewhere, I seem to rememeber the standard runtime used this
    sort of trick to enforce object creation order.
    --- Synchronet 3.20c-Linux NewsLink 1.2
  • From Paavo Helde@eesnimi@osa.pri.ee to comp.lang.c++ on Mon Mar 31 15:26:30 2025
    From Newsgroup: comp.lang.c++

    On 31.03.2025 12:11, Bonita Montero wrote:
    Am 31.03.2025 um 10:56 schrieb Paavo Helde:

    Before C++11 one had to just add their own synchronization for thread
    safety (assuming multi-threaded access was needed, which was not so
    often in the past).
    C++11 just made coding of a Meyer's singleton easier, that's all.

    That's not that easy since it is undefined when a static local variable
    is initialized before C++11. You'd have to wrap it in a union and leave
    only member which is the object uninitialized. That's possible, but
    that's not Meyer's singleton.

    Thread synchronization has been possible since the introduction of
    threads. Otherwise they would not have been usable.

    An example of pre-C++11 thread-safe Meyer singleton:

    std::map<std::string, std::string>& GetGlobalMap() {

    // No dynamic initialization, so this is safe:
    static std::map<std::string, std::string>* pGlobal = NULL;

    // No dynamic initialization, so this is safe as well:
    static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

    // Initialize the global static if not yet initialized.
    pthread_mutex_lock(&mutex);
    if (!pGlobal) {
    pGlobal = new std::map<std::string, std::string>();
    }
    pthread_mutex_unlock(&mutex);
    return *pGlobal;
    }


    --- Synchronet 3.20c-Linux NewsLink 1.2
  • From Bonita Montero@Bonita.Montero@gmail.com to comp.lang.c++ on Mon Mar 31 14:32:14 2025
    From Newsgroup: comp.lang.c++

    Am 31.03.2025 um 14:26 schrieb Paavo Helde:

    An example of pre-C++11 thread-safe Meyer singleton:

    std::map<std::string, std::string>& GetGlobalMap() {

        // No dynamic initialization, so this is safe:
        static std::map<std::string, std::string>* pGlobal = NULL;

        // No dynamic initialization, so this is safe as well:
        static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

        // Initialize the global static if not yet initialized.
        pthread_mutex_lock(&mutex);
        if (!pGlobal) {
            pGlobal = new std::map<std::string, std::string>();
        }
        pthread_mutex_unlock(&mutex);
        return *pGlobal;
    }

    That's rather slow. Double-checked locking as implemented for
    all static locals with current runtimes is much more efficient.
    --- Synchronet 3.20c-Linux NewsLink 1.2
  • From Paavo Helde@eesnimi@osa.pri.ee to comp.lang.c++ on Mon Mar 31 15:39:53 2025
    From Newsgroup: comp.lang.c++

    On 31.03.2025 12:09, Muttley@DastardlyHQ.org wrote:
    On Mon, 31 Mar 2025 11:49:23 +0300
    Paavo Helde <eesnimi@osa.pri.ee> wibbled:
    On 30.03.2025 18:30, Muttley@DastardlyHQ.org wrote:
    On Sun, 30 Mar 2025 10:38:57 -0400
    James Kuyper <jameskuyper@alumni.caltech.edu> wibbled:
    Section 6.9.3.3 does in fact impose many constraints on the sequence in >>>> which non-local objects with static storage duration get initialized.
    However, all of the sequence requirements are only between objects
    defined in the same translation unit. Also, it's implementation-defined >>>> which of those initializations occur before the start of main().

    Initialising global objects before main is an absolute must otherwise how >>> are you expected to use them safely? They're not in the code for decoration.

    Initializing global objects before main is not possible with
    demand-loaded dynamically loaded libraries.

    Well obviously, but thats not what I'm talking about. If myobj() is constructed
    in a linked .o file I expect it to be available and ready in main(). If not then when? Or are you just supposed to guess or hope for the best?

    The standard does not talk specifically about dynamic libraries, so the
    same rules apply for the main program. This means the same quote you
    snipped is relevant to your myobj as well:

    "If [initialization] is deferred, it strongly happens before any non-initialization odr-use of any non-inline function or non-inline
    variable defined in the same translation unit as the variable to be initialized."

    The keyword here is "non-initialization use". If you access your myobj
    from main() it would be a non-initialization use, which is guaranteed to trigger the needed initialization if needed, so everything will work fine.

    --- Synchronet 3.20c-Linux NewsLink 1.2
  • From Paavo Helde@eesnimi@osa.pri.ee to comp.lang.c++ on Mon Mar 31 15:44:48 2025
    From Newsgroup: comp.lang.c++

    On 31.03.2025 15:32, Bonita Montero wrote:
    Am 31.03.2025 um 14:26 schrieb Paavo Helde:

    An example of pre-C++11 thread-safe Meyer singleton:

    std::map<std::string, std::string>& GetGlobalMap() {

         // No dynamic initialization, so this is safe:
         static std::map<std::string, std::string>* pGlobal = NULL;

         // No dynamic initialization, so this is safe as well:
         static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

         // Initialize the global static if not yet initialized.
         pthread_mutex_lock(&mutex);
         if (!pGlobal) {
             pGlobal = new std::map<std::string, std::string>();
         }
         pthread_mutex_unlock(&mutex);
         return *pGlobal;
    }

    That's rather slow. Double-checked locking as implemented for
    all static locals with current runtimes is much more efficient.

    Sure. That's why one should not call such a function from inside a
    million iteration loop. But it would often be possible to call it before
    the loop and use the returned reference million times inside the loop.

    --- Synchronet 3.20c-Linux NewsLink 1.2
  • From Muttley@Muttley@DastardlyHQ.org to comp.lang.c++ on Mon Mar 31 14:01:09 2025
    From Newsgroup: comp.lang.c++

    On Mon, 31 Mar 2025 15:39:53 +0300
    Paavo Helde <eesnimi@osa.pri.ee> wibbled:
    On 31.03.2025 12:09, Muttley@DastardlyHQ.org wrote:
    "If [initialization] is deferred, it strongly happens before any >non-initialization odr-use of any non-inline function or non-inline
    variable defined in the same translation unit as the variable to be >initialized."

    Who writes this stuff? Its borderline gibberish.

    The keyword here is "non-initialization use". If you access your myobj
    from main() it would be a non-initialization use, which is guaranteed to >trigger the needed initialization if needed, so everything will work fine.

    Not necessarily. What it the constructor of one object opened a network
    socket but that object wasn't touched again until something else in the
    program tried to loop back to that socket?

    --- Synchronet 3.20c-Linux NewsLink 1.2
  • From scott@scott@slp53.sl.home (Scott Lurndal) to comp.lang.c++ on Mon Mar 31 14:15:35 2025
    From Newsgroup: comp.lang.c++

    Paavo Helde <eesnimi@osa.pri.ee> writes:
    On 30.03.2025 18:30, Muttley@DastardlyHQ.org wrote:
    On Sun, 30 Mar 2025 10:38:57 -0400
    James Kuyper <jameskuyper@alumni.caltech.edu> wibbled:
    Section 6.9.3.3 does in fact impose many constraints on the sequence in
    which non-local objects with static storage duration get initialized.
    However, all of the sequence requirements are only between objects
    defined in the same translation unit. Also, it's implementation-defined
    which of those initializations occur before the start of main().

    Initialising global objects before main is an absolute must otherwise how
    are you expected to use them safely? They're not in the code for decoration.

    Initializing global objects before main is not possible with
    demand-loaded dynamically loaded libraries.

    Which are initialized as the library is loaded. Much the
    same effect as implementing before main.

    --- Synchronet 3.20c-Linux NewsLink 1.2
  • From James Kuyper@jameskuyper@alumni.caltech.edu to comp.lang.c++ on Mon Mar 31 10:29:39 2025
    From Newsgroup: comp.lang.c++

    On 30.03.2025 18:30, Muttley@DastardlyHQ.org wrote:
    On Sun, 30 Mar 2025 10:38:57 -0400
    James Kuyper <jameskuyper@alumni.caltech.edu> wibbled:
    Section 6.9.3.3 does in fact impose many constraints on the sequence in
    which non-local objects with static storage duration get initialized.
    However, all of the sequence requirements are only between objects
    defined in the same translation unit. Also, it's implementation-defined
    which of those initializations occur before the start of main().

    Initialising global objects before main is an absolute must otherwise how
    are you expected to use them safely? They're not in the code for decoration.

    "If it [initialization] is deferred, it strongly happens before any non-initialization odr-use of any non-inline function or non-inline
    variable defined in the same translation unit as the variable to be initialized.47 It is implementation-defined in which threads and at
    which points in the program such deferred dynamic initialization
    occurs." (6.9.3.3p5).

    Therefore, what you need to do is make sure that the object has been initialized is to access it from a function defined in the same
    translation unit.
    --- Synchronet 3.20c-Linux NewsLink 1.2
  • From Bonita Montero@Bonita.Montero@gmail.com to comp.lang.c++ on Mon Mar 31 16:47:05 2025
    From Newsgroup: comp.lang.c++

    Am 31.03.2025 um 16:15 schrieb Scott Lurndal:

    Which are initialized as the library is loaded. Much the
    same effect as implementing before main.

    It looks somewhat strange to me to get the address of an export which
    is not a function with dladdr or GetProcAddress. I think the usual case
    would be that the dynamic library uses global objects for its own use.

    --- Synchronet 3.20c-Linux NewsLink 1.2
  • From Paavo Helde@eesnimi@osa.pri.ee to comp.lang.c++ on Mon Mar 31 20:06:08 2025
    From Newsgroup: comp.lang.c++

    On 31.03.2025 17:01, Muttley@DastardlyHQ.org wrote:
    On Mon, 31 Mar 2025 15:39:53 +0300
    Paavo Helde <eesnimi@osa.pri.ee> wibbled:
    On 31.03.2025 12:09, Muttley@DastardlyHQ.org wrote:
    "If [initialization] is deferred, it strongly happens before any
    non-initialization odr-use of any non-inline function or non-inline
    variable defined in the same translation unit as the variable to be
    initialized."

    Who writes this stuff? Its borderline gibberish.

    The keyword here is "non-initialization use". If you access your myobj >>from main() it would be a non-initialization use, which is guaranteed to
    trigger the needed initialization if needed, so everything will work fine.

    Not necessarily. What it the constructor of one object opened a network socket but that object wasn't touched again until something else in the program tried to loop back to that socket?

    The constructor of the object is not guaranteed to run if the object nor anything else in its TU is not accessed from outside. It means the
    socket might not be opened.

    And no, trying to access the object via a network socket does not
    qualify as "non-initialization odr-use" of the object, as far as the C++ standard is concerned ;-)


    --- Synchronet 3.20c-Linux NewsLink 1.2
  • From James Kuyper@jameskuyper@alumni.caltech.edu to comp.lang.c++ on Mon Mar 31 19:42:48 2025
    From Newsgroup: comp.lang.c++

    On 31.03.2025 17:01, Muttley@DastardlyHQ.org wrote:
    On Mon, 31 Mar 2025 15:39:53 +0300
    Paavo Helde <eesnimi@osa.pri.ee> wibbled:
    On 31.03.2025 12:09, Muttley@DastardlyHQ.org wrote:
    "If [initialization] is deferred, it strongly happens before any
    non-initialization odr-use of any non-inline function or non-inline
    variable defined in the same translation unit as the variable to be
    initialized."

    Who writes this stuff? Its borderline gibberish.

    Keep in mind that the key thing that makes this seem like gibberish is
    the use of precisely defined technical jargon, which is used for the
    same reason that jargon is used in many other contexts: it has a more
    precisely specified meaning than more informal wording would have had.

    Key pieces of jargon: "strongly happens before", "non-initialization", "odr-use", "translation unit". If there's anything you don't understand
    about that clause, it's probably based in unfamiliarity with such phrases.



    --- Synchronet 3.20c-Linux NewsLink 1.2
  • From Jakob Bohm@egenagwemdimtapsar@jbohm.dk to comp.lang.c++ on Tue Apr 1 06:06:11 2025
    From Newsgroup: comp.lang.c++

    On 2025-03-31 14:32, Bonita Montero wrote:
    Am 31.03.2025 um 14:26 schrieb Paavo Helde:

    An example of pre-C++11 thread-safe Meyer singleton:

    std::map<std::string, std::string>& GetGlobalMap() {

         // No dynamic initialization, so this is safe:
         static std::map<std::string, std::string>* pGlobal = NULL;

         // No dynamic initialization, so this is safe as well:
         static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

         // Initialize the global static if not yet initialized.
         pthread_mutex_lock(&mutex);
         if (!pGlobal) {
             pGlobal = new std::map<std::string, std::string>();
         }
         pthread_mutex_unlock(&mutex);
         return *pGlobal;
    }

    That's rather slow. Double-checked locking as implemented for
    all static locals with current runtimes is much more efficient.

    Artificial locking around ALL static locals as implemented by some
    modern compilers is highly wasteful as in most code, the code
    structure already ensures a single thread will be the first to
    execute that initialization/construction, often one of the threads
    in the compiler itself.

    That locking by compilers seem to be the result of someone in the C++
    ctte wanting to take over every OS feature that used to be out of
    scope for system programming languages like C/C++ . It also makes it unnecessarily harder to use the system compiler to implement the lower
    level code that exists at a more fundamental / portable level than
    silly textbook examples .


    Enjoy

    Jakob
    --
    Jakob Bohm, MSc.Eng., I speak only for myself, not my company
    This public discussion message is non-binding and may contain errors
    All trademarks and other things belong to their owners, if any.
    --- Synchronet 3.20c-Linux NewsLink 1.2
  • From Jakob Bohm@egenagwemdimtapsar@jbohm.dk to comp.lang.c++ on Tue Apr 1 06:29:14 2025
    From Newsgroup: comp.lang.c++

    On 2025-03-31 16:29, James Kuyper wrote:
    On 30.03.2025 18:30, Muttley@DastardlyHQ.org wrote:
    On Sun, 30 Mar 2025 10:38:57 -0400
    James Kuyper <jameskuyper@alumni.caltech.edu> wibbled:
    Section 6.9.3.3 does in fact impose many constraints on the sequence in
    which non-local objects with static storage duration get initialized.
    However, all of the sequence requirements are only between objects
    defined in the same translation unit. Also, it's implementation-defined
    which of those initializations occur before the start of main().

    Initialising global objects before main is an absolute must otherwise how
    are you expected to use them safely? They're not in the code for decoration.

    "If it [initialization] is deferred, it strongly happens before any non-initialization odr-use of any non-inline function or non-inline
    variable defined in the same translation unit as the variable to be initialized.47 It is implementation-defined in which threads and at
    which points in the program such deferred dynamic initialization
    occurs." (6.9.3.3p5).

    Therefore, what you need to do is make sure that the object has been initialized is to access it from a function defined in the same
    translation unit.


    The literalist reading of that wording fails miserably if a real world
    program uses a global constructor/initializer to cause some desired
    imperative effect outside the C++ runtime state. Examples include
    setting the CPU clock frequency of a small system, outputting some kind
    of welcome message to the human user etc. etc.

    However treating the standard text as an imperfect description of
    traditional compiler techniques used for 2nd. Edition compilers makes
    much more sense . Those guarantee that all included global objects
    are constructed before the first line of the main/init function of the
    linker output unit (program, dll, driver, whatever) and destructed after
    the last line of the main/cleanup function of the same . Even if either
    of those functions are implicit default empty functions . Just like if
    those globals were member objects of an implied program class where main/init/cleanup are member/constructor/destructor functions .

    Note that my previous paragraph accepts the possibility of some global
    objects getting optimized away completely along with their compilation
    unit by things like using a static library containing those compilation
    units .


    Enjoy

    Jakob
    --
    Jakob Bohm, MSc.Eng., I speak only for myself, not my company
    This public discussion message is non-binding and may contain errors
    All trademarks and other things belong to their owners, if any.
    --- Synchronet 3.20c-Linux NewsLink 1.2
  • From Chris M. Thomasson@chris.m.thomasson.1@gmail.com to comp.lang.c++ on Mon Mar 31 21:54:53 2025
    From Newsgroup: comp.lang.c++

    On 3/30/2025 10:37 PM, Bonita Montero wrote:
    Am 30.03.2025 um 22:57 schrieb Chris M. Thomasson:

    Creating threads, socket-connections before main is a bad idea...? ;^o

    Why ?


    Is main all setup pre main?
    --- Synchronet 3.20c-Linux NewsLink 1.2
  • From Bonita Montero@Bonita.Montero@gmail.com to comp.lang.c++ on Tue Apr 1 08:41:02 2025
    From Newsgroup: comp.lang.c++

    Am 01.04.2025 um 06:06 schrieb Jakob Bohm:

    Artificial locking around ALL static locals as implemented by some
    modern compilers is highly wasteful as in most code, the code
    structure already ensures a single thread will be the first to
    execute that initialization/construction, often one of the threads
    in the compiler itself.

    That locking by compilers seem to be the result of someone in the C++
    ctte wanting to take over every OS feature that used to be out of
    scope for system programming languages like C/C++ .  It also makes it unnecessarily harder to use the system compiler to implement the lower
    level code that exists at a more fundamental / portable level than
    silly textbook examples .

    Double-checked locking nearly costs nothing.

    --- Synchronet 3.20c-Linux NewsLink 1.2
  • From Bonita Montero@Bonita.Montero@gmail.com to comp.lang.c++ on Tue Apr 1 08:41:23 2025
    From Newsgroup: comp.lang.c++

    Am 01.04.2025 um 06:54 schrieb Chris M. Thomasson:

    Is main all setup pre main?

    Pre-main.

    --- Synchronet 3.20c-Linux NewsLink 1.2
  • From Chris M. Thomasson@chris.m.thomasson.1@gmail.com to comp.lang.c++ on Tue Apr 1 00:00:56 2025
    From Newsgroup: comp.lang.c++

    On 3/31/2025 11:41 PM, Bonita Montero wrote:
    Am 01.04.2025 um 06:54 schrieb Chris M. Thomasson:

    Is main all setup pre main?

    Pre-main.


    Setting a lot of things up pre-main can lead to some issues... Waiting
    on a connection before main is called seems rather odd to me, ect...
    --- Synchronet 3.20c-Linux NewsLink 1.2
  • From Muttley@Muttley@DastardlyHQ.org to comp.lang.c++ on Tue Apr 1 07:26:50 2025
    From Newsgroup: comp.lang.c++

    On Mon, 31 Mar 2025 19:42:48 -0400
    James Kuyper <jameskuyper@alumni.caltech.edu> wibbled:
    On 31.03.2025 17:01, Muttley@DastardlyHQ.org wrote:
    On Mon, 31 Mar 2025 15:39:53 +0300
    Paavo Helde <eesnimi@osa.pri.ee> wibbled:
    On 31.03.2025 12:09, Muttley@DastardlyHQ.org wrote:
    "If [initialization] is deferred, it strongly happens before any
    non-initialization odr-use of any non-inline function or non-inline
    variable defined in the same translation unit as the variable to be
    initialized."

    Who writes this stuff? Its borderline gibberish.

    Keep in mind that the key thing that makes this seem like gibberish is
    the use of precisely defined technical jargon, which is used for the
    same reason that jargon is used in many other contexts: it has a more >precisely specified meaning than more informal wording would have had.

    Key pieces of jargon: "strongly happens before", "non-initialization",

    "strongly happens before" is genuine gibberish. Either something happens before or it doesn't, the adverb is entirely superfluous.

    "odr-use", "translation unit". If there's anything you don't understand
    about that clause, it's probably based in unfamiliarity with such phrases.

    I'm a native english speaker and had to read it more than once to understand it. I feel sorry for people who's native language is not english trying to understand this crap.

    Yes this sort of language is similar to legalese, but with law it usually only applies to a given country so will be in the language of that country.

    --- Synchronet 3.20c-Linux NewsLink 1.2
  • From Paavo Helde@eesnimi@osa.pri.ee to comp.lang.c++ on Tue Apr 1 11:41:01 2025
    From Newsgroup: comp.lang.c++

    On 01.04.2025 07:06, Jakob Bohm wrote:
    On 2025-03-31 14:32, Bonita Montero wrote:
    Am 31.03.2025 um 14:26 schrieb Paavo Helde:

    An example of pre-C++11 thread-safe Meyer singleton:

    std::map<std::string, std::string>& GetGlobalMap() {

         // No dynamic initialization, so this is safe:
         static std::map<std::string, std::string>* pGlobal = NULL;

         // No dynamic initialization, so this is safe as well:
         static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

         // Initialize the global static if not yet initialized.
         pthread_mutex_lock(&mutex);
         if (!pGlobal) {
             pGlobal = new std::map<std::string, std::string>();
         }
         pthread_mutex_unlock(&mutex);
         return *pGlobal;
    }

    That's rather slow. Double-checked locking as implemented for
    all static locals with current runtimes is much more efficient.

    Artificial locking around ALL static locals as implemented by some
    modern compilers is highly wasteful as in most code, the code
    structure already ensures a single thread will be the first to
    execute that initialization/construction,

    The synchronization of static variable initialization (which may or may
    not involve locking) is demanded by the C++11 standard (so it is pretty portable) and makes it easier, faster, safer, and more maintainable to
    use statics in multithreaded C++ code (which is "most code" in my area).

    In an unlikely event this causes any measurable slowdown in a tight
    loop, a reference to the static variable can often be extracted before
    the loop.

    often one of the threads in the compiler itself.

    Sorry, cannot parse that sentence.

    That locking by compilers seem to be the result of someone in the C++
    ctte wanting to take over every OS feature that used to be out of
    scope for system programming languages like C/C++.
      It also makes it
    unnecessarily harder to use the system compiler to implement the lower
    level code that exists at a more fundamental / portable level than
    silly textbook examples .

    How comes? In some lower level code you one might just not use dynamic initialization of statics, which avoids any need of thread synchronization.

    If you do not know the differences between zero-initialization, constant initialization and dynamic initialization, then you are not in a
    position to implement any "lower level" code.


    --- Synchronet 3.20c-Linux NewsLink 1.2
  • From Paavo Helde@eesnimi@osa.pri.ee to comp.lang.c++ on Tue Apr 1 11:48:23 2025
    From Newsgroup: comp.lang.c++

    On 01.04.2025 10:26, Muttley@DastardlyHQ.org wrote:
    On Mon, 31 Mar 2025 19:42:48 -0400
    James Kuyper <jameskuyper@alumni.caltech.edu> wibbled:
    On 31.03.2025 17:01, Muttley@DastardlyHQ.org wrote:
    On Mon, 31 Mar 2025 15:39:53 +0300
    Paavo Helde <eesnimi@osa.pri.ee> wibbled:
    On 31.03.2025 12:09, Muttley@DastardlyHQ.org wrote:
    "If [initialization] is deferred, it strongly happens before any
    non-initialization odr-use of any non-inline function or non-inline
    variable defined in the same translation unit as the variable to be
    initialized."

    Who writes this stuff? Its borderline gibberish.

    Keep in mind that the key thing that makes this seem like gibberish is
    the use of precisely defined technical jargon, which is used for the
    same reason that jargon is used in many other contexts: it has a more
    precisely specified meaning than more informal wording would have had.

    Key pieces of jargon: "strongly happens before", "non-initialization",

    "strongly happens before" is genuine gibberish. Either something happens before
    or it doesn't, the adverb is entirely superfluous.

    Welcome to the 21-st century where out-of-sync CPU caches and pipelines
    are the norm.


    "odr-use", "translation unit". If there's anything you don't understand
    about that clause, it's probably based in unfamiliarity with such phrases.

    I'm a native english speaker and had to read it more than once to understand it.

    Somehow I suspect you have not understood much. For understanding the technical terms you need to read their definitions in the standard, not
    try to guess their meaning by an isolated usage example.


    --- Synchronet 3.20c-Linux NewsLink 1.2
  • From Muttley@Muttley@DastardlyHQ.org to comp.lang.c++ on Tue Apr 1 08:57:14 2025
    From Newsgroup: comp.lang.c++

    On Tue, 1 Apr 2025 11:48:23 +0300
    Paavo Helde <eesnimi@osa.pri.ee> wibbled:
    On 01.04.2025 10:26, Muttley@DastardlyHQ.org wrote:
    On Mon, 31 Mar 2025 19:42:48 -0400
    James Kuyper <jameskuyper@alumni.caltech.edu> wibbled:
    On 31.03.2025 17:01, Muttley@DastardlyHQ.org wrote:
    On Mon, 31 Mar 2025 15:39:53 +0300
    Paavo Helde <eesnimi@osa.pri.ee> wibbled:
    On 31.03.2025 12:09, Muttley@DastardlyHQ.org wrote:
    "If [initialization] is deferred, it strongly happens before any
    non-initialization odr-use of any non-inline function or non-inline
    variable defined in the same translation unit as the variable to be
    initialized."

    Who writes this stuff? Its borderline gibberish.

    Keep in mind that the key thing that makes this seem like gibberish is
    the use of precisely defined technical jargon, which is used for the
    same reason that jargon is used in many other contexts: it has a more
    precisely specified meaning than more informal wording would have had.

    Key pieces of jargon: "strongly happens before", "non-initialization",

    "strongly happens before" is genuine gibberish. Either something happens >before
    or it doesn't, the adverb is entirely superfluous.

    Welcome to the 21-st century where out-of-sync CPU caches and pipelines
    are the norm.

    Are you smoking something illegal? You're making less sense than that paragraph.

    I'm a native english speaker and had to read it more than once to understand >> it.

    Somehow I suspect you have not understood much. For understanding the >technical terms you need to read their definitions in the standard, not
    try to guess their meaning by an isolated usage example.

    Save your lame patronising for someone who cares and while you're at it
    mene vittuun itseäsi.



    --- Synchronet 3.20c-Linux NewsLink 1.2
  • From Paavo Helde@eesnimi@osa.pri.ee to comp.lang.c++ on Tue Apr 1 12:21:56 2025
    From Newsgroup: comp.lang.c++

    On 01.04.2025 11:57, Muttley@DastardlyHQ.org wrote:

    Save your lame patronising for someone who cares and while you're at it
    mene vittuun itseäsi.

    Wrong language :-) Try again!


    --- Synchronet 3.20c-Linux NewsLink 1.2
  • From Bonita Montero@Bonita.Montero@gmail.com to comp.lang.c++ on Tue Apr 1 11:42:43 2025
    From Newsgroup: comp.lang.c++

    Am 01.04.2025 um 09:00 schrieb Chris M. Thomasson:

    Setting a lot of things up pre-main can lead to some issues... Waiting
    on a connection before main is called seems rather odd to me, ect...

    If it does happen anyway it doesn't matter when it happens.

    --- Synchronet 3.20c-Linux NewsLink 1.2
  • From Fred. Zwarts@F.Zwarts@HetNet.nl to comp.lang.c++ on Tue Apr 1 12:00:40 2025
    From Newsgroup: comp.lang.c++

    Op 01.apr.2025 om 11:42 schreef Bonita Montero:
    Am 01.04.2025 um 09:00 schrieb Chris M. Thomasson:

    Setting a lot of things up pre-main can lead to some issues... Waiting
    on a connection before main is called seems rather odd to me, ect...

    If it does happen anyway it doesn't matter when it happens.


    One may wonder why we still need a 'main'. Everything in main can be
    done in an static object.
    --- Synchronet 3.20c-Linux NewsLink 1.2
  • From Muttley@Muttley@DastardlyHQ.org to comp.lang.c++ on Tue Apr 1 10:08:26 2025
    From Newsgroup: comp.lang.c++

    On Tue, 1 Apr 2025 12:21:56 +0300
    Paavo Helde <eesnimi@osa.pri.ee> wibbled:
    On 01.04.2025 11:57, Muttley@DastardlyHQ.org wrote:

    Save your lame patronising for someone who cares and while you're at it
    mene vittuun itseäsi.

    Wrong language :-) Try again!


    Oh well, I'm sure you can use google translate too.

    --- Synchronet 3.20c-Linux NewsLink 1.2
  • From Michael S@already5chosen@yahoo.com to comp.lang.c++ on Tue Apr 1 13:12:47 2025
    From Newsgroup: comp.lang.c++

    On Tue, 1 Apr 2025 12:21:56 +0300
    Paavo Helde <eesnimi@osa.pri.ee> wrote:
    On 01.04.2025 11:57, Muttley@DastardlyHQ.org wrote:

    Save your lame patronising for someone who cares and while you're
    at it mene vittuun itseäsi.

    Wrong language :-) Try again!


    He is probably using Google Translate. Google Translate does not know
    how to say it in right language. So Muttley, being Muttley, had no
    choice but to select a closest language in which Google translate does
    know a translation.
    --- Synchronet 3.20c-Linux NewsLink 1.2
  • From Michael S@already5chosen@yahoo.com to comp.lang.c++ on Tue Apr 1 13:20:44 2025
    From Newsgroup: comp.lang.c++

    On Tue, 1 Apr 2025 11:48:23 +0300
    Paavo Helde <eesnimi@osa.pri.ee> wrote:


    Welcome to the 21-st century where out-of-sync CPU caches and
    pipelines are the norm.



    It seems to me that saying that events are "strongly ordered" makes
    sense only when "weakly ordered" and "unordered" are not the same.
    In this particular case I don't see how exactly "weakly ordered"
    differs from "unordered".

    --- Synchronet 3.20c-Linux NewsLink 1.2
  • From Muttley@Muttley@DastardlyHQ.org to comp.lang.c++ on Tue Apr 1 10:23:24 2025
    From Newsgroup: comp.lang.c++

    On Tue, 1 Apr 2025 13:12:47 +0300
    Michael S <already5chosen@yahoo.com> wibbled:
    On Tue, 1 Apr 2025 12:21:56 +0300
    Paavo Helde <eesnimi@osa.pri.ee> wrote:

    On 01.04.2025 11:57, Muttley@DastardlyHQ.org wrote:
    =20
    Save your lame patronising for someone who cares and while you're
    at it mene vittuun itse=C3=A4si. =20
    =20
    Wrong language :-) Try again!
    =20
    =20

    He is probably using Google Translate. Google Translate does not know
    how to say it in right language. So Muttley, being Muttley, had no
    choice but to select a closest language in which Google translate does
    know a translation.


    --- Synchronet 3.20c-Linux NewsLink 1.2
  • From Muttley@Muttley@DastardlyHQ.org to comp.lang.c++ on Tue Apr 1 10:27:06 2025
    From Newsgroup: comp.lang.c++

    On Tue, 1 Apr 2025 13:12:47 +0300
    Michael S <already5chosen@yahoo.com> wibbled:
    On Tue, 1 Apr 2025 12:21:56 +0300
    Paavo Helde <eesnimi@osa.pri.ee> wrote:

    On 01.04.2025 11:57, Muttley@DastardlyHQ.org wrote:
    =20
    Save your lame patronising for someone who cares and while you're
    at it mene vittuun itse=C3=A4si. =20
    =20
    Wrong language :-) Try again!
    =20
    =20

    He is probably using Google Translate. Google Translate does not know
    how to say it in right language. So Muttley, being Muttley, had no
    choice but to select a closest language in which Google translate does
    know a translation.

    Going by his name I assumed he was finnish but looking at his address now I suspect estonian. Right ballpark.

    --- Synchronet 3.20c-Linux NewsLink 1.2
  • From Paavo Helde@eesnimi@osa.pri.ee to comp.lang.c++ on Tue Apr 1 13:33:43 2025
    From Newsgroup: comp.lang.c++

    On 01.04.2025 13:20, Michael S wrote:
    On Tue, 1 Apr 2025 11:48:23 +0300
    Paavo Helde <eesnimi@osa.pri.ee> wrote:


    Welcome to the 21-st century where out-of-sync CPU caches and
    pipelines are the norm.



    It seems to me that saying that events are "strongly ordered" makes
    sense only when "weakly ordered" and "unordered" are not the same.
    In this particular case I don't see how exactly "weakly ordered"
    differs from "unordered".

    The standard defines the terms "happens before", "simply happens
    before", and "strongly happens before". The standard does not contain
    phrases "strongly ordered" or "weakly ordered".


    --- Synchronet 3.20c-Linux NewsLink 1.2
  • From Muttley@Muttley@DastardlyHQ.org to comp.lang.c++ on Tue Apr 1 10:48:49 2025
    From Newsgroup: comp.lang.c++

    On Tue, 1 Apr 2025 13:33:43 +0300
    Paavo Helde <eesnimi@osa.pri.ee> wibbled:
    On 01.04.2025 13:20, Michael S wrote:
    On Tue, 1 Apr 2025 11:48:23 +0300
    Paavo Helde <eesnimi@osa.pri.ee> wrote:


    Welcome to the 21-st century where out-of-sync CPU caches and
    pipelines are the norm.



    It seems to me that saying that events are "strongly ordered" makes
    sense only when "weakly ordered" and "unordered" are not the same.
    In this particular case I don't see how exactly "weakly ordered"
    differs from "unordered".

    The standard defines the terms "happens before", "simply happens
    before", and "strongly happens before". The standard does not contain

    Those phrases all mean the same thing.


    --- Synchronet 3.20c-Linux NewsLink 1.2
  • From Bonita Montero@Bonita.Montero@gmail.com to comp.lang.c++ on Tue Apr 1 14:16:38 2025
    From Newsgroup: comp.lang.c++

    Am 01.04.2025 um 12:00 schrieb Fred. Zwarts:

    One may wonder why we still need a 'main'. Everything in main can be
    done in an static object.

    It's easier to define a main() since it needs less syntax than a class.
    --- Synchronet 3.20c-Linux NewsLink 1.2
  • From Bonita Montero@Bonita.Montero@gmail.com to comp.lang.c++ on Tue Apr 1 16:03:38 2025
    From Newsgroup: comp.lang.c++

    Am 01.04.2025 um 14:16 schrieb Bonita Montero:

    Am 01.04.2025 um 12:00 schrieb Fred. Zwarts:

    One may wonder why we still need a 'main'. Everything in main can be
    done in an static object.

    It's easier to define a main() since it needs less syntax than a class.

    And more important: there might be other global objects which are
    initialized after this pseudo-"main()", but which are needed before.

    --- Synchronet 3.20c-Linux NewsLink 1.2
  • From James Kuyper@jameskuyper@alumni.caltech.edu to comp.lang.c++ on Tue Apr 1 13:55:43 2025
    From Newsgroup: comp.lang.c++

    On 4/1/25 00:29, Jakob Bohm wrote:
    On 2025-03-31 16:29, James Kuyper wrote:
    ...
    "If it [initialization] is deferred, it strongly happens before any
    non-initialization odr-use of any non-inline function or non-inline
    variable defined in the same translation unit as the variable to be
    initialized.47 It is implementation-defined in which threads and at
    which points in the program such deferred dynamic initialization
    occurs." (6.9.3.3p5).

    Therefore, what you need to do is make sure that the object has been
    initialized is to access it from a function defined in the same
    translation unit.


    The literalist reading of that wording fails miserably if a real world program uses a global constructor/initializer to cause some desired imperative effect outside the C++ runtime state. Examples include
    setting the CPU clock frequency of a small system, outputting some kind
    of welcome message to the human user etc. etc.

    The wording describes what C++ does and does not require of an
    implementation. What actual implementations do is a different issue. If
    an implementation doesn't do what's required of it, it's non-conforming.
    If a program expects more than is required, the behavior of that code is undefined, which includes the possibility that the code will work
    exactly as intended if translated by an implementation that does, in
    fact, do more than what is required.

    However treating the standard text as an imperfect description of traditional compiler techniques used for 2nd. Edition compilers makes
    much more sense .

    No, that does not. The standard was never intended as a description of
    how compilers actually work, it was always intended to be a description
    of requirements on how they should work.
    --- Synchronet 3.20c-Linux NewsLink 1.2
  • From James Kuyper@jameskuyper@alumni.caltech.edu to comp.lang.c++ on Tue Apr 1 14:32:54 2025
    From Newsgroup: comp.lang.c++

    On 01.04.2025 10:26, Muttley@DastardlyHQ.org wrote:
    On Mon, 31 Mar 2025 19:42:48 -0400
    James Kuyper <jameskuyper@alumni.caltech.edu> wibbled:
    On 31.03.2025 17:01, Muttley@DastardlyHQ.org wrote:
    On Mon, 31 Mar 2025 15:39:53 +0300
    Paavo Helde <eesnimi@osa.pri.ee> wibbled:
    On 31.03.2025 12:09, Muttley@DastardlyHQ.org wrote:
    "If [initialization] is deferred, it strongly happens before any
    non-initialization odr-use of any non-inline function or non-inline
    variable defined in the same translation unit as the variable to be
    initialized."

    Who writes this stuff? Its borderline gibberish.

    Keep in mind that the key thing that makes this seem like gibberish is
    the use of precisely defined technical jargon, which is used for the
    same reason that jargon is used in many other contexts: it has a more
    precisely specified meaning than more informal wording would have had.

    Key pieces of jargon: "strongly happens before", "non-initialization",

    "strongly happens before" is genuine gibberish. Either something happens before
    or it doesn't, the adverb is entirely superfluous.

    Terms are explicitly defined by the C++ standard precisely because their meaning cannot be inferred by using ordinary English to interpret the
    words that make them up. Both "happens before" and "strongly happens
    before" are separate pieces of C++ jargon, and the requirements for
    qualifying as "strongly happens before" are in fact stronger than those
    for "happens before".

    "An evaluation A happens before an evaluation B (or, equivalently, B
    happens after A) if:
    (10.1)— A is sequenced before B, or
    (10.2)— A inter-thread happens before B.
    The implementation shall ensure that no program execution demonstrates a
    cycle in the “happens before” relation. [Note: This cycle would
    otherwise be possible only through the use of consume operations. — end note]" (6.9.2.1p10).

    the first occurrence of "happens before" in that clause is in italics,
    an ISO convention indicating that it is a piece of specialized jargon
    whose definition is provided by the sentence in which it occurs. Note
    that "sequenced before" and "inter-thread happens before" are two other
    pieces of standard-defined jargon.

    "An evaluation A strongly happens before an evaluation D if, either
    (12.1)— A is sequenced before D, or
    (12.2)— A synchronizes with D, and both A and D are sequentially
    consistent atomic operations (31.4), or
    (12.3)— there are evaluations B and C such that A is sequenced before B,
    B simply happens before C, and C is sequenced before D, or
    (12.4)— there is an evaluation B such that A strongly happens before B,
    and B strongly happens before D.
    [Note: Informally, if A strongly happens before B, then A appears to be evaluated before B in all contexts. Strongly happens before excludes
    consume operations. — end note]"

    The first occurrence of "strongly happens before" in that clause is also italicized.

    Note that "A is sequenced before D" would be sufficient to ensure that
    both "A happens before D" and "A strongly happens before D" are true.
    The difference between the two terms only shows up if A is not sequenced
    before D. In that case, at a minimum you must have "A inter-thread
    happens before D", but is not synchronized with D.

    For instance A inter-thread happens before D if it is dependency-ordered
    before D. (6.9.2.1p9). This could happen if A performs a release
    operation on an atomic object M , and, in another thread, D performs a
    consume operation on M and reads the value written by A (6.9.2.1p8).

    In that case, the requirements associated with "A happens before D" must
    be met, but those associated with "A strongly happens before D" need not be.

    Do you need an explanation of the parts of the above explanation that
    use the terms "release" and "consume"? I have little experience with multi-threaded code - someone else might be able to explain those better
    than I can.



    --- Synchronet 3.20c-Linux NewsLink 1.2
  • From James Kuyper@jameskuyper@alumni.caltech.edu to comp.lang.c++ on Tue Apr 1 14:37:50 2025
    From Newsgroup: comp.lang.c++

    On 4/1/25 06:20, Michael S wrote:
    ...
    It seems to me that saying that events are "strongly ordered" makes
    sense only when "weakly ordered" and "unordered" are not the same.
    In this particular case I don't see how exactly "weakly ordered"
    differs from "unordered".

    The term is "happens before", not "ordered". The standard defines
    neither "weakly happens before" nor anything connected to "happens
    before" that would be analogous to "unordered". See my response
    else-thread for more details on the relevant definitions.

    --- Synchronet 3.20c-Linux NewsLink 1.2
  • From Chris M. Thomasson@chris.m.thomasson.1@gmail.com to comp.lang.c++ on Tue Apr 1 12:39:07 2025
    From Newsgroup: comp.lang.c++

    On 4/1/2025 11:32 AM, James Kuyper wrote:
    On 01.04.2025 10:26, Muttley@DastardlyHQ.org wrote:
    On Mon, 31 Mar 2025 19:42:48 -0400
    James Kuyper <jameskuyper@alumni.caltech.edu> wibbled:
    On 31.03.2025 17:01, Muttley@DastardlyHQ.org wrote:
    On Mon, 31 Mar 2025 15:39:53 +0300
    Paavo Helde <eesnimi@osa.pri.ee> wibbled:
    On 31.03.2025 12:09, Muttley@DastardlyHQ.org wrote:
    "If [initialization] is deferred, it strongly happens before any
    non-initialization odr-use of any non-inline function or non-inline
    variable defined in the same translation unit as the variable to be
    initialized."

    Who writes this stuff? Its borderline gibberish.

    Keep in mind that the key thing that makes this seem like gibberish is
    the use of precisely defined technical jargon, which is used for the
    same reason that jargon is used in many other contexts: it has a more
    precisely specified meaning than more informal wording would have had.

    Key pieces of jargon: "strongly happens before", "non-initialization",

    "strongly happens before" is genuine gibberish. Either something happens before
    or it doesn't, the adverb is entirely superfluous.

    Terms are explicitly defined by the C++ standard precisely because their meaning cannot be inferred by using ordinary English to interpret the
    words that make them up. Both "happens before" and "strongly happens
    before" are separate pieces of C++ jargon, and the requirements for qualifying as "strongly happens before" are in fact stronger than those
    for "happens before".

    "An evaluation A happens before an evaluation B (or, equivalently, B
    happens after A) if:
    (10.1)— A is sequenced before B, or
    (10.2)— A inter-thread happens before B.
    The implementation shall ensure that no program execution demonstrates a cycle in the “happens before” relation. [Note: This cycle would
    otherwise be possible only through the use of consume operations. — end note]" (6.9.2.1p10).

    the first occurrence of "happens before" in that clause is in italics,
    an ISO convention indicating that it is a piece of specialized jargon
    whose definition is provided by the sentence in which it occurs. Note
    that "sequenced before" and "inter-thread happens before" are two other pieces of standard-defined jargon.

    "An evaluation A strongly happens before an evaluation D if, either
    (12.1)— A is sequenced before D, or
    (12.2)— A synchronizes with D, and both A and D are sequentially
    consistent atomic operations (31.4), or
    (12.3)— there are evaluations B and C such that A is sequenced before B,
    B simply happens before C, and C is sequenced before D, or
    (12.4)— there is an evaluation B such that A strongly happens before B,
    and B strongly happens before D.
    [Note: Informally, if A strongly happens before B, then A appears to be evaluated before B in all contexts. Strongly happens before excludes
    consume operations. — end note]"

    The first occurrence of "strongly happens before" in that clause is also italicized.

    Note that "A is sequenced before D" would be sufficient to ensure that
    both "A happens before D" and "A strongly happens before D" are true.
    The difference between the two terms only shows up if A is not sequenced before D. In that case, at a minimum you must have "A inter-thread
    happens before D", but is not synchronized with D.

    For instance A inter-thread happens before D if it is dependency-ordered before D. (6.9.2.1p9). This could happen if A performs a release
    operation on an atomic object M , and, in another thread, D performs a consume operation on M and reads the value written by A (6.9.2.1p8).

    In that case, the requirements associated with "A happens before D" must
    be met, but those associated with "A strongly happens before D" need not be.

    Do you need an explanation of the parts of the above explanation that
    use the terms "release" and "consume"? I have little experience with multi-threaded code - someone else might be able to explain those better
    than I can.

    Consume is weaker than acquire. It is basically used for data-dependent
    loads. For instance, it can be used for RCU algorithms that do not need
    a full acquire barrier. Now, iirc, the only system that actually needs
    an explicit barrier for data-dependent loads is the dec alpha. Actually,
    it kind of seems like consume was meant for RCU like algos.
    --- Synchronet 3.20c-Linux NewsLink 1.2
  • From Michael S@already5chosen@yahoo.com to comp.lang.c++ on Tue Apr 1 23:10:40 2025
    From Newsgroup: comp.lang.c++

    On Tue, 1 Apr 2025 13:55:43 -0400
    James Kuyper <jameskuyper@alumni.caltech.edu> wrote:

    On 4/1/25 00:29, Jakob Bohm wrote:


    However treating the standard text as an imperfect description of traditional compiler techniques used for 2nd. Edition compilers
    makes much more sense .

    No, that does not. The standard was never intended as a description of
    how compilers actually work, it was always intended to be a
    description of requirements on how they should work.


    It sounds to me like a revisionisms.
    Most language standards are intended to codify commonalities of work of existing compilers. That applies to C++98 and mostly, although not
    completely, to the following C++ standards.
    There exist exceptions, for example, Ada83. But they are exceptions.





    --- Synchronet 3.20c-Linux NewsLink 1.2
  • From Michael S@already5chosen@yahoo.com to comp.lang.c++ on Tue Apr 1 23:26:00 2025
    From Newsgroup: comp.lang.c++

    On Tue, 1 Apr 2025 14:32:54 -0400
    James Kuyper <jameskuyper@alumni.caltech.edu> wrote:
    On 01.04.2025 10:26, Muttley@DastardlyHQ.org wrote:
    On Mon, 31 Mar 2025 19:42:48 -0400
    James Kuyper <jameskuyper@alumni.caltech.edu> wibbled:
    On 31.03.2025 17:01, Muttley@DastardlyHQ.org wrote:
    On Mon, 31 Mar 2025 15:39:53 +0300
    Paavo Helde <eesnimi@osa.pri.ee> wibbled:
    On 31.03.2025 12:09, Muttley@DastardlyHQ.org wrote:
    "If [initialization] is deferred, it strongly happens before any
    non-initialization odr-use of any non-inline function or
    non-inline variable defined in the same translation unit as the
    variable to be initialized."

    Who writes this stuff? Its borderline gibberish.

    Keep in mind that the key thing that makes this seem like
    gibberish is the use of precisely defined technical jargon, which
    is used for the same reason that jargon is used in many other
    contexts: it has a more precisely specified meaning than more
    informal wording would have had.

    Key pieces of jargon: "strongly happens before",
    "non-initialization",

    "strongly happens before" is genuine gibberish. Either something
    happens before or it doesn't, the adverb is entirely superfluous.

    Terms are explicitly defined by the C++ standard precisely because
    their meaning cannot be inferred by using ordinary English to
    interpret the words that make them up. Both "happens before" and
    "strongly happens before" are separate pieces of C++ jargon, and the requirements for qualifying as "strongly happens before" are in fact
    stronger than those for "happens before".

    "An evaluation A happens before an evaluation B (or, equivalently, B
    happens after A) if:
    (10.1)— A is sequenced before B, or
    (10.2)— A inter-thread happens before B.
    The implementation shall ensure that no program execution
    demonstrates a cycle in the “happens before” relation. [Note: This
    cycle would otherwise be possible only through the use of consume
    operations. — end note]" (6.9.2.1p10).

    the first occurrence of "happens before" in that clause is in italics,
    an ISO convention indicating that it is a piece of specialized jargon
    whose definition is provided by the sentence in which it occurs. Note
    that "sequenced before" and "inter-thread happens before" are two
    other pieces of standard-defined jargon.

    "An evaluation A strongly happens before an evaluation D if, either
    (12.1)— A is sequenced before D, or
    (12.2)— A synchronizes with D, and both A and D are sequentially
    consistent atomic operations (31.4), or
    (12.3)— there are evaluations B and C such that A is sequenced before
    B, B simply happens before C, and C is sequenced before D, or
    (12.4)— there is an evaluation B such that A strongly happens before
    B, and B strongly happens before D.
    [Note: Informally, if A strongly happens before B, then A appears to
    be evaluated before B in all contexts. Strongly happens before
    excludes consume operations. — end note]"

    The first occurrence of "strongly happens before" in that clause is
    also italicized.

    Note that "A is sequenced before D" would be sufficient to ensure that
    both "A happens before D" and "A strongly happens before D" are true.
    The difference between the two terms only shows up if A is not
    sequenced before D. In that case, at a minimum you must have "A
    inter-thread happens before D", but is not synchronized with D.

    For instance A inter-thread happens before D if it is
    dependency-ordered before D. (6.9.2.1p9). This could happen if A
    performs a release operation on an atomic object M , and, in another
    thread, D performs a consume operation on M and reads the value
    written by A (6.9.2.1p8).

    In that case, the requirements associated with "A happens before D"
    must be met, but those associated with "A strongly happens before D"
    need not be.

    You probably paid attentions that the text is not crystal clear.
    It looks like authors of the Standard invent their own terminology not
    only when absolutely necessary but sometimes even when there exist
    established terms for the same things. To their defense, I could say
    that in the branch of CS that is related to concurrency and parallelism
    very few terms are 100% consensus.
    Do you need an explanation of the parts of the above explanation that
    use the terms "release" and "consume"? I have little experience with multi-threaded code - someone else might be able to explain those
    better than I can.

    I suspected that the difference between "strong happens before" and
    "happens before" is somehow related to implied ordering due to
    causality. After reading the text above my feeling changed from
    suspicion to strong suspicion. But it is not yet a certainty.
    --- Synchronet 3.20c-Linux NewsLink 1.2
  • From Keith Thompson@Keith.S.Thompson+u@gmail.com to comp.lang.c++ on Tue Apr 1 14:20:49 2025
    From Newsgroup: comp.lang.c++

    Michael S <already5chosen@yahoo.com> writes:
    On Tue, 1 Apr 2025 13:55:43 -0400
    James Kuyper <jameskuyper@alumni.caltech.edu> wrote:
    On 4/1/25 00:29, Jakob Bohm wrote:
    However treating the standard text as an imperfect description of
    traditional compiler techniques used for 2nd. Edition compilers
    makes much more sense .

    No, that does not. The standard was never intended as a description of
    how compilers actually work, it was always intended to be a
    description of requirements on how they should work.

    It sounds to me like a revisionisms.
    Most language standards are intended to codify commonalities of work of existing compilers. That applies to C++98 and mostly, although not completely, to the following C++ standards.

    I disagree. Many language standards are *based on* the behavior
    of existing compilers. In the case of C, for example, there were
    multiple implementations before the first standard was published, and
    the standard was largely based on their behavior (and on K&R1). The
    C++ standard evolved similarly; there were several implementations
    and books before the first C++ standard was published.

    But once a standard is published, it is a set of requirements on
    conforming implementations and programs. Note in particular that
    standards typically don't mention any specific implementations,
    and that implementations have had to be changed to satisfy the
    standard's requirements.

    I think of a language standard as a proposed contract between
    implementers and programmers. If an implementation claims
    conformance, programmers have a right to expect conforming code to
    behave as specified by the standard. But neither implementers nor
    programmers are necessarily required to accept the contract.

    There exist exceptions, for example, Ada83. But they are exceptions.

    Ada 83 was unusual in the sense that the standard was deliberately
    developed first, and implementations followed (though a lot of it
    was based on other existing languages). But once published, the
    Ada standard served much the same purpose as the C and C++ standards.
    --
    Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
    void Void(void) { Void(); } /* The recursive call of the void */
    --- Synchronet 3.20c-Linux NewsLink 1.2
  • From James Kuyper@jameskuyper@alumni.caltech.edu to comp.lang.c++ on Tue Apr 1 18:57:28 2025
    From Newsgroup: comp.lang.c++

    On 4/1/25 16:10, Michael S wrote:
    On Tue, 1 Apr 2025 13:55:43 -0400
    James Kuyper <jameskuyper@alumni.caltech.edu> wrote:
    ...
    No, that does not. The standard was never intended as a description of
    how compilers actually work, it was always intended to be a
    description of requirements on how they should work.


    It sounds to me like a revisionisms.
    Most language standards are intended to codify commonalities of work of existing compilers. That applies to C++98 and mostly, although not completely, to the following C++ standards.

    Regardless of whether they codify existing implementations or innovate
    far beyond them, programming language standards are codifications - and
    that makes them prescriptive documents. The C++ standard exists to
    define what it means to be a conforming implementation of C++, and what
    it means to write well-formed code. Well-formed code translated by a
    conforming implementation of C++ will produce the behavior that meets
    the requirements specified by the standard - and that's the point of the standard.

    However, C++98 was in fact notorious for the extent to which it went
    beyond merely codifying existing practice. In particular, <iostream> was
    a big change from <iostream.h>, and the process of incorporating STL
    into the C++ standard library involved a lot of changes.
    And every revision to the C++ standard has increased C++'s reputation
    for innovating well beyond existing practice. The language defined by
    the latest standard is very different from the one defined by C++98.

    The other standard that I'm most familiar with, the C standard, is by comparison a very slowly changing standard - but C90, C99, and C2011
    were all pretty significant changes from existing practice.
    --- Synchronet 3.20c-Linux NewsLink 1.2
  • From James Kuyper@jameskuyper@alumni.caltech.edu to comp.lang.c++ on Tue Apr 1 19:08:09 2025
    From Newsgroup: comp.lang.c++

    On 4/1/25 16:26, Michael S wrote:
    ...
    You probably paid attentions that the text is not crystal clear.
    It looks like authors of the Standard invent their own terminology not
    only when absolutely necessary but sometimes even when there exist established terms for the same things. To their defense, I could say
    that in the branch of CS that is related to concurrency and parallelism
    very few terms are 100% consensus.

    Feel free to propose alternative wording with the same precise meaning.
    Keep in mind that these terms were invented to convey a more
    precisely-define meaning than existing terms would have provided, so
    wording that says "approximately" the same thing would not be an
    acceptable replacement.

    ...
    I suspected that the difference between "strong happens before" and
    "happens before" is somehow related to implied ordering due to
    causality. After reading the text above my feeling changed from
    suspicion to strong suspicion. But it is not yet a certainty.

    I'm no expert in multi-threaded code, so I don't fully understand the significance of what it says. However, I able to derive the fact that
    there is a difference between the two terms only when one evaluation "inter-thread happens before" another evaluation, and the two
    evaluations are not synchronized. In other words, the difference is with
    regard to what's required for unsynchronized threads.

    --- Synchronet 3.20c-Linux NewsLink 1.2
  • From James Kuyper@jameskuyper@alumni.caltech.edu to comp.lang.c++ on Tue Apr 1 22:55:56 2025
    From Newsgroup: comp.lang.c++

    On 4/1/25 14:32, James Kuyper wrote:
    ...
    Note that "A is sequenced before D" would be sufficient to ensure that
    both "A happens before D" and "A strongly happens before D" are true.
    The difference between the two terms only shows up if A is not sequenced before D. In that case, at a minimum you must have "A inter-thread
    happens before D", but is not synchronized with D.

    For instance A inter-thread happens before D if it is dependency-ordered before D. (6.9.2.1p9). This could happen if A performs a release
    operation on an atomic object M , and, in another thread, D performs a consume operation on M and reads the value written by A (6.9.2.1p8).

    I got sidetracked by life before I could look into that further, but
    I've traced down relevant text in 1.10p7: "An evaluation A that performs
    a release operation on an object M synchronizes with an evaluation B
    that performs an acquire operation on M and reads a value written by any
    side effect in the release sequence headed by A."

    Therefore, A "happens before" D, but does not "strongly happen before" D
    if A does a release on M, and D does a consume on M, but D does not do
    an acquire on M followed by reading a value written by a side effect of
    A's release sequence.
    --- Synchronet 3.20c-Linux NewsLink 1.2
  • From Muttley@Muttley@DastardlyHQ.org to comp.lang.c++ on Wed Apr 2 07:34:52 2025
    From Newsgroup: comp.lang.c++

    On Tue, 1 Apr 2025 14:32:54 -0400
    James Kuyper <jameskuyper@alumni.caltech.edu> wibbled:
    "An evaluation A strongly happens before an evaluation D if, either
    :
    (12.4)— there is an evaluation B such that A strongly happens before B,
    and B strongly happens before D.

    Looks like a circular definition to me. But regardless, looks like the usual unintelligable nonsense thats no use to anyone except the people who wrote it.

    Do you need an explanation of the parts of the above explanation that
    use the terms "release" and "consume"? I have little experience with >multi-threaded code - someone else might be able to explain those better
    than I can.

    I don't particularly care. I generally find standards and RFCs unreadable.
    Its often easier to look at code or test with a working example to see what actually happens. Thats the method I used to write my NNTP and NMAP clients amongst many others.

    --- Synchronet 3.20c-Linux NewsLink 1.2
  • From David Brown@david.brown@hesbynett.no to comp.lang.c++ on Wed Apr 2 10:29:17 2025
    From Newsgroup: comp.lang.c++

    On 01/04/2025 22:10, Michael S wrote:
    On Tue, 1 Apr 2025 13:55:43 -0400
    James Kuyper <jameskuyper@alumni.caltech.edu> wrote:

    On 4/1/25 00:29, Jakob Bohm wrote:


    However treating the standard text as an imperfect description of
    traditional compiler techniques used for 2nd. Edition compilers
    makes much more sense .

    No, that does not. The standard was never intended as a description of
    how compilers actually work, it was always intended to be a
    description of requirements on how they should work.


    It sounds to me like a revisionisms.
    Most language standards are intended to codify commonalities of work of existing compilers. That applies to C++98 and mostly, although not completely, to the following C++ standards.
    There exist exceptions, for example, Ada83. But they are exceptions.


    Most language standards /started/ with a codification of existing tools.
    Making a language standard is a lot of effort, and is rarely done
    until there is at least one implementation and it has been used for a
    while - there's little point spending a lot of time defining a language
    that might never be used, or might turn out to be impractical or
    inefficient to implement. Initial standards are often books - K&R "The
    C Programming Language" and Stroustrup "The C++ Programming Language"
    being fine examples. More official standards can come later.

    Sometimes there is a "reference implementation" and the documentation
    for that becomes, in effect, the standard.

    But once the process is in place, it is now the standard that defines
    the language, and future implementations are intended to conform to the standard. Implementations can have extensions and extra features, and
    those can strongly influence future versions of the standard, but the
    standard defines how the language works.

    Thus many features that were added to C and C++ after their initial standardisation began as extensions in compilers - especially gcc. But
    the standardised features were what the language committees felt were
    best for the language going forward - /not/ a codification of existing practice. There are countless examples of new features in language
    standards that are clearly inspired by, but noticeably different from, extensions in compilers.


    --- Synchronet 3.20c-Linux NewsLink 1.2