Re: [asio-users] asio and good error handling
Brought to you by:
chris_kohlhoff
From: Vinnie F. <vin...@gm...> - 2018-12-28 04:17:50
|
On Thu, Dec 27, 2018 at 5:59 PM Vinícius dos Santos Oliveira <vin...@gm...> wrote: > However I found hard to grasp the difference between error code and error > condition. The “portable” name sometimes associated as the difference has > given me no hints as to whenever to use each one. This was my experience as well. And it is a shame, because error_code and error_condition are incredibly well-designed (now that I finally understand them). The blog posts and tutorials floating around the web can sometimes be a little cryptic with references to "system" errors and that sort of nonsense. I find it easiest to explain error_condition as the equivalent of an "error group." That is, multiple distinct values of error_code can map to the same error_condition. This allows code which can fail to concisely provide the exact cause of failure (error_code) while also allowing the code to determine the general category of error. For example, in a WebSocket implementation, there are many ways that network input can cause a failure. Examples: * A WebSocket Upgrade request specified HTTP/1.0 (instead of the required HTTP/1.1) * A WebSocket Upgrade request is missing the Host field * A frame was received with an illegal opcode * A control frame had the "fragment" bit set Note that the first 2 error codes above are handshake failures, while the last two are protocol errors. If the caller wants to distinguish between a handshake error or a protocol error (a common use-case) they would need to manually check the error code against the list of all known error codes, and know in which grouping they should be placed. Beast reports these four cases as distinct errors: <https://www.boost.org/doc/libs/1_69_0/libs/beast/doc/html/beast/ref/boost__beast__websocket__error.html> The error condition system allows specific error codes to be mapped to general error conditions. In the list above there are two conditions. The first is the "handshake failed" condition, while the second is the "protocol error" condition. In Beast this is represented using an error condition enum: <https://www.boost.org/doc/libs/1_69_0/libs/beast/doc/html/beast/ref/boost__beast__websocket__condition.html> Thanks to the magic (or curse) of argument dependent lookup in the design of error_code, comparisons of error codes against error conditions Just Work. Believe it or not, this compiles and works: boost::system::error_code ec = websocket::error::bad_http_version; BOOST_ASSERT(ec == websocket::condition::handshake_failed); We are actually comparing an error_code initialized from the specific, low-level error, against an error condition which represents a high level, generic grouping of websocket failure modes. That's amazing! The beauty of this wonderfully designed error system is that I can add more error codes that existing users don't know about, and map my error codes to the known conditions, then any user code which compares beast errors against the predefined error conditions will Just Work when one of the new error codes is returned. C++ really deserves a better set of documentation that explains in clear and simple terms how error codes and error conditions work, it took me quite a while to figure out and I hear from other people that they have the same experience. error_code is a little C++ gem waiting to be discovered by the general public. Regards |