C++ Creating an atomic function

10,341

Solution 1

The concept of atomic methods doesnt exist in C++ like it does in Java, where you can define a method as synchronized. The closest you can get to that in C++ would be to create a ScopedMutex class as follows:

class ScopedMutex {
public:
    ScopedMutex(pthread_mutex *m) : theMutex_(m) {pthread_mutex_lock(theMutex_);}
    ~ScopedMutex() { pthread_mutex_unlock(theMutex_); }
    // Add appropriate copy constructors and operator=() to disallow mutex copy
    // Or consider passing in a reference
private:
    pthread_mutex *theMutex_;
};

Then use it like this in your function:

void foo ( Bar* bar , void(Bar::*qux)(void) )
{
    ScopedMutex m(&aMutex); // This mutex must be defined/initialized elsewhere

    if ( bar )
    {
        bar->qux();
    }

    // The ScopedMutex goes out of scope when the function does,
    // thus releasing the lock
}

But this wont do you any good unless you use the same mutex in every other method that uses the bar object.

Scoped Mutex are especially useful when you have a function with complicated logic where there are several return statements, so you dont have to manually unlock the mutex it will be unlocked when the function goes out of scope.

Solution 2

You probably want to use a smart pointer with shared ownership semantics (e.g. shared_ptr, intrusive_ptr) to make sure the object stays alive as long as you refer to it.

Solution 3

You want to temporarily share ownership of the object, in order to prevent another thread from deleting it. This is a job for shared_ptr, using weak_ptr to allow deletion when we don't need to access it:

void foo ( std::weak_ptr<Bar> weak_bar , void(Bar::*qux)(void) ) 
{
    if (std::shared_ptr<Bar> bar = weak_bar.lock())
    {
        // We now share ownership of the object - it won't be deleted
        bar->qux();
    }

    // We have released ownership - it can now be deleted
}

Of course, you still need synchronisation if multiple threads need to access the object; this only solves the problem of deletion specified in the question.

Solution 4

Sorry, but no. C++ doesn't have anything to support that. You don't necessarily need to add the mutex to Bar, but to avoid it, you'll probably need a wrapper around Bar, or something on that order.

Share:
10,341
Kolyunya
Author by

Kolyunya

Developer

Updated on June 06, 2022

Comments

  • Kolyunya
    Kolyunya almost 2 years
    void foo ( Bar* bar , void(Bar::*qux)(void) )
    {
        if ( bar )
        {
            bar->qux();
        }
    }
    

    The problem is:

    1. bar can be deleted after the check by another thread.

    2. I can not add a mutex member to Bar in order to lock it.

    Thus I wonder, if I can tell the processor to run this function atomically, and how would I do so? I've spent way to much time on Google, but found no understandable manuals...

    P.S. Debian, gcc , Boost NOT allowed, C++11 IS allowed.