На это невозможно ответить без знания хотя бы фактического интерфейса класса.В общем случае ответ будет отрицательным.
С практической точки зрения C ++, если класс не предназначен для расширения, каждый не виртуальный метод не будет переопределен, и в результате вы можете получить смесь из некоторых поточно-безопасных и некоторыхметоды, не поддерживающие потоки.
Даже если вы решите обернуть (без наследования) и принудительно делегировать только во время удержания блокировки, этот подход все еще не действителен во всех случаях.Для обеспечения безопасности потоков требуется не только блокировка, но и интерфейс, который можно сделать потокобезопасным.
Рассмотрим реализацию stack
, как в STL, просто добавив слой блокировки (т.е. сделав каждый метод потокобезопасным, выне будет гарантировать безопасность потоков в контейнере. Рассмотрим несколько потоков, добавляющих элементы в стек, и два потока, извлекающих информацию:
if ( !stack.empty() ) { // 1
x = stack.top(); // 2
stack.pop(); // 3
// operate on data
}
Существует ряд возможных вещей, которые могут пойти не так: здесь могут выполняться оба потокапроверить [1], когда в стеке есть один элемент, а затем ввести последовательно, в этом случае второй поток завершится с ошибкой в [2] (или получить то же значение и потерпеть неудачу в [3]), даже в случае несколькихобъекты в контейнере, оба потока могут выполнить [1] и [2] до того, как любой из них выполнит [3], и в этом случае оба потока будут использовать один и тот же объект, а второй элемент в стеке будет отброшен без обработки...
Безопасность потоков требует (в большинстве случаев) изменений в API, в exaНесколько выше, интерфейс, который обеспечивает bool pop( T& v );
, реализованный как:
bool stack::try_pop( T& v ) { // argument by reference, to provide exception safety
std::lock<std:mutex> l(m);
if ( s.empty() ) return false; // someone consumed all data, return failure
v = s.top(); // top and pop are executed "atomically"
s.pop();
return true; // we did consume one datum
}
Конечно, есть и другие подходы, вы можете не возвращать ошибку, а скорее ждать условия в операции pop
, которая гарантированноблокировка до тех пор, пока данные не будут готовы, используя условную переменную или что-то подобное ...