Как подождать, пока отдельный отрезок будет завершен на C++?Подождите, пока выделенная нить закончится на C++
Мне не нужен статус выхода, я просто хочу знать, закончилась ли нить.
Я пытаюсь предоставить синхронную обертку вокруг асинхронного третьего инструмента. Проблема заключается в непредвиденном крушении гонки, включающем обратный вызов. Прогрессия:
- Я называю ThirdParty, и зарегистрировать функцию обратного вызова
- когда ThirdParty заканчивается, он уведомляет меня, используя функцию обратного вызова - в отдельном потоке у меня нет реального контроля над.
- Я хочу, чтобы поток из (1) дождался (2).
Я хочу обернуть это механизмом, который обеспечивает блокирующий вызов. До сих пор у меня есть:
class Wait {
public:
void callback() {
pthread_mutex_lock(&m_mutex);
m_done = true;
pthread_cond_broadcast(&m_cond);
pthread_mutex_unlock(&m_mutex);
}
void wait() {
pthread_mutex_lock(&m_mutex);
while (!m_done) {
pthread_cond_wait(&m_cond, &m_mutex);
}
pthread_mutex_unlock(&m_mutex);
}
private:
pthread_mutex_t m_mutex;
pthread_cond_t m_cond;
bool m_done;
};
// elsewhere...
Wait waiter;
thirdparty_utility(&waiter);
waiter.wait();
Насколько я могу судить, это должно работать, и это обычно делает, но иногда он выходит из строя. Насколько я могу судить из Файл_дампа, мое предположение, как к этой проблеме заключается в следующем:
- Когда обратный вызов транслирует конец m_done, ждать поток просыпается
- Ждания нить теперь делаются здесь, и Wait уничтожен. Все члены Wait уничтожены, включая мьютекс и cond.
- Обратный поток пытается продолжить работу с точки широковещательной передачи, но теперь использует память, которая была выпущена, что приводит к повреждению памяти.
- Когда обратный поток пытается вернуться (выше уровня моего плохого метода обратного вызова), программа вылетает (обычно с помощью SIGSEGV, но я видел SIGILL пару раз).
Я пробовал много разных механизмов, чтобы попытаться исправить это, но ни одна из них не решила проблему. Я все еще вижу случайные сбои.
EDIT: Подробнее:
Это является частью массово многопоточного приложения, поэтому создание статического Wait не практично.
Я проверил тест, создав Wait on the heap и сознательно пропуская память (т. Е. Объекты Wait никогда не освобождаются), и это не привело к сбоям. Поэтому я уверен, что это проблема «Подождите, если вы освободите ее слишком рано».
Я также пробовал тест с sleep(5)
после разблокировки в wait
, и это также не приводило к сбоям. Однако я ненавижу полагаться на такой клочок.
EDIT: ThirdParty детали:
Я не думаю, что это было актуально в первый, но чем больше я думаю об этом, тем больше я думаю, что это реальная проблема:
ThirdParty материал Я упомянул, и почему я не контролирую поток: это использует CORBA.
Итак, возможно, что CORBA удерживает ссылку на мой объект дольше, чем предполагалось.
К сожалению, это приложение в многопользовательском режиме, и нам действительно нужны отдельные объекты Wait для каждого - в противном случае это слишком сильно замедляет нас. – Tim
Кроме того, если мы используем статический Wait, возникает проблема с попыткой координировать, какой поток необходимо возобновить. – Tim
Хорошо, вы можете это сделать.Вы можете добавить поле refcount к объекту Wait, защищенному глобальным мьютексом. Запустите refcount на 2, а затем выполните обратный вызов, и официант уменьшит пересчет при завершении. Если глобальный мьютекс становится вашим узким местом, существуют и другие более сложные решения. –