Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
307 views
in Technique[技术] by (71.8m points)

Porting code using FreeRTOS even groups to C++ threads

I'm porting a FreeRTOS-based application to C++ std threads. The basic structure of the application contains a an "event loop" thread, which works as such:

while (true)
{
    const EventBits_t bits = xEventGroupWaitBits(event_group, EVENTS, pdTRUE, pdFALSE, portMAX_DELAY);
    if (bit & EVENT_1)
    {
        ...
    }
    if (bit & EVENT_2)
    {
        ...
    }

Where other "producer" threads are responsible of xEventGroupSetBits(event_group, EVENT_1)ing events.

What is the best way to port it to C++ std theads?

question from:https://stackoverflow.com/questions/66060525/porting-code-using-freertos-even-groups-to-c-threads

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You may need to implement the behavior of event groups yourself. You may limit yourself to what you strictly need, instead of porting the original FreeRTOS implementation completely. In line with your code fragment, I've made a suggestion below. I think the condition variable is the best way to implement it with.

#include <iostream>
#include <chrono>
#include <mutex>
#include <condition_variable>

using sclock_t = std::chrono::steady_clock;

using event_bits_t = unsigned;
event_bits_t const event_0 = 1u << 0;
event_bits_t const event_1 = 1u << 1;
event_bits_t const event_2 = 1u << 2;

class event_or_group_t
{
public:
    event_bits_t set_bits(event_bits_t event_bits)
    {
        {
            std::lock_guard<std::mutex> lk(m_mutex);
            event_bits = (m_event_bits |= event_bits);
        }
        m_cv.notify_all();
        return event_bits;
    }
    event_bits_t wait_bits(event_bits_t events, bool clear, sclock_t::duration timeout)
    {
        event_bits_t event_bits{};
        std::unique_lock<std::mutex> lk(m_mutex);
        if (m_cv.wait_for(lk, timeout, [this] { return m_event_bits; }))
        {
            event_bits = m_event_bits;
            if (clear)
            {
                m_event_bits = 0;
            }
        }
        return event_bits;
    }
    /* event_bits_t wait_bits(event_bits_t events, bool clear, sclock_t::time_point until) 
       to be implemented with m_cv.wait_until */
protected:
    event_bits_t m_event_bits{};
    std::mutex m_mutex;
    std::condition_variable m_cv;
};


int main()
{
    using namespace std::chrono_literals;
    event_or_group_t event_group;
    sclock_t::duration port_max_delay = 10ms;
    event_bits_t events = event_1 | event_2;
    event_group.set_bits(event_2); // can be called from any thread
    while (true)
    {
        const event_bits_t bits = event_group.wait_bits(events, true, port_max_delay);
        if (bits & event_1)
        {
            std::cout << "event_1" << std::endl;
        }
        if (bits & event_2)
        {
            std::cout << "event_2" << std::endl;
        }
    }
}

(Please note that it is no more tested then this sample code itself. In case you'll find some bugs I'll be happy to update my answer with)

When you also need the 'and' functionality for some other event group, then you can make a separate event_and_group_t.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...