Index: mojo/public/python/src/python_system_helper.cc |
diff --git a/mojo/public/python/src/python_system_helper.cc b/mojo/public/python/src/python_system_helper.cc |
index 22b6bbb4a5d47eff3e459168b387df4e58b3ddf9..0c5a358f2355d70a56516809ea807a121da5b10a 100644 |
--- a/mojo/public/python/src/python_system_helper.cc |
+++ b/mojo/public/python/src/python_system_helper.cc |
@@ -6,173 +6,37 @@ |
#include "Python.h" |
-#include "mojo/public/cpp/environment/environment.h" |
-#include "mojo/public/cpp/environment/logging.h" |
-#include "mojo/public/cpp/system/macros.h" |
#include "mojo/public/cpp/utility/run_loop.h" |
+#include "mojo/public/python/src/common.h" |
namespace { |
- |
-class ScopedGIL { |
- public: |
- ScopedGIL() { state_ = PyGILState_Ensure(); } |
- |
- ~ScopedGIL() { PyGILState_Release(state_); } |
- |
- private: |
- PyGILState_STATE state_; |
- |
- MOJO_DISALLOW_COPY_AND_ASSIGN(ScopedGIL); |
-}; |
- |
-enum ScopedPyRefAcquire { |
- kAcquire, |
-}; |
- |
-class ScopedPyRef { |
+class QuitCurrentRunLoop : public mojo::Closure::Runnable { |
public: |
- ScopedPyRef(PyObject* object) : object_(object) {} |
- ScopedPyRef(PyObject* object, ScopedPyRefAcquire) : object_(object) { |
- Py_XINCREF(object_); |
- } |
- |
- ~ScopedPyRef() { |
- if (object_) { |
- ScopedGIL acquire_gil; |
- Py_DECREF(object_); |
- } |
- } |
- |
- operator PyObject*() const { return object_; } |
- |
- private: |
- PyObject* object_; |
- |
- MOJO_DISALLOW_COPY_AND_ASSIGN(ScopedPyRef); |
-}; |
- |
-class PythonClosure : public mojo::Closure::Runnable { |
- public: |
- PythonClosure(PyObject* callable) : callable_(callable, kAcquire) { |
- MOJO_DCHECK(callable); |
- } |
- |
void Run() const override { |
- ScopedGIL acquire_gil; |
- ScopedPyRef empty_tuple(PyTuple_New(0)); |
- if (!empty_tuple) { |
- mojo::RunLoop::current()->Quit(); |
- return; |
- } |
- |
- ScopedPyRef result(PyObject_CallObject(callable_, empty_tuple)); |
- if (!result) { |
- mojo::RunLoop::current()->Quit(); |
- return; |
- } |
+ mojo::RunLoop::current()->Quit(); |
} |
- private: |
- ScopedPyRef callable_; |
- |
- MOJO_DISALLOW_COPY_AND_ASSIGN(PythonClosure); |
+ static mojo::Closure NewQuitClosure() { |
+ return mojo::Closure( |
+ static_cast<mojo::Closure::Runnable*>(new QuitCurrentRunLoop())); |
+ } |
}; |
-void AsyncCallbackForwarder(void* closure, MojoResult result) { |
- mojo::Callback<void(MojoResult)>* callback = |
- static_cast<mojo::Callback<void(MojoResult)>*>(closure); |
- // callback will be deleted when it is run. |
- callback->Run(result); |
-} |
- |
} // namespace |
namespace mojo { |
namespace python { |
-class PythonAsyncWaiter::AsyncWaiterRunnable |
- : public mojo::Callback<void(MojoResult)>::Runnable { |
- public: |
- AsyncWaiterRunnable(PyObject* callable, CallbackMap* callbacks) |
- : wait_id_(0), callable_(callable, kAcquire), callbacks_(callbacks) { |
- MOJO_DCHECK(callable); |
- MOJO_DCHECK(callbacks_); |
- } |
- |
- void set_wait_id(int wait_id) { wait_id_ = wait_id; } |
- |
- void Run(MojoResult mojo_result) const override { |
- MOJO_DCHECK(wait_id_); |
- |
- // Remove to reference to this object from PythonAsyncWaiter and ensure this |
- // object will be destroyed when this method exits. |
- MOJO_DCHECK(callbacks_->find(wait_id_) != callbacks_->end()); |
- internal::SharedPtr<mojo::Callback<void(MojoResult)>> self = |
- (*callbacks_)[wait_id_]; |
- callbacks_->erase(wait_id_); |
- |
- ScopedGIL acquire_gil; |
- ScopedPyRef args_tuple(Py_BuildValue("(i)", mojo_result)); |
- if (!args_tuple) { |
- mojo::RunLoop::current()->Quit(); |
- return; |
- } |
- |
- ScopedPyRef result(PyObject_CallObject(callable_, args_tuple)); |
- if (!result) { |
- mojo::RunLoop::current()->Quit(); |
- return; |
- } |
- } |
- |
- private: |
- MojoAsyncWaitID wait_id_; |
- ScopedPyRef callable_; |
- CallbackMap* callbacks_; |
- |
- MOJO_DISALLOW_COPY_AND_ASSIGN(AsyncWaiterRunnable); |
-}; |
- |
Closure BuildClosure(PyObject* callable) { |
if (!PyCallable_Check(callable)) |
return Closure(); |
- return Closure( |
- static_cast<mojo::Closure::Runnable*>(new PythonClosure(callable))); |
+ return mojo::Closure( |
+ NewRunnableFromCallable(callable, QuitCurrentRunLoop::NewQuitClosure())); |
} |
-PythonAsyncWaiter::PythonAsyncWaiter() { |
- async_waiter_ = Environment::GetDefaultAsyncWaiter(); |
-} |
- |
-PythonAsyncWaiter::~PythonAsyncWaiter() { |
- for (CallbackMap::const_iterator it = callbacks_.begin(); |
- it != callbacks_.end(); |
- ++it) { |
- async_waiter_->CancelWait(it->first); |
- } |
-} |
- |
-MojoAsyncWaitID PythonAsyncWaiter::AsyncWait(MojoHandle handle, |
- MojoHandleSignals signals, |
- MojoDeadline deadline, |
- PyObject* callable) { |
- AsyncWaiterRunnable* runner = new AsyncWaiterRunnable(callable, &callbacks_); |
- internal::SharedPtr<mojo::Callback<void(MojoResult)>> callback( |
- new mojo::Callback<void(MojoResult)>( |
- static_cast<mojo::Callback<void(MojoResult)>::Runnable*>(runner))); |
- MojoAsyncWaitID wait_id = async_waiter_->AsyncWait( |
- handle, signals, deadline, &AsyncCallbackForwarder, callback.get()); |
- callbacks_[wait_id] = callback; |
- runner->set_wait_id(wait_id); |
- return wait_id; |
-} |
- |
-void PythonAsyncWaiter::CancelWait(MojoAsyncWaitID wait_id) { |
- if (callbacks_.find(wait_id) != callbacks_.end()) { |
- async_waiter_->CancelWait(wait_id); |
- callbacks_.erase(wait_id); |
- } |
+PythonAsyncWaiter* NewAsyncWaiter() { |
+ return new PythonAsyncWaiter(QuitCurrentRunLoop::NewQuitClosure()); |
} |
} // namespace python |