boost::python threading to pause and resume c++ function through python

189 Views Asked by At

I have a simple c++ class that I've built a wrapper for to interface it with python 2.7. Now, I would like to be able to call a method of that class, ExampleClass::simulate(double sim_time) through python and pause the method/thread by calling another method, ExampleClass::pause(). A very simplistic example would look something like this:

#include<iostream>
#include<unistd.h>

class ExampleClass {
  public:
    void simulate(double sim_time)
    {
      pause_ = false;
      int count = 0;
      while (count < 10) {
        std::cout << "simulating.\n";
        sleep(1);
        while(pause_) {
          std::cout << "paused.\n";
          sleep(1);
        }
        count += 1;
      }
    }
    void pause()
    {
      pause_ = true;
    }
    void resume()
    { 
      pause_ = false;
    }
  private:
    bool pause_;
};

With the corresponding python wrapper:

    void simulate_wrapper(ExampleClass* ec, double t_sim)
    {
      PyGILState_STATE gstate = PyGILState_Ensure();
      ec->simulate(t_sim);
      PyGILState_Release(gstate);
    } 

    BOOST_PYTHON_MODULE(ExampleExt)
    {
      PyEval_InitThreads();
      boost::python::class_<ExampleClass>("ExampleClass")
      .def("pause",&ExampleClass::pause)
      .def("resume",&ExampleClass::resume)
      .def("simulate", &simulate_wrapper);
    }

Then in python, I have:

    import threading
    import time
    import ExampleExt
    ec = ExampleExt.ExampleClass()
    t_sim = 2 

    def simulate(ec, t_sim):
            print ('starting simulation.')
            t = time.clock()
            ec.simulate(t_sim)
            dt = time.clock() - t
            print ('simulation took',dt, 'seconds')

    threading1 = threading.Thread(target=simulate, args=(ec,t_sim))
    threading1.daemon = True
    threading1.start()

But when I create a ExampleClass object in ipython and run the simulate function, I can't run any other commands. I was reading about GIL and apparently it blocks all python I/O events so I guess it's really not what I should be doing. Especially because I want to modify the member pause_ whilst the simulate method is running. Any thoughts on how to make this work?

Thanks

Edit: I had a go at boost::thread to see whether that would solve my problem, with some interesting results. This is how I changed my wrapper:

  #include<example_class.hh>
  #include<iostream>
  #include<boost/python.hpp>
  #include<boost/thread/thread.hpp>
  #include<boost/bind.hpp>

  void simulate_wrapper(ExampleClass* ec, double t_sim)
  {
      boost::thread t1(boost::bind(&ExampleClass::simulate,ec, t_sim));
  } 

And my .py script just looks like this:

import ExampleExt
ec = ExampleExt.ExampleClass()
t_sim = 2
ec.simulate(t_sim)

Everything else is the same as before. Now when I run the .py script, I can use the pause and resume methods without problems but when the simulate method finishes, I get a SIGSEGV. What could be causing it?

Thanks for any insights!

0

There are 0 best solutions below