Re[3]: api design: return code or exception - formal criteri
От: Николай Ивченков  
Дата: 31.08.09 19:53
Оценка:
По-моему, вопрос изначально нужно поставить так: нужна ли раскрутка стека для обработки исключительной ситуации? Если мы предполагаем, что в ряде случаев она нужна (полезна), то следует предоставить функцию, генерирующую исключение. Если мы предполагаем, что в ряде случаев исключительную ситуацию нужно обрабатывать на месте и при этом использование кодов исключительных ситуаций возможно и получается заметно удобнее/эффективнее, чем использование try/catch, то следует предоставить функцию, сообщающую код исключительной ситуации. Соответственно, если подходят оба случая, то следует предоставить оба варианта (выше было показано, как это можно сделать). Отмечу, что это применимо к исключительным ситуациям вообще, а не только к ошибкам. Например, то, что пользователь захотел отменить какое-то длительное вычисление, ошибкой не является, но является исключительной ситуацией, и раскрутку стека при этом удобно выполнить через генерацию исключения (как видно, именно удобство механизма исключений даёт повод к его применению).
Re[3]: api design: return code or exception - formal criteri
От: jazzer Россия Skype: enerjazzer
Дата: 01.09.09 05:12
Оценка:
Здравствуйте, Andrew S, Вы писали:

J>>О, я придумал формальный критерий: всегда должны использоваться исключения, потому что они обеспечивают гарантию непродолжения в случае ошибки, не давая програмисту неявно ошибиться.


AS>Удобство использования страдает. Пример — тот же File.

Да ладно, где оно там так уж фатально страдает?
В примере с перебором файла разницы практически никакой.

AS>В результате разработчик будет делать как ему удобнее — не проверять коды. Плюсом придется писать кучу апгрейдов из одного интерфейса в другой...


Имхо, удобнее как раз с исключениями — ничего явно не надо проверять и бояться, что что-то забыл проверить и пытаешься записать в неоткрытый файл (например).

Еще раз, идея следующая — коды ошибок должны рассмативаться как оптимизация (да, и еще один случай забыл — когда пишем небросающий код для обеспечения безопасности исключений).
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[2]: api design: return code or exception - formal criteri
От: Кодт Россия  
Дата: 01.09.09 10:34
Оценка:
Здравствуйте, minorlogic, Вы писали:

M>1. в конструкторе обертки над мютексом, мы не смогли создать именованный мютекс. В этом случае лучше кинуть ексепшен, потому что объект повиснет в невалидном состоянии. Если этого не делать , то пользователь класса может и забыть проверить валидное создание объекта.


Согласен.
И вообще, временный объект любого типа может быть участником выражения, а не отдельного стейтмента.
Прервать вычисление выражения можно только через исключение.
Либо срезать углы, тщательно проверяя операнды (подобно тому, как в плавающей арифметике поступают с NaN).

M>2. Объект поток не смог открыться и вернул напримр false в методе stream.open(), после этого любая попытка прочесть из него или записать должны кидать эксепшены.


А вот здесь можно и ассерты, ибо если пользователь не проверил возвращаемое значение — он ССЗБ.
Вообще, у потоков есть флаг ошибки, срезающий углы.
... << RSDN@Home 1.2.0 alpha 4 rev. 1237>>
Перекуём баги на фичи!
Re: api design: return code or exception - formal criteria
От: slava_phirsov Россия  
Дата: 01.09.09 16:26
Оценка:
Здравствуйте, Andrew S, Вы писали:

AS>Если есть ссылки критерии, best practice или что-нибудь подобное — будет супер.


Скотт Майерс, "Эффективное использование C++: 35 новых рекомендаций", глава 3, в особенности Правило 15 "Оценивайте затраты на обработку исключений"

Почитал-почитал, и понял, почему разработчики известных мне библиотек так осторожно относятся к использованию исключений.

P.S. Хотя, возможно, эта книга устарела? Написана 13 лет назад, а, как мне снисходительно пояснил на собеседовании один "молодой, да ранний" гуру вкуривший непосредственно стандарт, "С тех пор C++ радикально изменился".
Люди! Люди, смотрите, я сошел с ума! Люди! Возлюбите друг друга! (вы чувствуете, какой бред?)
Re[3]: api design: return code or exception - formal criteri
От: Andrew S Россия http://alchemy-lab.com
Дата: 01.09.09 18:51
Оценка:
M>>2. Объект поток не смог открыться и вернул напримр false в методе stream.open(), после этого любая попытка прочесть из него или записать должны кидать эксепшены.

К>А вот здесь можно и ассерты, ибо если пользователь не проверил возвращаемое значение — он ССЗБ.


На мой взгляд в этом случае именно что ассерты. Пользователь продолжает пользовать невалидный объект — значит ошибка в логике программы, а ошибку в логике надо по возможности отлавливать никак не в релизе. Эксепшены только в случае, если слой более низкого уровня вернул "плохую" ошибку. На плохой хендл, например, многие api так и сделают, так что автоматически без "лишней" рантайм проверки в релизе все будет выглядеть как надо.

Но, тут появляется неожиданная тонкость. Возьмем, к примеру, unique_lock а-ля буст:

        void lock()
        {
            if(owns_lock())
            {
                throw boost::lock_error();
            }
            m->lock();
            is_locked=true;
        }


Правомерно ли тут использование именно исключения, а не ассерта? На самом деле, вопрос интересный. С одной стороны, ситуация похожа на то, что мы видели ранее со стримом. С другой стороны, ситуация _кардинально_ отличается. В случае со стримом кейс, где идет работа далее с невалидным объектом — основной сценарий использования. Тут же — дополнительный (например, из-за ошибки пытаемся залочить рекурсивно). Разница в том, что в одном случае это отлавливается сразу же, и не приводит к фатальному изменению состояния объекта (ну или не должна приводить). Тут же — приводит, очевидным образом, сделав 2 раза лок (первый раз неявно, в конструкторе), сделать 2 раза анлок мы уже не сможем, по вполне очевидным причинам
Стоит ли тут использовать исключения или assert? Я, например, не знаю. Мнения?

В общем, вот все это и хочется формализовать
Более того, надо еще учесть и требования к перфомансу. Но это вторично. Главное — не дать проигнорировать фатальную ошибку, ну и не писАть лишнего — как проверок возвращаемых кодов, так и лишних try-catch. И то, и то, на мой взгляд, вполне сравнимое зло.
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[4]: api design: return code or exception - formal criteri
От: Andrew S Россия http://alchemy-lab.com
Дата: 01.09.09 18:54
Оценка:
J>>>О, я придумал формальный критерий: всегда должны использоваться исключения, потому что они обеспечивают гарантию непродолжения в случае ошибки, не давая програмисту неявно ошибиться.

AS>>Удобство использования страдает. Пример — тот же File.

J>Да ладно, где оно там так уж фатально страдает?

Например, проходимся по списку файлов, пробуем открыть. Если нет — ничего страшного, пробуем следующий. На мой взгляд, именно для таких кейсов в файла помимо конструктора должна быть еще и open. Кроме того, open может возвращать расширенный статус — например, успешность + то, что файл уже существовал. Это позволяет во многих случаях _значительно_ упростить логику за счет атомарности такой проверки. Из того же конструктора такой функциональности нормальным способом не добиться.

J>В примере с перебором файла разницы практически никакой.


AS>>В результате разработчик будет делать как ему удобнее — не проверять коды. Плюсом придется писать кучу апгрейдов из одного интерфейса в другой...


J>Имхо, удобнее как раз с исключениями — ничего явно не надо проверять и бояться, что что-то забыл проверить и пытаешься записать в неоткрытый файл (например).


J>Еще раз, идея следующая — коды ошибок должны рассмативаться как оптимизация (да, и еще один случай забыл — когда пишем небросающий код для обеспечения безопасности исключений).
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[5]: api design: return code or exception - formal criteri
От: Юрий Жмеренецкий ICQ 380412032
Дата: 01.09.09 21:29
Оценка:
Здравствуйте, Andrew S, Вы писали:

J>>>>О, я придумал формальный критерий: всегда должны использоваться исключения, потому что они обеспечивают гарантию непродолжения в случае ошибки, не давая програмисту неявно ошибиться.


AS>>>Удобство использования страдает. Пример — тот же File.

J>>Да ладно, где оно там так уж фатально страдает?

AS>Например, проходимся по списку файлов, пробуем открыть. Если нет — ничего страшного, пробуем следующий.


А что будет дальше, после успешного открытия? Врядли сохранение объекта file в массиве... Чтение/запись, какая-то обработка — все эти операции также могут кидать исключения. Даже если решить "проблему" c open, вероятность получить в итоге подобный код:

for(...)
{
  if(boost:optional<file> f = open_file(...))
    process_file(*f);
}

//...
void process_file(file& f)
{
  try
  {
    // read/write
    // some action
    // ...
  }
  catch(const runtime_error& ex)
  {    
    handle_exception(ex);
  }
}


имеется. Собственно вопрос — почему бы сразу не использовать кидающий конструктор для открытия в функции process_file (или во вложенной функции, в случае если process_file только обрабатывает исключения)? Или предполагается переписать process_file на версию, в которой используются некидающие варианты всех вызываемых функций (для избавления от try/catch)?
Re[4]: api design: return code or exception - formal criteri
От: Юрий Жмеренецкий ICQ 380412032
Дата: 01.09.09 22:05
Оценка:
Здравствуйте, Andrew S, Вы писали:

AS>Но, тут появляется неожиданная тонкость. Возьмем, к примеру, unique_lock а-ля буст:


AS>
AS>        void lock()
AS>        {
AS>            if(owns_lock())
AS>            {
AS>                throw boost::lock_error();
AS>            }
            m->>lock();
AS>            is_locked=true;
AS>        }
AS>


AS>Правомерно ли тут использование именно исключения, а не ассерта? На самом деле, вопрос интересный. С одной стороны, ситуация похожа на то, что мы видели ранее со стримом. С другой стороны, ситуация _кардинально_ отличается. В случае со стримом кейс, где идет работа далее с невалидным объектом — основной сценарий использования. Тут же — дополнительный (например, из-за ошибки пытаемся залочить рекурсивно). Разница в том, что в одном случае это отлавливается сразу же, и не приводит к фатальному изменению состояния объекта (ну или не должна приводить). Тут же — приводит, очевидным образом, сделав 2 раза лок (первый раз неявно, в конструкторе), сделать 2 раза анлок мы уже не сможем, по вполне очевидным причинам

AS>Стоит ли тут использовать исключения или assert? Я, например, не знаю. Мнения?

Конкретно здесь, если рассматривать только unique_lock — assert, т.к. очевидно нарушение предусловия: owns_lock() == false. + есть метод для проверки(owns_lock), + еще некоторые аргументы. Но Lockable Concept (к которой относится lock) не содежит функции owns_lock, поэтому предусловия невозможно обобщить в общем случае. Скорее всего так сделано для дальнейшего расширения набора lock types.

Lockable Concept

The Lockable concept models exclusive ownership. A type that implements the Lockable concept shall provide the following member functions:

void lock();
bool try_lock();
void unlock();

void lock()

Effects:
The current thread blocks until ownership can be obtained for the current thread.

Postcondition:
The current thread owns *this.

Throws:
boost::thread_resource_error if an error occurs.


При такой формулировке (общей для всех lock types), с отсутствующими предусловиями — возбуждение исключения единственно верный вариант.
Re[2]: api design: return code or exception - formal criteri
От: pivcorp Россия  
Дата: 02.09.09 01:32
Оценка:
Здравствуйте, slava_phirsov, Вы писали:

_>Почитал-почитал, и понял, почему разработчики известных мне библиотек так осторожно относятся к использованию исключений.


_>P.S. Хотя, возможно, эта книга устарела? Написана 13 лет назад, а, как мне снисходительно пояснил на собеседовании один "молодой, да ранний" гуру вкуривший непосредственно стандарт, "С тех пор C++ радикально изменился".


ИМХО книга отнюдь не устарела.
C++ конечно изменился, но исключения были и тогда, а реализация стандартом не определяется.
Что изменилось, так это аппаратное обеспечение — компы стали пошустрее.
Но всё равно в гэйм деве зачастую исключения отключают нафиг — производительность страдает.
Re[4]: api design: return code or exception - formal criteri
От: Quasi  
Дата: 02.09.09 12:12
Оценка:
Здравствуйте, gear nuke, Вы писали:

GN>В последней ревизии немного другой подход:

GN>
void f(error_code& ec=throws());
здесь


Тот же подход в boost
void f(boost::system::error_code& ec = boost::system::throws);

Нельзя невольно проигнорировать ошибку, исключает необходимость дублирования интерфейса
Re[3]: api design: return code or exception - formal criteri
От: jazzer Россия Skype: enerjazzer
Дата: 02.09.09 12:34
Оценка:
Здравствуйте, pivcorp, Вы писали:

P>Но всё равно в гэйм деве зачастую исключения отключают нафиг — производительность страдает.


К чему я и клоню: разработка без исключений — это оптимизация.
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[4]: api design: return code or exception - formal criteri
От: slava_phirsov Россия  
Дата: 02.09.09 17:15
Оценка: +1
Здравствуйте, jazzer, Вы писали:

J>К чему я и клоню: разработка без исключений — это оптимизация.


Не согласен. Это просто другой подход к разработке. Где-то выше уже поминался iostream, в котором исключения не используются, а используются флаги. ИМХО, в C++ надо десять раз подумать, прежде чем кидаться исключениями. Слышал такой аргумент: "А если в клиентском коде не обрабатываются коды ошибок?". ОК, а если автор клиентского кода засунет функцию генерирующую исключение в try-catch с пустым блоком catch — лучше будет? Ну да, это немного потруднее чем просто проигнорировать код ошибки. Но для копипэйстных кодеров (нормальный-то кодер ИМХО не станет игнорировать код ошибки)- не проблема, и лично я такую стратегию наблюдал неоднократно.
Люди! Люди, смотрите, я сошел с ума! Люди! Возлюбите друг друга! (вы чувствуете, какой бред?)
Re[5]: api design: return code or exception - formal criteri
От: Andrew S Россия http://alchemy-lab.com
Дата: 02.09.09 17:29
Оценка: +1
ЮЖ>

ЮЖ>Lockable Concept

ЮЖ>The Lockable concept models exclusive ownership. A type that implements the Lockable concept shall provide the following member functions:

ЮЖ>void lock();
ЮЖ>bool try_lock();
ЮЖ>void unlock();

ЮЖ>void lock()

ЮЖ>Effects:
ЮЖ>The current thread blocks until ownership can be obtained for the current thread.

ЮЖ>Postcondition:
ЮЖ>The current thread owns *this.

ЮЖ>Throws:
ЮЖ>boost::thread_resource_error if an error occurs.


ЮЖ>При такой формулировке (общей для всех lock types), с отсутствующими предусловиями — возбуждение исключения единственно верный вариант.


Не согласен. Приведенная формулировка концепта никоим образом не влияет на то, что именно должен делать lock холдер в случае нарушения _своего_ предусловия. Оунер может быть и рекурсивным. Assert ровно такое же средство уведомления о нарушении контракта, как и исключение. Вот только объект lock холдер после него в релизе останется в невалидном состоянии. Т.е. тут совсем другая ситуация, чем в случае с handle holder (ака File), который даже после нарушения контракта все равно останется валидным.
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[6]: api design: return code or exception - formal criteri
От: Andrew S Россия http://alchemy-lab.com
Дата: 02.09.09 17:31
Оценка:
J>>>>>О, я придумал формальный критерий: всегда должны использоваться исключения, потому что они обеспечивают гарантию непродолжения в случае ошибки, не давая програмисту неявно ошибиться.

AS>>>>Удобство использования страдает. Пример — тот же File.

J>>>Да ладно, где оно там так уж фатально страдает?

AS>>Например, проходимся по списку файлов, пробуем открыть. Если нет — ничего страшного, пробуем следующий.


ЮЖ>А что будет дальше, после успешного открытия? Врядли сохранение объекта file в массиве... Чтение/запись, какая-то обработка — все эти операции также могут кидать исключения. Даже если решить "проблему" c open, вероятность получить в итоге подобный код:


После этого может быть все что угодно. Например, инициация асинхронной операции, где, как вы понимаете, исключений быть не может.
В общем, не стОит упрощать — File слишком сложный объект, чтобы так просто описать все его юзе кейсы.
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[5]: api design: return code or exception - formal criteri
От: jazzer Россия Skype: enerjazzer
Дата: 02.09.09 22:09
Оценка: +2
Здравствуйте, slava_phirsov, Вы писали:

_>Здравствуйте, jazzer, Вы писали:


J>>К чему я и клоню: разработка без исключений — это оптимизация.


_>Не согласен. Это просто другой подход к разработке. Где-то выше уже поминался iostream, в котором исключения не используются, а используются флаги.

Во-первых, ты мешаешь все в кучу.
Там флаги состояния потока (которые устанавливаются функцией setstate!). А это значит, что реализуется конечный автомат, и к исключениям это никакого отношения не имеет.
А вот как сигнализировать о том, что пользователь пытается выполнить операцию, которая недопустима для текущего состояния или переводит поток в плохое состояние (failbit) — тут можно использовать и исключения, и коды.

Во-вторых, неплохо бы такие утверждения проверять и не верить им на слово.
Открываем стандарт и чуть ли не в каждом абзаце видим:

If ......, calls setstate(failbit), which may throw ios_base::failure (27.4.4.3).

что же означает may throw?
Это означает, что iostream можно сконфигурировать как для бросания исключений, так и молчаливого возврата.
Смотрим 27.4.4 и видим такую пару функций:

iostate exceptions() const;
void exceptions(iostate except);

A mask that determines what elements set in rdstate() cause exceptions to be thrown.


_>ИМХО, в C++ надо десять раз подумать, прежде чем кидаться исключениями.

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

_>Слышал такой аргумент: "А если в клиентском коде не обрабатываются коды ошибок?". ОК, а если автор клиентского кода засунет функцию генерирующую исключение в try-catch с пустым блоком catch — лучше будет? Ну да, это немного потруднее чем просто проигнорировать код ошибки.

Именно что потруднее, но главное даже не это, главное, что пустой catch очень хорошо виден, и code review такой код просто не пройдет.

_>Но для копипэйстных кодеров (нормальный-то кодер ИМХО не станет игнорировать код ошибки)- не проблема, и лично я такую стратегию наблюдал неоднократно.

Против копипейстных кодеров, кроме code review, вообще приема нет, это диверсанты.
Также я видел море кода нормальных кодеров (включая себя), которые забывали проверять коды ошибок.

Еще раз: проблема кодов ошибок — это их невидимость.
Вызов функции, которая ничего не возвращает, в коде никак не отличается от вызова функции, которая возвращает код ошибки.
Вот это на 4.5 порядка сложнее отследить, чем написанный большими русскими буквами пустой catch.

Ну и обработка кодов ошибок очень сильно захламляет код, в отличие от кода, написанного с исключениями, в котором основная линия исполнения программы (т.е. когда не происходит ошибок) незамусорена и легко читается (== легко поддерживается).
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[6]: api design: return code or exception - formal criteri
От: Юрий Жмеренецкий ICQ 380412032
Дата: 03.09.09 02:59
Оценка:
Здравствуйте, Andrew S, Вы писали:

ЮЖ>>

ЮЖ>>Lockable Concept

ЮЖ>>The Lockable concept models exclusive ownership. A type that implements the Lockable concept shall provide the following member functions:

ЮЖ>>void lock();
ЮЖ>>bool try_lock();
ЮЖ>>void unlock();

ЮЖ>>void lock()

ЮЖ>>Effects:
ЮЖ>>The current thread blocks until ownership can be obtained for the current thread.

ЮЖ>>Postcondition:
ЮЖ>>The current thread owns *this.

ЮЖ>>Throws:
ЮЖ>>boost::thread_resource_error if an error occurs.


ЮЖ>>При такой формулировке (общей для всех lock types), с отсутствующими предусловиями — возбуждение исключения единственно верный вариант.


AS>Не согласен. Приведенная формулировка концепта никоим образом не влияет на то, что именно должен делать lock холдер в случае нарушения _своего_ предусловия.


Очень даже влияет — объект, моделирующий этот концепт, не должен усиливать предусловия (и ослаблять постусловия) для функции lock. unique_lock не имеет "своего" предусловия для ф-ии lock, т.к:

Specializations of boost::unique_lock model the TimedLockable concept if the supplied Lockable type itself models TimedLockable concept (e.g. boost::unique_lock<boost::timed_mutex>), or the Lockable concept otherwise.

Re[5]: api design: return code or exception - formal criteri
От: jazzer Россия Skype: enerjazzer
Дата: 03.09.09 03:37
Оценка:
Здравствуйте, Quasi, Вы писали:

Q>void f(boost::system::error_code& ec = boost::system::throws);


Q>Нельзя невольно проигнорировать ошибку, исключает необходимость дублирования интерфейса

И исключает возможность привязки по указателю на функцию
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[4]: api design: return code or exception - formal criteri
От: jazzer Россия Skype: enerjazzer
Дата: 03.09.09 04:18
Оценка: 1 (1)
Здравствуйте, gear nuke, Вы писали:

GN>Здравствуйте, Andrew S, Вы писали:


AS>>вот такое раздвонение интерфейса.


GN>В последней ревизии немного другой подход:

GN>
void f(error_code& ec=throws());
здесь


вообще-то соответствующий баг все еще в состоянии Open, так что окончательное решение еще не принято.
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[5]: api design: return code or exception - formal criteri
От: Юрий Жмеренецкий ICQ 380412032
Дата: 03.09.09 06:31
Оценка: +1
Здравствуйте, slava_phirsov, Вы писали:

_>Здравствуйте, jazzer, Вы писали:


J>>К чему я и клоню: разработка без исключений — это оптимизация.


_>Не согласен. Это просто другой подход к разработке.


Другой подход — это следствие, причем весьма заметное, т.к. влияет на дизайн в целом, и не редко, в худшую сторону. Как минимум, контракты становятся "толще", и соответственно повышается вероятность ошибки в самом контракте, не говоря уже о реализации и использовании.

Можно услышать такой аргумент против — при использовании исключений приходится отдавать дань за удобство в виде abstraction penalty, а именно — снижение производительности. Этот аргумент может быть актуальным, а может быть и нет. Реальное снижение производительности может быть вызвано неправильным использованием — логика на исключениях, либо использованием в контекстах, в которых стоимость производимых операций одного порядка со стоимостью затрат на поддержку исключений. Оторванные от контекста заявления вроде 'исключения снижают производительность' — не более чем сферокони. Для проверки так это или нет — нужно смотреть конктерную ситуацию. Плюс, адекватное сравнение производительности двух подходов выполнить достаточно сложно.

Так же на нераспростроненность исключений (косвенно это можно назвать 'другим подходом') сказывается соседство с С и наличие огромного количества legacy кода без использования исключений. Некоторые особенности "модульной" системы С++ (осутствие единого, полностью специфицированного ABI), таже не поощеряют исключения.

_>... ИМХО, в C++ надо десять раз подумать, прежде чем кидаться исключениями.

Безусловно, использование исключений требует некоторой дисциплины. Но осязаемых бенефитов в совокупности в результате больше, имхо.

PS: Здесь — How much does Exception Handling cost, really? есть небольшой обзор по поводу затрат на поддержку исключений.
Re[5]: api design: return code or exception - formal criteri
От: Николай Ивченков  
Дата: 03.09.09 11:56
Оценка:
Юрий Жмеренецкий:

ЮЖ>Throws:

ЮЖ>boost::thread_resource_error if an error occurs. [/q]

ЮЖ>При такой формулировке (общей для всех lock types), с отсутствующими предусловиями — возбуждение исключения единственно верный вариант.


Какой же он верный, когда boost::lock_error и boost::thread_resource_error — это два несвязанных наследованием исключения? IMHO, тут в любом случае несоответствие концепции получается. Здесь, вероятно, нужна более общая концепция — что-то вроде OnceLockable. Объект, соответствующий концепции Lockable (MultiLockable), мог бы быть использован как OnceLockable, но не наоборот.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.