Search code examples
c++libcurlnonblocking

what is the difference between multi-thread blocking and non-blocking?


I am using libcurl to do url request, the network latency is not acceptable. so i want it to be non blocking.

the bad news is libcurl non-blocking method is very confusing, my ideal api function will be curl_perform(CRUL*, int), the int control blocking or non-blocking.

but libcurl seems need to use select to manage those url request.

in my understanding, select need loop to monitor the socket, which need a single thread, and this thread can't do anything else.

so, the other method is:

I create a shared queue, and open another thread, this thread is while(1) { check_queue(); }

when the queue is not empty, it handles the data.

so, my main thread just put the request into queue, then it can do other things.

what is the difference between select and another thread?


Solution

  • Here is a code example for you (live demo : https://onlinegdb.com/lrYaY1osw)

    #include <chrono>
    #include <iostream>
    #include <thread>
    #include <condition_variable>
    #include <mutex>
    
    // a condition variable is (almost always used) in combination 
    // with a mutex and a value so wrap that concept once for reuse 
    // it is a template so you can also use it with enum values
    // (very useful for communicating state changes!)
    // or you can use integer type to use it as a semaphore too
    
    template<typename type_t>
    class synchronization_signal_t final
    {
    public:
        explicit synchronization_signal_t(const type_t& value) :
            m_value{ value }
        {
        }
    
        ~synchronization_signal_t() = default;
    
        void operator=(const type_t& value)
        {
            std::unique_lock<std::mutex> lock{ m_mtx };
            m_value = value;
            m_signal.notify_all();
        }
    
        void wait_for(const type_t& value)
        {
            std::unique_lock<std::mutex> lock{ m_mtx };
            // wait with predicate
            m_signal.wait(lock, [&] { return m_value == value; });
        }
    
    private:
        std::mutex m_mtx;
        std::condition_variable m_signal;
        type_t m_value;
    };
    
    // for readable time notation
    using namespace std::chrono_literals;
    
    int main()
    {
        // create a simple two state (bool) signal
        synchronization_signal_t<bool> signal{ false };
    
        // start a thread
        std::thread thread1{ [&]
        {
          std::cout << "thread started\n";
          std::this_thread::sleep_for(2s);
          std::cout << "thread setting signal\n";
    
          // set the signal
          signal = true;
          
          std::cout << "thread signal set\n";
        }};
    
        // the mainthread will wait for thread1 to have finished
        std::cout << "mainthread waiting...\n";
        signal.wait_for(true);
        std::cout << "mainthread done waiting\n";
    
        thread1.join();
        return 0;
    }