C ++ condition_variable wait_for并不总是有效

时间:2017-07-26 14:02:53

标签: c++ multithreading visual-studio-2017 mutex condition-variable

我的应用程序启动logThread线程然后循环调用lookForSms进行卷曲调用并等待logThread读取某个字符串,但是这个字符串可能永远不会出现,所以我用过condition_variable wait_for,以便最终(5分钟后)继续测试。 问题是它有时会等待很长时间,有时甚至会持续20分钟。 如何让它可靠地工作?

我正在使用Visual Studio Community 2017,这里是代码:

            void lookForSms(CURL *curl) {
                sms_found = false;

                int  i;
                CURLcode res;
                cout << "\n" << timestamp() << "\t";

                res = curl_easy_perform(curl);
                if (res == CURLE_OK) {
                    unique_lock<mutex> lk(F);

                    analysis << timestampMil() << "\t";

                    while (cv.wait_for(lk, TIMEOUT_SMS * 1000ms) != cv_status::timeout && !sms_found);

                    if (sms_found) {
                        analysis << timestampMil() << "\tSMS RECEIVED\n";
                        cout << "\tOK";
                    }
                    else {
                        analysis << timestampMil() << "\tSMS LOST\n";
                        cout << "\tKO";
                    }

                }
            }

            void logThread() {
                string line;
                int n, i, count;
                unsigned char buf[BUFFER];
                while (!close) {
                    N.lock();
                    M.lock();
                    N.unlock();

                    n = RS232_PollComport(comport, buf, BUFFER);
                    if (n > 0 && n < BUFFER) {
                        buf[n] = '\0';

                        for (i = 0; i < n; i++) {
                            if (buf[i] == '\n') {
                                all << timestampMil() << "\t" << line << "\n";
                                handleLine(line);
                                line = string();
                            }
                            else if (buf[i] != '\r' && buf[i] >= 32) {
                                line += buf[i];
                            }
                        }
                    }
                    M.unlock();
                }

            }

            void handleLine(string line) {
                if (searchString(line, RCV_SMS)) {
                    unique_lock<mutex> lk(F);
                    sms_found = true;
                    lk.unlock();
                    cv.notify_all();
                }
            }

[编辑]这应该具备重建问题所需的一切。

            #include <iostream>
            #include <thread>
            #include <mutex>
            #include <condition_variable>

            #define TIMEOUT_SMS 300
            #define DELAY_SMS 10


            mutex L, M, N, F;
            condition_variable cv;

            void logThread() {
                while (!close) {
                    N.lock();
                    M.lock();
                    N.unlock();

                    handleLine("");
                    Sleep(500);

                    M.unlock();
                }

            }


            void lookForSms() {

                    unique_lock<mutex> lk(F);
                    sms_found = false;
                    unlocked = false;


                    //while (cv.wait_for(lk, TIMEOUT_SMS * 1000ms) != cv_status::timeout && !unlocked);
                    cv.wait_for(lk, 10 * TIMEOUT_SMS * 1000ms, []() {return unlocked; });

                    if (sms_found) {
                        cout << "\tOK";
                    }
                    else {
                        cout << "\tKO";
                    }

                }
            }

            void handleLine(string line) {
                if (false) {// the problem is when cv remains locked
                    unique_lock<mutex> lk(F);
                    unlocked = true;
                    sms_found = true;
                    lk.unlock();
                    cv.notify_all();
                }
            }

            void stopThreads() {
                N.lock();
                M.lock();
                //stop log thread
                close = true;
                N.unlock();
                M.unlock();
            }

            int main(int argc, const char * argv[]) {


                thread logger(logThread);

                for (i = 0; i < repeat; i++) {
                    lookForSms();
                    Sleep(DELAY_SMS * 1000);
                }

                //aquire mutex and set close to true, then join
                stopThreads();
                //wait for the thread to end
                logger.join();

                return 0;
            }

0 个答案:

没有答案