Я думаю о создании класса, который представляет владение примитива синхронизации, что-то вроде этого:
class CCriticalSectionLock
{
public:
CCriticalSectionLock( CCriticalSection &cs ) : cs( cs )
{ cs.Enter(); }
~CCriticalSectionLock()
{ cs.Leave(); }
private:
CCriticalSection &cs;
};
Это выглядит как хороший способ получить право собственности во время выполнения функции и обеспечить освобождение владельца, даже если существует несколько точек выхода или исключений. Это, однако, поднимает некоторые тонкие вопросы о том, когда именно компилятор будет оценивать различные вещи. Рассмотрим следующее использование:
int MyMethod( void )
{
not_locked(); // do something not under lock
CCriticalSectionLock myLock( someCriticalSection );
locked(); // do something under lock
return ...; // some expression
}
AFAIK, правила жизни C ++ гарантируют, что not_locked()
будет называться до замок взят, и это locked()
будет вызван, пока блокировка удерживается.
Тем не менее, я не совсем понимаю, когда именно будет вычислено возвращаемое выражение. относительно точки, в которой вызывается деструктор блокировки. Гарантируется ли, что выражение будет оценено до деструктор? Я бы так подумал, но я не уверен на 100%, и в противном случае это может привести к очень тонким, прерывистым, труднодоступным ошибкам!
Если бы они не были, это было бы очень проблематично.
Действительно, рассмотрим следующий код:
int function(){
MyClass myObject;
//stuff
return 5 + myObject.getNumericalValue();
}
с getNumericalValue()
простая функция-член, которая возвращает int на основе вычислений для переменной-члена. Если выражение было оценено после уничтожения myObject
, вы бы имели неопределенное поведение, и использование локальных операторов было бы невозможно в выражении return (что не так).
В вашем случае замок будет разрушен после оценка возврата заявления.
Чтобы добавить к этому некоторую строгость, позвольте мне процитировать стандарт (§3.7.3 / 3, выделение мое):
Если переменная с автоматической продолжительностью хранения имеет инициализацию или деструктор с побочными эффектами, это не должно
быть уничтоженным до конца своего блока, и при этом это не должно быть устранено как оптимизация, даже если это кажется
быть неиспользованным
Конец блока для функции после ответное заявление.
Других решений пока нет …