Changes between Version 42 and Version 43 of BestPracticeHandbook


Ignore:
Timestamp:
Jun 11, 2015, 3:28:11 AM (7 years ago)
Author:
Niall Douglas
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • BestPracticeHandbook

    v42 v43  
    492492      // If a temporary failure, this is an expected unexpected outcome
    493493      if(EBUSY==code || EISDIR==code || ELOOP==code || ENOENT==code || ENOTDIR==code || EPERM==code || EACCES==code)
    494         return std::make_unexpected(std::error_code(code, generic_category());
     494        return std::make_unexpected(std::error_code(code, std::generic_category());
    495495
    496496      // If a non-temporary failure, this is an unexpected outcome
    497       std::string errstr(strerror(code));
    498       return std::make_unexpected(std::make_exception_ptr(std::system_error(ec, std::move(errstr))));
     497      return std::make_unexpected(std::make_exception_ptr(std::system_error(code, std::generic_category(), strerror(code))));
    499498    }
    500499    return std::make_shared<handle_type>(fd);
     
    516515You may have noticed though the (Strongly) in the title of this section being in brackets, and if you guessed there are caveats in the above then you are right. The first big caveat is that the expected<T, E> implementation in Boost.Expected is very powerful and full featured, but unfortunately has a big negative effect on compile times, and that rather ruins it for the majority of people who only need about 10% of what it provides (and would rather like that to be quick to compile). The second caveat is that integration between Expected and Future-Promise especially with resumable functions in the mix is currently poorly defined, and using Expected now almost certainly introduces immediate technical debt into your code that you'll have to pay for later.
    517516
    518 The third caveat is that I personally plan to write a much lighter weight monadic result transport which isn't as flexible as expected<T, E> (and probably hard coded to a T, error_code and exception_ptr outcomes) but would have negligible effects on compile times, and very deep integration with a non-allocating all-constexpr new lightweight future-promise implementation. Once implemented, my monadic transport may be disregarded by the community, evolved more towards expected<T, E>, or something else entirely may turn up.
     517The third caveat is that [https://github.com/ned14/boost.spinlock/blob/master/include/boost/spinlock/monad.hpp I have written a much lighter weight monadic result transport] which isn't as flexible as expected<T, E> (and is hard coded to a T, error_code and exception_ptr outcomes) but has negligible effects on compile times, and very deep integration with a forthcoming non-allocating all-constexpr new lightweight future-promise implementation. Once implemented, my monadic transport may be disregarded by the community, evolved more towards expected<T, E>, or something else entirely may turn up. As a quick taster:
     518
     519{{{#!c++
     520using namespace boost::spinlock::lightweight_futures;
     521monad<std::shared_ptr<handle_type>> openfile(std::filesystem::path path) noexcept
     522{
     523  int fd;
     524  while(-1==(fd=::open(path.c_str(), 0)) && EINTR==errno);
     525  try
     526  {
     527    if(-1==fd)
     528    {
     529      int code=errno;
     530      // If a temporary failure, this is an expected unexpected outcome
     531      if(EBUSY==code || EISDIR==code || ELOOP==code || ENOENT==code || ENOTDIR==code || EPERM==code || EACCES==code)
     532        return std::error_code(code, std::generic_category());
     533
     534      // If a non-temporary failure, this is an unexpected outcome
     535      return std::make_exception_ptr(std::system_error(code, std::generic_category(), strerror(code)));
     536    }
     537    return std::make_shared<handle_type>(fd);
     538  }
     539  catch(...)
     540  {
     541    // Any exception thrown is truly unexpected
     542    return std::current_exception();
     543  }
     544}
     545}}}
     546
     547This lightweight monadic implementation generates about 260 x64 opcodes, not enormously more than if the monadic transport were not being used at all. This lightweight monad isn't quite ready for prime time yet though, but should be by August 2015.
    519548
    520549In other words, I recommend you very strongly consider ''some'' mechanism for more closely and cleanly matching C++ semantics with what a function does now that C++ 11 makes it possible, but I unfortunately cannot categorically recommend one solution over another at the time of writing.