title: BOOST_ASSERT failure raised in boost::fiber on Visual Studio "Debug" build
body: <p>I run into issue with boost::fiber. My code is based on &quot;work_stealing.cpp&quot; example of boost::fiber. I decorated it a little bit. It can work now on Windows Subsystem Linux Ubuntu for both Debug and Release build. In fact, till last night it can work on Windows Visual Studio build... But today, we I attempt to run some test, a BOOST ASSERT failure raised on Debug build. The Release build can work...</p>
  <p>I don't know why... so, do anyone know something about this? Why it's only on Windows Debug build? What did I do wrong?</p>
  <p>I am using cmake as build tool, Visual Studio 2019 Community Edition as development tool. I also test on WSL Ubuntu 20.04 and macOS 10.15.x(cannot recall it...).</p>
  <p>Thank you.</p>
  <p>-Quan</p>
  <p>The failure raised from the below code of boost:</p>
  <pre><code>// &lt;boost&gt;/lib/fiber/src/scheduler.cpp
  ...
  void
  scheduler::detach_worker_context( context * ctx) noexcept {
      BOOST_ASSERT( nullptr != ctx);
      BOOST_ASSERT( ! ctx-&gt;ready_is_linked() );
  #if ! defined(BOOST_FIBERS_NO_ATOMICS)
      BOOST_ASSERT( ! ctx-&gt;remote_ready_is_linked() );
  #endif
      BOOST_ASSERT( ! ctx-&gt;sleep_is_linked() );
      BOOST_ASSERT( ! ctx-&gt;terminated_is_linked() );
      BOOST_ASSERT( ! ctx-&gt;wait_is_linked() ); // &lt;-- [THE ERROR RAISED FROM HERE!]
      BOOST_ASSERT( ctx-&gt;worker_is_linked() );
      BOOST_ASSERT( ! ctx-&gt;is_context( type::pinned_context) );
      ctx-&gt;worker_unlink();
      BOOST_ASSERT( ! ctx-&gt;worker_is_linked() );
      ctx-&gt;scheduler_ = nullptr;
      // a detached context must not belong to any queue
  }
  ...
  </code></pre>
  <p>And my code is like below (I removed some not-related parts...):</p>
  <pre><code>//coroutine.h
  class CoroutineManager {
    ...
  
    typedef std::unique_lock&lt;std::mutex&gt; lock_type;
    typedef boost::fibers::algo::work_stealing scheduler_algorithm;
    typedef boost::fibers::default_stack stack_type;
    
    ...
    void wait() {
      lock_type shutdown_lock(shutdown_mutex);
      shutdown_condition.wait(shutdown_lock, [this]() { return 1 == this-&gt;shutdown_flag; });
      BOOST_ASSERT(1 == this-&gt;shutdown_flag);
    }
  
    void shutdown(bool wait = true) {
      lock_type shutdown_lock(shutdown_mutex);
  
      this-&gt;shutdown_flag = 1;
  
      shutdown_lock.unlock();
  
      this-&gt;shutdown_condition.notify_all();
  
      if (wait) {
        for (std::thread&amp; t : threads) {
          if (t.joinable()) {
            t.join();
          }
        }
      }
    }
    
    ...
  
    template &lt;class TaskType&gt;
    void submit(const TaskType&amp; task) {
      boost::fibers::fiber(boost::fibers::launch::dispatch, std::allocator_arg, stack_type(this-&gt;stack_size), task).detach();
    }
    
    ...
    
    void init() {
      if (verbose) spdlog::info(&quot;INIT THREAD({0}) STARTED.&quot;, std::this_thread::get_id());
  
      for (int i = 0; i &lt; (this-&gt;thread_count - 1); ++i) {
        threads.push_back(std::thread(&amp;CoroutineManager::thread, this));
      }
  
      boost::fibers::use_scheduling_algorithm&lt;scheduler_algorithm&gt;(this-&gt;thread_count);
  
      this-&gt;start_barrier.wait();
    }
  
    void dispose() {
      if (verbose) spdlog::info(&quot;INIT THREAD({0}) DISPOSED.&quot;, std::this_thread::get_id());
    }
  
    void thread() {
      if(verbose) spdlog::info(&quot;WORKER THREAD({0}) STARTED.&quot;, std::this_thread::get_id());
  
      boost::fibers::use_scheduling_algorithm&lt;scheduler_algorithm&gt;(this-&gt;thread_count);
  
      this-&gt;start_barrier.wait();
  
      this-&gt;wait();
  
      if (verbose) spdlog::info(&quot;WORKER THREAD({0}) DISPOSED.&quot;, std::this_thread::get_id());
    }
  
    ...
  };
  
  - - - - - - - - - - - - - - - - - - - - - - -
  
  // coroutine_test.cpp
  ...
  
  int main(int argc, char* argv[]) {
    init_file_logger(&quot;coroutine_test.log&quot;);
    time_tracker tracker(&quot;[coroutine_test.main]&quot;);
  
    typedef std::thread::id tid_t;
    typedef boost::fibers::fiber::id fid_t;
    typedef boost::fibers::buffered_channel&lt;std::tuple&lt;tid_t, fid_t, int&gt;&gt; channel_t;
  
    CoroutineManager manager(std::thread::hardware_concurrency(), 1024 * 1024 * 8, true);
  
    const int N = 1;
  
    channel_t chan { 8 };
  
    boost::fibers::barrier done_flag(2);
  
    manager.submit([&amp;chan, &amp;done_flag]() {
      std::tuple&lt;tid_t, fid_t, int&gt; p;
  
      while( boost::fibers::channel_op_status::success == chan.pop_wait_for(p, std::chrono::milliseconds(100))) {
        spdlog::info(&quot;[thead({0}) : fiber({1}) from {2}]&quot;, std::get&lt;0&gt;(p), std::get&lt;1&gt;(p), std::get&lt;2&gt;(p));
      }
  
      done_flag.wait();
    });
  
    for (int i = 0; i &lt; N; ++i) {
      manager.submit([&amp;chan, i]() {
        for (int j = 0; j &lt; 1000; ++j) {
          chan.push(std::move(std::make_tuple(std::this_thread::get_id(), boost::this_fiber::get_id(), i)));
          boost::this_fiber::yield();
        }
      });
    }
  
    done_flag.wait();
  
    spdlog::info(&quot;-START TO SHUTDOWN-&quot;);
  
    manager.shutdown();
  
    spdlog::info(&quot;-END-&quot;);
  
    return 0;
  }
  </code></pre>
  <p>[UPDATE]
  <a href="https://i.stack.imgur.com/acOub.png" rel="nofollow noreferrer">Add a snapshot to explain my situation more clearly...</a></p>