Сделал вот такой класс двунаправленного связанного списка http://pastebin.com/JRsWwaKS. По понятным причинам он не является thread-safe. Поэтому я любые обращения к нему защищаю с помощью pthread mutex. И всегда думал - «если есть потоконебезопасный код, то защищаешь его mutex, теряешь какую-то производительность, зато работаешь как обычно». А вот нифига.
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
List list;
void* thread_func(void* arg) {
	ListItem item;
	while (true) {
		pthread_mutex_lock(&mutex);
		list.insertHead(&item);
		pthread_mutex_unlock(&mutex);
	}
}
int main() {
	pthread_t threads[2];
	pthread_create(&threads[0], nullptr, thread_func, nullptr);
	pthread_create(&threads[1], nullptr, thread_func, nullptr);
	while (true) {
		pthread_mutex_lock(&mutex);
		ListItem* item;
		do {
			item = list.removeTail();
		} while (item);
		pthread_mutex_unlock(&mutex);
	}
	return 0;
}
Это небольшой тестовый код. Два потока добавляют элементы в список (добавление одного и того же элемента допустимо, ведь в функциях добавления есть проверка, что элемента ещё нет в списке и они просто вернут false). А другой извлекает все доступные элементы. Пример абстрактный, в реальном приложении над элементами списка ещё и совершают всякие полезные действия (а ещё иногда спят и т. д.). Почему mutex не интегрирован в класс списка? Потому что опять же в реальном коде списки являются частями более сложных структур, которые уже имеют свои mutex. Это чтобы избежать стилистических замечаний. Вышеприведённый код 100% блокирует все операции со списком, хотя и делает это не в ООП стиле.
И в итоге что я получаю? А получаю я срабатывание assert(retval) в функции List::removeTail. А это может означать лишь одно - в списке числится (и не просто числится, а числится хвостом списка) элемент, у которого m_list == nullptr. Что и подтверждается, если посмотреть отладчиком после abort из-за проваленного assert. Значит либо ошибка в реализации алгоритма списка (но в однопоточных тестах вроде проблем не было), либо я что-то делаю не так с блокировками.
Я понимаю, что скорее всего у меня возникло некоторое непонимание с тем как писать многопоточные приложения на C++ и считаю, что данный пример позволит наконец-то во всём разобраться (ибо он не сложный, кода мало и я могу легко сделать минимально рабочий пример). А ещё я собираюсь читать книгу про многопоточное программирование в C++, однако хотелось бы получить первые замечания быстрее, чем я её прочитаю.
P. S.: Тестовый код компилирую без каких-либо оптимизаций.
UPD: Посыпаю голову пеплом. Ошибка была в том что функции добавления таки не проверяли проверку item->m_list. Сейчас всё работает.


