11320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Copyright 2014 The Chromium Authors. All rights reserved. 21320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Use of this source code is governed by a BSD-style license that can be 31320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// found in the LICENSE file. 41320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 51320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "mojo/public/python/src/python_system_helper.h" 61320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 71320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "Python.h" 81320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 91320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "mojo/public/cpp/environment/environment.h" 101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "mojo/public/cpp/environment/logging.h" 111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "mojo/public/cpp/system/macros.h" 121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "mojo/public/cpp/utility/run_loop.h" 131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccinamespace { 151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciclass ScopedGIL { 171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci public: 181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ScopedGIL() { state_ = PyGILState_Ensure(); } 191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ~ScopedGIL() { PyGILState_Release(state_); } 211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci private: 231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci PyGILState_STATE state_; 241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci MOJO_DISALLOW_COPY_AND_ASSIGN(ScopedGIL); 261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}; 271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciclass PythonClosure : public mojo::Closure::Runnable { 291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci public: 301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci PythonClosure(PyObject* callable) : callable_(callable) { 311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci MOJO_DCHECK(callable); 321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Py_XINCREF(callable); 331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci virtual ~PythonClosure() { 361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ScopedGIL acquire_gil; 371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Py_DECREF(callable_); 381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci virtual void Run() const MOJO_OVERRIDE { 411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ScopedGIL acquire_gil; 421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci PyObject* empty_tuple = PyTuple_New(0); 431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!empty_tuple) { 441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci mojo::RunLoop::current()->Quit(); 451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return; 461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci PyObject* result = PyObject_CallObject(callable_, empty_tuple); 491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Py_DECREF(empty_tuple); 501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (result) { 511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Py_DECREF(result); 521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } else { 531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci mojo::RunLoop::current()->Quit(); 541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return; 551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci private: 591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci PyObject* callable_; 601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci MOJO_DISALLOW_COPY_AND_ASSIGN(PythonClosure); 621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}; 631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid AsyncCallbackForwarder(void* closure, MojoResult result) { 651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci mojo::Callback<void(MojoResult)>* callback = 661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci static_cast<mojo::Callback<void(MojoResult)>*>(closure); 671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // callback will be deleted when it is run. 681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci callback->Run(result); 691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} // namespace 721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccinamespace mojo { 741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccinamespace python { 751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciclass PythonAsyncWaiter::AsyncWaiterRunnable 771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci : public mojo::Callback<void(MojoResult)>::Runnable { 781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci public: 791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci AsyncWaiterRunnable(PyObject* callable, CallbackMap* callbacks) 801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci : wait_id_(0), callable_(callable), callbacks_(callbacks) { 811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci MOJO_DCHECK(callable); 821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci MOJO_DCHECK(callbacks_); 831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Py_XINCREF(callable); 841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci virtual ~AsyncWaiterRunnable() { 871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ScopedGIL acquire_gil; 881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Py_DECREF(callable_); 891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci void set_wait_id(int wait_id) { wait_id_ = wait_id; } 921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci virtual void Run(MojoResult mojo_result) const MOJO_OVERRIDE { 941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci MOJO_DCHECK(wait_id_); 951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Remove to reference to this object from PythonAsyncWaiter and ensure this 971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // object will be destroyed when this method exits. 981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci MOJO_DCHECK(callbacks_->find(wait_id_) != callbacks_->end()); 991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci internal::SharedPtr<mojo::Callback<void(MojoResult)> > self = 1001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci (*callbacks_)[wait_id_]; 1011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci callbacks_->erase(wait_id_); 1021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ScopedGIL acquire_gil; 1041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci PyObject* args_tuple = Py_BuildValue("(i)", mojo_result); 1051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!args_tuple) { 1061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci mojo::RunLoop::current()->Quit(); 1071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return; 1081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 1091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci PyObject* result = PyObject_CallObject(callable_, args_tuple); 1111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Py_DECREF(args_tuple); 1121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (result) { 1131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Py_DECREF(result); 1141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } else { 1151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci mojo::RunLoop::current()->Quit(); 1161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return; 1171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 1181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 1191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci private: 1211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci MojoAsyncWaitID wait_id_; 1221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci PyObject* callable_; 1231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci CallbackMap* callbacks_; 1241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci MOJO_DISALLOW_COPY_AND_ASSIGN(AsyncWaiterRunnable); 1261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}; 1271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciClosure BuildClosure(PyObject* callable) { 1291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!PyCallable_Check(callable)) 1301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return Closure(); 1311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return Closure( 1331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci static_cast<mojo::Closure::Runnable*>(new PythonClosure(callable))); 1341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciPythonAsyncWaiter::PythonAsyncWaiter() { 1371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci async_waiter_ = Environment::GetDefaultAsyncWaiter(); 1381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciPythonAsyncWaiter::~PythonAsyncWaiter() { 1411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci for (CallbackMap::const_iterator it = callbacks_.begin(); 1421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci it != callbacks_.end(); 1431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ++it) { 1441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci async_waiter_->CancelWait(it->first); 1451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 1461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciMojoAsyncWaitID PythonAsyncWaiter::AsyncWait(MojoHandle handle, 1491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci MojoHandleSignals signals, 1501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci MojoDeadline deadline, 1511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci PyObject* callable) { 1521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci AsyncWaiterRunnable* runner = new AsyncWaiterRunnable(callable, &callbacks_); 1531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci internal::SharedPtr<mojo::Callback<void(MojoResult)> > callback( 1541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci new mojo::Callback<void(MojoResult)>( 1551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci static_cast<mojo::Callback<void(MojoResult)>::Runnable*>(runner))); 1561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci MojoAsyncWaitID wait_id = async_waiter_->AsyncWait( 1571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci handle, signals, deadline, &AsyncCallbackForwarder, callback.get()); 1581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci callbacks_[wait_id] = callback; 1591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci runner->set_wait_id(wait_id); 1601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return wait_id; 1611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid PythonAsyncWaiter::CancelWait(MojoAsyncWaitID wait_id) { 1641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (callbacks_.find(wait_id) != callbacks_.end()) { 1651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci async_waiter_->CancelWait(wait_id); 1661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci callbacks_.erase(wait_id); 1671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 1681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} // namespace python 1711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} // namespace mojo 172