• Is this safe?

    From boltar@3:633/10 to All on Sat Jul 18 09:19:35 2026
    Is this function thread safe? Ie will the return string value be set on
    the stack before the lock_guard is released?

    string mygetter(void)
    {
    lock_guard<mutex> lock(setmtx);
    return some_string_set_elsewhere;
    }

    or do I need to do this:

    string mygetter(void)
    {
    lock_guard<mutex> lock(setmtx);
    string tmp = some_string_set_elsewhere;
    return tmp;
    }

    I should probably know the answer to this but I'm not 100% sure.


    --- PyGate Linux v1.5.18
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Paavo Helde@3:633/10 to All on Sat Jul 18 17:58:16 2026
    On 7/18/2026 12:19 PM, boltar@caprica.universe wrote:
    Is this function thread safe? Ie will the return string value be set on
    the stack before the lock_guard is released?

    string mygetter(void)
    {
    lock_guard<mutex> lock(setmtx);
    return some_string_set_elsewhere;
    }

    or do I need to do this:

    string mygetter(void)
    {
    lock_guard<mutex> lock(setmtx);
    string tmp = some_string_set_elsewhere;
    return tmp;
    }

    I should probably know the answer to this but I'm not 100% sure.


    AFAIK these are functionally equivalent and the compiler can optimize
    them to the same machine code. To my knowledge, both are safe (the
    return value is constructed before destroying local variables like lock).



    --- PyGate Linux v1.5.18
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From boltar@3:633/10 to All on Sat Jul 18 15:25:14 2026
    On Sat, 18 Jul 2026 17:58:16 +0300
    Paavo Helde <eesnimi@osa.pri.ee> gabbled:
    On 7/18/2026 12:19 PM, boltar@caprica.universe wrote:
    Is this function thread safe? Ie will the return string value be set on
    the stack before the lock_guard is released?

    string mygetter(void)
    {
    lock_guard<mutex> lock(setmtx);
    return some_string_set_elsewhere;
    }

    or do I need to do this:

    string mygetter(void)
    {
    lock_guard<mutex> lock(setmtx);
    string tmp = some_string_set_elsewhere;
    return tmp;
    }

    I should probably know the answer to this but I'm not 100% sure.


    AFAIK these are functionally equivalent and the compiler can optimize
    them to the same machine code. To my knowledge, both are safe (the
    return value is constructed before destroying local variables like lock).


    Thanks. That is certainly the sensible approach but you can never be 100%
    sure with C++.


    --- PyGate Linux v1.5.18
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Chris M. Thomasson@3:633/10 to All on Sat Jul 18 17:12:47 2026
    On 7/18/2026 2:19 AM, boltar@caprica.universe wrote:
    Is this function thread safe? Ie will the return string value be set on
    the stack before the lock_guard is released?

    string mygetter(void)
    {
    lock_guard<mutex> lock(setmtx);
    return some_string_set_elsewhere;
    }


    That's okay. But I totally understand why you would ask.



    or do I need to do this:

    string mygetter(void)
    {
    lock_guard<mutex> lock(setmtx);
    string tmp = some_string_set_elsewhere;
    return tmp;
    }

    I should probably know the answer to this but I'm not 100% sure.



    --- PyGate Linux v1.5.18
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Chris M. Thomasson@3:633/10 to All on Sat Jul 18 17:26:45 2026
    On 7/18/2026 8:25 AM, boltar@caprica.universe wrote:
    On Sat, 18 Jul 2026 17:58:16 +0300
    Paavo Helde <eesnimi@osa.pri.ee> gabbled:
    On 7/18/2026 12:19 PM, boltar@caprica.universe wrote:
    Is this function thread safe? Ie will the return string value be set on
    the stack before the lock_guard is released?

    string mygetter(void)
    {
    ˙˙˙˙lock_guard<mutex> lock(setmtx);
    ˙˙˙˙return some_string_set_elsewhere;
    }

    or do I need to do this:

    string mygetter(void)
    {
    ˙˙˙˙lock_guard<mutex> lock(setmtx);
    ˙˙˙˙string tmp = some_string_set_elsewhere;
    ˙˙˙˙return tmp;
    }

    I should probably know the answer to this but I'm not 100% sure.


    AFAIK these are functionally equivalent and the compiler can optimize
    them to the same machine code. To my knowledge, both are safe (the
    return value is constructed before destroying local variables like lock).


    Thanks. That is certainly the sensible approach but you can never be 100% sure with C++.


    You can see it in action by making a raii object cout what its doing. Something like this:

    _____________________
    #include <iostream>

    struct raii
    {
    raii()
    {
    std::cout << "(" << this << ")->raii::raii()\n";
    }

    ~raii()
    {
    std::cout << "(" << this << ")->raii::~raii()\n";
    }
    };


    struct raii_return
    {
    int m_state = 0;

    raii_return(int state) : m_state(state)
    {
    std::cout << "(" << this << ")->raii_return::raii_return()
    m_state = " << m_state << "\n";
    }

    ~raii_return()
    {
    std::cout << "(" << this << ")->raii_return::~raii_return()
    m_state = " << m_state << "\n";
    }
    };


    raii_return
    foo()
    {
    raii raii0;

    std::cout << "foo()\n";

    return raii_return(42);
    }


    int main()
    {
    std::cout << "before foo()\n";
    foo();
    std::cout << "after foo()\n";

    return 0;
    }
    _____________________


    Gives me this output, examine it:
    _____________________
    before foo()
    (0x7fffd424560f)->raii::raii()
    foo()
    (0x7fffd424563c)->raii_return::raii_return() m_state = 42 (0x7fffd424560f)->raii::~raii()
    (0x7fffd424563c)->raii_return::~raii_return() m_state = 42
    after foo()
    _____________________


    It works fine.


    --- PyGate Linux v1.5.18
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Fred. Zwarts@3:633/10 to All on Sun Jul 19 12:07:01 2026
    Op 18.jul.2026 om 11:19 schreef boltar@caprica.universe:
    Is this function thread safe? Ie will the return string value be set on
    the stack before the lock_guard is released?

    string mygetter(void)
    {
    lock_guard<mutex> lock(setmtx);
    return some_string_set_elsewhere;
    }

    or do I need to do this:

    string mygetter(void)
    {
    lock_guard<mutex> lock(setmtx);
    string tmp = some_string_set_elsewhere;
    return tmp;
    }

    I should probably know the answer to this but I'm not 100% sure.


    These two are equivalent. If string is std::string, then it is safe.
    I was once caught by a similar construction, but where string was a C
    string, i.e. a pointer to an array of char.
    Then only a pointer to the array was returned. Another thread could
    damage the contents of the array before the caller could read it.
    In that case the work around in the second function would not help.
    Instead of creating a new pointer, a pointer to a copy of the array must
    be returned.

    --- PyGate Linux v1.5.18
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From boltar@3:633/10 to All on Sun Jul 19 18:46:13 2026
    On Sun, 19 Jul 2026 12:07:01 +0200
    "Fred. Zwarts" <F.Zwarts@HetNet.nl> wrote:
    Op 18.jul.2026 om 11:19 schreef boltar@caprica.universe:
    I should probably know the answer to this but I'm not 100% sure.


    These two are equivalent. If string is std::string, then it is safe.
    I was once caught by a similar construction, but where string was a C >string, i.e. a pointer to an array of char.
    Then only a pointer to the array was returned. Another thread could
    damage the contents of the array before the caller could read it.
    In that case the work around in the second function would not help.
    Instead of creating a new pointer, a pointer to a copy of the array must
    be returned.

    Returning raw char* from a C function can lead to all sorts of gotchas in the higher level code. The classic one is calling the a function that returns a pointer to a static buffer 2 or more times in a printf, eg inet_ntoa().
    Then there's strtok().....


    --- PyGate Linux v1.5.18
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)