wxCriticalSection vs wxMutex vs std::mutex

If you are using the main C++ distribution of wxWidgets, Feel free to ask any question related to wxWidgets development here. This means questions regarding to C++ and wxWidgets, not compile problems.
Post Reply
ONEEYEMAN
Part Of The Furniture
Part Of The Furniture
Posts: 7477
Joined: Sat Apr 16, 2005 7:22 am
Location: USA, Ukraine

wxCriticalSection vs wxMutex vs std::mutex

Post by ONEEYEMAN »

Hi, ALL,
I need to understand what is the best approach in order to do successful implementation.

I have a class (interface) which is located inside the statically linked dll (I will use Windows terminology here - it is easier).
This DLL contains only this one class. Lets call this class Foo. This class as is the dll does not have a dependency on the wx.

I also have a main application which is written in wxWidgets. This application contains a main frame and some other classes. At some point of time the application creates a class derived from Foo and spawns a thread which calls a virtual function from Derived. Everything is good so far.

Now by the nature of the application if the thread is executing a virtual function - no calls to other virtual functions from class Derived should be possible - they should wait until after the function is finished and then execute.

So it is something like this:

Code: Select all

class Foo
{
public:
    void func1() = 0;
    void func2() = 0;
    void threadfunc() = 0;
};

class Derived : public Foo
{
public:
    void func1();
    void func2();
    void threadfunc();
};

class MainFrame : public wxFrame
{
public:
    void CreateObjectAndStartThread();
    void CallFunc1();
    void CallFunc2();
private:
    Foo *m_derived;
    MyThread *m_handler;
};

void MainFrame::CreateObjectAndStartThread()
{
    m_derived = new Derived;
    m_handler = new wxThread;
    if( m_handler->Run() != wxTHREAD_NO_ERROR )
    {
    }
}

void MainFrame::CallFunc1()
{
    // if threadfunc() running - wait to finish
    m_derived->func1();
}

void MainFrame::CallFunc2()
{
    // if threadfunc() running - wait to finish
    m_derived->func1();
}

wxThread::ExitCode MyThread::Entry()
{
    while( !TestDestroy() )
    {
// if there is a call to func1 or func2 - wait for it to finish
        m_derived->threadfunc();
        Sleep( 5000 );
    }
}
There is no extra processes involved - just one app with some dlls.

Now, my question - what is best to use here - wxCriticalSection, wxMutex or std::mutex?
With the latter I can keep the Foo class independent of wx and just protect the appropriate section with the:

Code: Select all

{
    std::lock_guard<std::mutex> lock( m_derived->m_mutex );
}
by adding the static m_mutex class to the Foo.

But if I can use wx' classes and just protect the calls to func1(), func2() and threadfunc() it would be even better.

So what is the best solution here? Can I use wxCriticalSection/wxMutex or I should use std::mutex as I wrote above?

Thank you.
User avatar
doublemax
Moderator
Moderator
Posts: 19159
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: wxCriticalSection vs wxMutex vs std::mutex

Post by doublemax »

First of all, without knowing why these methods are only allowed to be called once, the whole issue smells like bad design.

But let's assume there is a good reason for it, i think this check should happen inside the DLL. The main app should not have to keep track of which method it is allowed to call at any given time. Calling a method that is "busy" should just return an error code immediately.
Use the source, Luke!
ONEEYEMAN
Part Of The Furniture
Part Of The Furniture
Posts: 7477
Joined: Sat Apr 16, 2005 7:22 am
Location: USA, Ukraine

Re: wxCriticalSection vs wxMutex vs std::mutex

Post by ONEEYEMAN »

doublemax,
doublemax wrote: First of all, without knowing why these methods are only allowed to be called once, the whole issue smells like bad design.
They can be called many times, but they cannot be executed at the same time.
doublemax wrote: But let's assume there is a good reason for it, i think this check should happen inside the DLL. The main app should not have to keep track of which method it is allowed to call at any given time. Calling a method that is "busy" should just return an error code immediately.
There is.
I'm connecting to the SQL Server and doing some queries. In the thread I'm reusing the connection and doing some queries that cannot be executed concurrently with any other. Therefore I want to protect the function calls.

Or this is wrong?

Thank you.
User avatar
doublemax
Moderator
Moderator
Posts: 19159
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: wxCriticalSection vs wxMutex vs std::mutex

Post by doublemax »

Or this is wrong?
I can't tell without knowing the "bigger picture".
They can be called many times, but they cannot be executed at the same time.
Why not? Database accesses can run in parallel.

Queries can run in parallel anyway, and writes if they are put into a transaction.

If there are database requests can not run in parallel (for whatever reason), then a mutex (doesn't matter if wxMutex, std::mutex or critical condition) is the way to go. Then one thread will just wait until the lock is free.
Use the source, Luke!
ONEEYEMAN
Part Of The Furniture
Part Of The Furniture
Posts: 7477
Joined: Sat Apr 16, 2005 7:22 am
Location: USA, Ukraine

Re: wxCriticalSection vs wxMutex vs std::mutex

Post by ONEEYEMAN »

doublemax,
According to the MSDN it is a requirement of this specific query - it has to run when no other query is performed.
But my question is actually about protection - as I say with the std::mutex I can just leave the classes intact of the wx dependency.
But using wx classes I can protect the function call itself.

What is better?
Also, I'm already using C++11. So presumably std::mutex is a way to go?

Thank you.
User avatar
doublemax
Moderator
Moderator
Posts: 19159
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: wxCriticalSection vs wxMutex vs std::mutex

Post by doublemax »

Also, I'm already using C++11. So presumably std::mutex is a way to go?
Yes
Use the source, Luke!
Post Reply