Flask,boost::python 和线程
Flask, boost::python and threads
我有一个通过 boost::python 公开的 C++ class:
class RunnerState {
public:
RunnerState(std::string& input) : m_output(3, 0) { }
std::vector<int>& get_output() { return m_output; }
void run() {
std::unique_lock<std::mutex> running(m);
t = new std::thread([this] (std::unique_lock<std::mutex> running) {
sleep(10);
}, std::move(running));
}
bool is_running() {
if(m.try_lock()) {
m.unlock();
return false;
}
return true;
}
private:
std::thread *t;
std::mutex m;
};
BOOST_PYTHON_MODULE(librunner)
{
class_<std::vector<int>>("int_vector").def(vector_indexing_suite<std::vector<int>>());
class_<RunnerState, boost::noncopyable>("RunnerState", init<std::string>())
.def("get_output", &RunnerState::get_output, return_value_policy<copy_non_const_reference>())
.def("run", &RunnerState::run)
.def("is_running", &RunnerState::run);
}
然后由 Flask 网络服务使用:
from flask import Flask, request
import librunner
app = Flask(__name__)
current_run = None
@app.route('/run', methods=['POST'])
def run():
data = request.get_data()
current_run = librunner.Run(data)
output = current_run.get_output()
# do something with output...
current_run.run()
return "Success!", 200, {'Content-Type': 'text/plain'}
@app.route('/running')
def running():
result = False
if current_run != None:
result = current_run.is_running()
return str(result), 200, {'Content-Type': 'text/plain'}
问题是 POST
对 /run
的请求不会 return 直到在 C++ 中创建的线程退出。为什么?
我猜测这与 Boost::Python return 价值政策和 Boost::Python 在指定时间内保持 returned 价值有关,但我无法具体指出问题所在。
这里的问题是函数不访问 current_run
全局变量,而是它们各自得到一个名为 current_run
的局部变量。这是通过将 python 更改为以下内容来解决的:
from flask import Flask, request
import librunner
app = Flask(__name__)
current_run = None
@app.route('/run', methods=['POST'])
def run():
data = request.get_data()
global current_run
current_run = librunner.Run(data)
output = current_run.get_output()
# do something with output...
current_run.run()
return "Success!", 200, {'Content-Type': 'text/plain'}
@app.route('/running')
def running():
result = False
global current_run
if current_run != None:
result = current_run.is_running()
return str(result), 200, {'Content-Type': 'text/plain'}
我有一个通过 boost::python 公开的 C++ class:
class RunnerState {
public:
RunnerState(std::string& input) : m_output(3, 0) { }
std::vector<int>& get_output() { return m_output; }
void run() {
std::unique_lock<std::mutex> running(m);
t = new std::thread([this] (std::unique_lock<std::mutex> running) {
sleep(10);
}, std::move(running));
}
bool is_running() {
if(m.try_lock()) {
m.unlock();
return false;
}
return true;
}
private:
std::thread *t;
std::mutex m;
};
BOOST_PYTHON_MODULE(librunner)
{
class_<std::vector<int>>("int_vector").def(vector_indexing_suite<std::vector<int>>());
class_<RunnerState, boost::noncopyable>("RunnerState", init<std::string>())
.def("get_output", &RunnerState::get_output, return_value_policy<copy_non_const_reference>())
.def("run", &RunnerState::run)
.def("is_running", &RunnerState::run);
}
然后由 Flask 网络服务使用:
from flask import Flask, request
import librunner
app = Flask(__name__)
current_run = None
@app.route('/run', methods=['POST'])
def run():
data = request.get_data()
current_run = librunner.Run(data)
output = current_run.get_output()
# do something with output...
current_run.run()
return "Success!", 200, {'Content-Type': 'text/plain'}
@app.route('/running')
def running():
result = False
if current_run != None:
result = current_run.is_running()
return str(result), 200, {'Content-Type': 'text/plain'}
问题是 POST
对 /run
的请求不会 return 直到在 C++ 中创建的线程退出。为什么?
我猜测这与 Boost::Python return 价值政策和 Boost::Python 在指定时间内保持 returned 价值有关,但我无法具体指出问题所在。
这里的问题是函数不访问 current_run
全局变量,而是它们各自得到一个名为 current_run
的局部变量。这是通过将 python 更改为以下内容来解决的:
from flask import Flask, request
import librunner
app = Flask(__name__)
current_run = None
@app.route('/run', methods=['POST'])
def run():
data = request.get_data()
global current_run
current_run = librunner.Run(data)
output = current_run.get_output()
# do something with output...
current_run.run()
return "Success!", 200, {'Content-Type': 'text/plain'}
@app.route('/running')
def running():
result = False
global current_run
if current_run != None:
result = current_run.is_running()
return str(result), 200, {'Content-Type': 'text/plain'}