PacktPublishing / Cpp-High-Performance-Second-Edition

C++ High Performance Second Edition, published by Packt
MIT License
230 stars 104 forks source link

Chapter 13: attempting to reference a deleted function #3

Open puhach opened 3 years ago

puhach commented 3 years ago

The Promise struct in Chapter13\sync_wait.h causes the following compilation errors:

3>C:\temp\Cpp-High-Performance-Second-Edition-master\Chapter13\task_ex.cpp(31): error C2280: 'detail::SyncWaitTask::Promise::Promise(void)': attempting to reference a deleted function 3>C:\temp\Cpp-High-Performance-Second-Edition-master\Chapter13\sync_wait.h(65): message : compiler has generated 'detail::SyncWaitTask::Promise::Promise' here 4>C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30037\include\execution(1222,5): error C2338: Parallel algorithms require forward iterators or stronger. 3>C:\temp\Cpp-High-Performance-Second-Edition-master\Chapter13\syncwait.h(65,1): message : 'detail::SyncWaitTask::Promise::Promise(void)': function was implicitly deleted because a data member 'detail::SyncWaitTask::Promise::semaphore' has either no appropriate default constructor or overload resolution was ambiguous 3>C:\temp\Cpp-High-Performance-Second-Edition-master\Chapter13\syncwait.h(59): message : see declaration of 'detail::SyncWaitTask::Promise::semaphore' 3>C:\temp\Cpp-High-Performance-Second-Edition-master\Chapter13\task_ex.cpp(26): message : see reference to function template instantiation 'int sync_wait<Task&>(T)' being compiled 3> with 3> [ 3> T=Task & 3> ] 3>Done building project "Chapter13-Asynchronous_Programming_With_Coroutines.vcxproj" -- FAILED.

I believe the issue is caused by std::binary_semaphore, which is used incorrectly. According to the documentation, this class has to be initialized with the internal counter. Here it is used without any parameters:

  struct Promise {
    SyncWaitTask get_return_object() noexcept { return SyncWaitTask{*this}; }
    auto initial_suspend() noexcept { return std::suspend_always{}; }
    void unhandled_exception() noexcept { error_ = std::current_exception(); }
    auto yield_value(T&& x) noexcept { // Result has arrived
      value_ = std::addressof(x);
      return final_suspend();
    }

    auto final_suspend() noexcept {
      struct Awaitable {
        bool await_ready() noexcept { return false; }
        void await_suspend(std::coroutine_handle<Promise> h) noexcept {

#if defined(__cpp_lib_semaphore)
          h.promise().semaphore_.release(); // Signal!
#else
          {
            auto lock = std::unique_lock{h.promise().mtx_};
            h.promise().ready_ = true;
          }
          h.promise().cv_.notify_one();
#endif
        }
        void await_resume() noexcept {}
      };
      return Awaitable{};
    }

    void return_void() noexcept { assert(false); }

    T* value_ = nullptr;
    std::exception_ptr error_;

#if defined(__cpp_lib_semaphore)
    std::binary_semaphore semaphore_; // !!
#else
    bool ready_{false};
    std::mutex mtx_;
    std::condition_variable cv_;
#endif
  };
zhaohui0923 commented 2 years ago

@puhach just change "std::binarysemaphore semaphore;" to "std::binarysemaphore semaphore{1};" will fix the issue.