Forum Replies Created

Viewing 15 posts - 31 through 45 (of 344 total)
  • Author
    Posts
  • in reply to: Atomic bool vs. atomic_flag #633028
    RainerRainer
    Keymaster
        Up
        0
        Down
        ::

        Being lock-free means that no locking mechanism such as a mutex is used internally. In C++11, you can’t read the value of an atomic_flag without changing it. In C++20, you can call test on an atomic_flag. If possible, I would prefer std::atomic_flag.

        in reply to: Spinlock vs. mutex #632952
        RainerRainer
        Keymaster
            Up
            0
            Down
            ::

            A spinlock may be useful when you only wait for a short period of time because the sleeping of the mutex is expensive. Usually, a mutex spins for a short time and then falls asleep. std::mutex is only a wrapper around the OS mutex. This means it is probably a pthread mutex on Unix/Linux. You can access the underlying mutex by calling std::mutex::native_handle.

            RainerRainer
            Keymaster
                Up
                0
                Down
                ::

                The crucial observations is that the operation compare_exchange_strong is atomic. If someone changed the value between the load and the compare_exchange_strong call this is not an issue because the latter runs in a while loop until successful.

                in reply to: Resuming on a different thread #632799
                RainerRainer
                Keymaster
                    Up
                    0
                    Down
                    ::

                    Here is your modified await_suspend call.

                    void await_suspend(std::coroutine_handle<> h) {
                             auto outerThread = std::jthread([h]() { h.resume();});
                        }
                    

                    You use a jthread. The jthread automatically joins in its destructor if still joinable. This means, your await_suspend call is blocking.

                    Additionally, you don’t have a handle to the thread. You can, for example, not cooperatively interrupt it.

                    in reply to: Return type of await_suspend #632778
                    RainerRainer
                    Keymaster
                        Up
                        1
                        Down
                        ::

                        The function await_suspend handles the suspension of the coroutine. await_suspend is the crucial function of the Awaiter. It can have the following return types:

                        • void: the control flow immediately returns to the caller. The coroutine remains suspended.
                        • bool:
                          •  true: the control flow immediately returns to the caller
                          • false: the coroutine is resumed
                        • std::coroutine_handle<>:
                          • if it returns a coroutine handle coroHandle of another coroutine, this coroutine is resumed: coroHandle.resume(). This strategy is called symmetric transfer.
                          • std::noop_coroutine: no coroutine is resumed. Equivalent to returning true.

                        In both the example and in the case where we don’t call handle.resume() in await_suspend like here the coroutines get destroyed thanks to the destructor of Job and there are no leaks right?

                        Right.

                        In the example, I think it would be better to use the name MySuspendSometimes instead of MySuspendAlways.

                        You are right. It only sometimes suspends when await_ready return true.

                        in reply to: Wrong content in Blog #632655
                        RainerRainer
                        Keymaster
                            Up
                            1
                            Down
                            ::

                            Damn. I will fix it.

                            in reply to: Wrong content in Blog #632645
                            RainerRainer
                            Keymaster
                                Up
                                1
                                Down
                                ::

                                Thanx. I will fix it.

                                in reply to: Improved Generator #632631
                                RainerRainer
                                Keymaster
                                    Up
                                    1
                                    Down
                                    ::
                                    • When I have three iterations in the coroutine and four iterations in main, I get the last value repeated and no error

                                    You resume final_suspend. This is undefined behavior.

                                    • When I have two iterations in the coroutine and four iterations in main, I get an error

                                    There is nothing left to  resume. The coroutine already ended.

                                     

                                    in reply to: Improved Generator #632630
                                    RainerRainer
                                    Keymaster
                                        Up
                                        1
                                        Down
                                        ::

                                        Good point. I fixed it. It should be bool.

                                        bool next() {
                                            std::cout << "        Generator::next" << '\n';
                                            coro.resume();
                                            return not coro.done();
                                        }
                                        
                                        in reply to: Deploying modules #632625
                                        RainerRainer
                                        Keymaster
                                            Up
                                            1
                                            Down
                                            ::

                                            There is an excellent about distributing modules on CppCon  2023: C++20 Modules: The Packaging and Binary Redistribution Story by Luis Caro  Campos

                                            in reply to: My First Queston #632622
                                            RainerRainer
                                            Keymaster
                                                Up
                                                0
                                                Down
                                                ::

                                                std::cout << '\n';
                                                
                                                    std::atomic<std::shared_ptr<std::string>> sharString(
                                                        std::make_shared<std::string>("Zero"));
                                                    
                                                    std::thread t1([&sharString]{ 
                                                        sharString.store(std::make_shared<std::string>(*sharString.load() + "One")); 
                                                    });
                                                    std::thread t2([&sharString]{ 
                                                        sharString.store(std::make_shared<std::string>(*sharString.load() + "Two")); 
                                                    });
                                                    std::thread t3([&sharString]{ 
                                                        sharString.store(std::make_shared<std::string>(*sharString.load() +"Three"));
                                                    });
                                                    std::thread t4([&sharString]{ 
                                                        sharString.store(std::make_shared<std::string>(*sharString.load() +"Four")); 
                                                    });
                                                    std::thread t5([&sharString]{ 
                                                        sharString.store(std::make_shared<std::string>(*sharString.load() +"Five")); 
                                                    });
                                                
                                                in reply to: Function Hiding vs Overriding #632567
                                                RainerRainer
                                                Keymaster
                                                    Up
                                                    0
                                                    Down
                                                    ::

                                                    When you apply multiple inheritance, the base classes should be orthogonal. Said that, this example is crazy because both base classes provide a pure virtual member function display. I cannot find anything in the C++ standard, but I assume that the program is correct. You essentially override both pure virtual member functions.

                                                    I modified the program and added a display function to Derived:

                                                    #include <iostream>
                                                    
                                                    class GrandGrandParent
                                                    {
                                                    public:
                                                        virtual void display() = 0;
                                                    };
                                                    
                                                    class GrandParent : public GrandGrandParent
                                                    {
                                                    };
                                                    
                                                    class human
                                                    {
                                                    public:
                                                        virtual void display() = 0;
                                                    };
                                                    
                                                    class Parent : public GrandParent, public human
                                                    {
                                                    public:
                                                        // Both parent class has method with same name display. We have overriden the function in this class.
                                                        // Which function is getting overriden ? Can you please provide some more insight how static(Parent*P) and dynamic type(new Derived()) working here
                                                        void display() override
                                                        {
                                                            std::cout << "Derived";
                                                        }
                                                    };
                                                    
                                                    class Derived : public Parent
                                                    {
                                                        void display() override {
                                                            std::cout << "Derived display";
                                                        }
                                                    };
                                                    
                                                    int main()
                                                    {
                                                        Parent *p = new Derived();
                                                        p->display(); // Derived
                                                    }
                                                    

                                                    The static type of Parent *p = new Derived() is Parent but the dynamic Derived. The static type determines the access specifiers. Consequentially, display in Derived can be private.

                                                    in reply to: Deriving privately #632544
                                                    RainerRainer
                                                    Keymaster
                                                        Up
                                                        0
                                                        Down
                                                        ::

                                                        Here is a pictorial representation:

                                                        in reply to: reinterpret cast – undefined behavior? #632081
                                                        RainerRainer
                                                        Keymaster
                                                            Up
                                                            0
                                                            Down
                                                            ::

                                                            The use-cases for a reinterpret_cast are pretty limited:

                                                            • A pointer into a pointer
                                                            • An integral into a pointer
                                                            • A pointer into an integral

                                                            The reinterpret_cast guarantees that the conversion to and from a pointer returns the same value.

                                                            All other casts are undefined behavior.

                                                             

                                                            RainerRainer
                                                            Keymaster
                                                                Up
                                                                0
                                                                Down
                                                                ::

                                                                Interestingly, when you use a constexpr function in between, the GCC and MSVC apply the necessary conversions: https://godbolt.org/z/d3jM6oaeP

                                                                template <double d>
                                                                auto acceptOnlyDouble() {
                                                                    return d;
                                                                }
                                                                
                                                                constexpr double ToDouble(double param) {
                                                                    return param;
                                                                }
                                                                
                                                                int main() {
                                                                    const auto xf_double88 = acceptOnlyDouble<-5.123456788>();
                                                                    const auto xf_double89 = acceptOnlyDouble<-5.123456789>();
                                                                    const auto xf_float = acceptOnlyDouble<ToDouble(-9.48f)>();
                                                                    const auto xf_long = acceptOnlyDouble<ToDouble(-20L)>();
                                                                }
                                                                

                                                                Finally, I asked Jorg Brown, author of the proposal P1714: NTTP are incomplete without float, double, and long double! (Revision 1).

                                                                He said: Anyway, to answer your question, I think MSVC is doing the right thing here. I’ll check with a friend to be sure…

                                                              Viewing 15 posts - 31 through 45 (of 344 total)