
Hi Tomas, Thanks for your reply. One thing I forgot to mention is that this is also in the context of writing a proposal for TR2 based on Boost.Asio. Since the filesystem library has already been accepted for TR2 I want to keep the low-level error approach as consistent as possible with it. <snip>
The other problem was that Windows and Unix have a different models of handling errors. On Unix, errors are "syscall sensitive", i.e. there is a limited number of error codes and they sometimes mean slightly different things depending on which system call was invoked. On the other hand, on Windows the error space is "flat" and any system call can essentially return any of the (10000 or so) error values.
Yep, this is exactly the main problem I'm facing. Even on windows the error space may not be truly flat once you incorporate other "system" libraries like OpenSSL say, which use their own error space. <snip>
d) The error handler would then get invoked with the SysResult and it could decide based either on the "System independent" or "system specific" error code, what it should do. The error handler would return one of "CONTINUE", "RETRY", "FAIL" enumerations. The first and second are, I think, self-explanatory. The third would cause the surrounding code to trow an exception, similar to system_error. My default error handlers would do something sensible like retry on EINTR and and throw on other error conditions. I also had a non-throwing version.
This approach is similar to what's currently in asio: - The synchronous functions have overloads that take an Error_Handler function object that can be used to customise what happens when an error occurs. However the Error_Handler does not allow the operation to be restarted. - The higher level asio::read() and asio::write() functions also have a Completion_Condition function object which is passed the error code and the amount of bytes transferred. The return value from this function object indicates whether the underlying operation should be restarted. <snip>
i) Assuming that your "high-level" system operation is implemented in terms of several system calls, what is a good way handling system-specific error codes? My error handlers had the possibility of handling not only the "high- level" library errors but also use the low-level system errnos. However, as you can see, this breaks encapsulation by making assumptions about how the function is implemented in terms of the underlying syscalls.
For most functions in the current asio implementation I think this isn't too bad. They are often relatively thin wrappers around the existing system calls, and in many cases there is already mapping to just one system call. In other cases I think it will have to be a best-effort translation of the error code to something sensible.
ii) The same issue I described above applies equaly well to other functions implemented in terms of several "high-level" (library) system calls. To be able to use the SysResult effectively, you would need to know which function generated it, again breaking encapsulation.
I think the idea with the error_code/system_error approach is to leave the error_code object with very little other than the system error number. However in the case of an exception, the system_error's "what" string can contain more information about the context where the error was generated. Cheers, Chris