Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Understanding a boost executor example

Tags:

c++

boost

I am having problems with understanding why an (undocumented) interface of boost::basic_thread_pool executor is used in this example below taken from the boost documentation itself:

template<typename T>
struct sorter
{
    boost::basic_thread_pool pool;
    typedef std::list<T> return_type;

    std::list<T> do_sort(std::list<T> chunk_data)
    {
        if(chunk_data.empty()) {
            return chunk_data;
        }

        std::list<T> result;
        result.splice(result.begin(),chunk_data, chunk_data.begin());
        T const& partition_val=*result.begin();

        typename std::list<T>::iterator divide_point =
            std::partition(chunk_data.begin(), chunk_data.end(),
                           [&](T const& val){return val<partition_val;});

        std::list<T> new_lower_chunk;
        new_lower_chunk.splice(new_lower_chunk.end(), chunk_data,
                               chunk_data.begin(), divide_point);
        boost::future<std::list<T> > new_lower =
             boost::async(pool, &sorter::do_sort, this, std::move(new_lower_chunk));
        std::list<T> new_higher(do_sort(chunk_data));
        result.splice(result.end(),new_higher);
        while(!new_lower.is_ready()) {
            pool.schedule_one_or_yield();
        }
        result.splice(result.begin(),new_lower.get());
        return result;
    }
};

The call in question is pool.schedule_one_or_yield();. Correct me if I am wrong, but it suggests that a submitted task will be eventually scheduled for execution. If so, should not have each previous call to boost::async(pool, &sorter::do_sort, this, std::move(new_lower_chunk)); already scheduled the submitted tasks implicitly?

I know the boost executor API is experimental, but do you know why schedule_one_or_yield is undocumented?

like image 505
Martin Avatar asked Nov 07 '22 01:11

Martin


1 Answers

The function schedule_one_or_yield() was removed from the current source code of boost because it implemented busy waiting. This is in

https://github.com/boostorg/thread/issues/117

loop_executor::loop is currently:

void loop()
{
  while (!closed())
  {
    schedule_one_or_yield();
  }
  while (try_executing_one())
  {
  }
}

The first loop repeatedly calls schedule_one_or_yield() which is simply

void schedule_one_or_yield()
{
    if ( ! try_executing_one())
    {
      this_thread::yield();
    }
}

current implementation loop_executor::loop of is

/**
     * The main loop of the worker thread
     */
    void loop()
    {
      while (execute_one(/*wait:*/true))
      {
      }
      BOOST_ASSERT(closed());
      while (try_executing_one())
      {
      }
}

source : https://github.com/boostorg/thread/blob/develop/include/boost/thread/executors/loop_executor.hpp

It was also removed in the example user_scheduler, the old version is in

https://github.com/mongodb/mongo/blob/master/src/third_party/boost-1.60.0/boost/thread/user_scheduler.hpp with schedule_one_or_yield() in line 63

the new version without schedule_one_or_yield() is in https://github.com/boostorg/thread/blob/develop/example/user_scheduler.cpp

like image 126
ralf htp Avatar answered Nov 14 '22 21:11

ralf htp