многопоточность — C ++ Создание атомарной функции

void foo ( Bar* bar , void(Bar::*qux)(void) )
{
if ( bar )
{
bar->qux();
}
}

Проблема в:

  1. bar можно удалить после проверка другим потоком.

  2. Я не могу добавить мьютекс Bar для того, чтобы заблокировать это.

Поэтому мне интересно, могу ли я сказать процессору, чтобы эта функция выполнялась атомарно, и как бы я это сделал? Я провел много времени в Google, но не нашел понятных руководств …

Постскриптум Debian, GCC, Boost НЕ разрешено, C ++ 11 ЯВЛЯЕТСЯ позволил.

3

Решение

Концепция атомарных методов не существует в C ++, как в Java, где вы можете определить метод как синхронизированный. Наиболее близким к этому в C ++ было бы создание класса ScopedMutex следующим образом:

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_;
};

Затем используйте это в своей функции:

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
}

Но это не принесет вам пользы, если вы не используете тот же мьютекс в любом другом методе, который использует объект bar.

Mutex с областью действия особенно полезен, когда у вас есть функция со сложной логикой, где есть несколько операторов возврата, поэтому вам не нужно вручную разблокировать мьютекс, он будет разблокирован, когда функция выйдет из области видимости.

2

Другие решения

Вы, вероятно, хотите использовать умный указатель с семантикой совместного владения (например, shared_ptr, intrusive_ptr), чтобы убедиться, что объект остается живым, пока вы на него ссылаетесь.

4

Вы хотите временно поделиться правами собственности на объект, чтобы предотвратить его удаление другим потоком. Это работа для shared_ptr, с помощью weak_ptr чтобы разрешить удаление, когда нам не нужен доступ к нему:

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
}

Конечно, вам все еще нужна синхронизация, если нескольким потокам необходим доступ к объекту; это только решает проблему удаления, указанную в вопросе.

4

Извините, но не. C ++ не имеет ничего, чтобы поддержать это. Вам не обязательно добавлять мьютекс в Bar, но, чтобы избежать этого, вам, вероятно, понадобится обертка вокруг Barили что-то в этом порядке.

1

У меня тоже есть требование для выполнения 2-х функций атомарно в Thread-1.

Основная тема:

   CMythread* pThread = GetThreadFromPool();
//allocate work to thread
pThread->ResumeThread();

Тема-1:

 AddtoThreadPool(this);
SuspendThread(); //sleep infinitely unless awakened by Main Thread

Проблема:
Основной поток может возобновить поток в пуле до его приостановки.
и Thread-1 (поток пула) может приостановить себя бесконечно.

Решение:
1. Выполните 2 функции в Thread-1 атомарно. Никакое количество защиты не будет работать.
2. Периодически проверяйте пул потоков, чтобы возобновить приостановленный поток, которому была выделена работа.

Спасибо за ваши ответы.

Аджай

0
По вопросам рекламы [email protected]