Commit f18d8adb authored by Nanshu Chen's avatar Nanshu Chen Committed by Facebook Github Bot

coro::Task bridge

Reviewed By: andriigrynenko

Differential Revision: D14637661

fbshipit-source-id: 0f8852e30ff554e9f0125e2d918054e4bc1e5af5
parent 6d45bcc0
/*
* Copyright 2019-present Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* This file serves as a helper for bridging folly::coroTask and python
* asyncio.future.
*/
#pragma once
#include <Python.h>
#include <folly/Executor.h>
#include <folly/experimental/coro/Task.h>
#include <folly/python/AsyncioExecutor.h>
#include <folly/python/executor_api.h>
namespace folly {
namespace python {
inline folly::Executor* getExecutor() {
import_folly__executor();
return get_executor();
}
template <typename T>
void bridgeCoroTask(
folly::Executor* executor,
folly::coro::Task<T>&& coroFrom,
folly::Function<void(folly::Try<T>&&, PyObject*)> callback,
PyObject* userData) {
std::move(coroFrom).scheduleOn(executor).start(
[callback = std::move(callback),
userData](folly::Try<T>&& result) mutable {
callback(std::move(result), userData);
});
}
template <typename T>
void bridgeCoroTask(
folly::coro::Task<T>&& coroFrom,
folly::Function<void(folly::Try<T>&&, PyObject*)> callback,
PyObject* userData) {
bridgeCoroTask(
getExecutor(), std::move(coroFrom), std::move(callback), userData);
}
} // namespace python
} // namespace folly
# Copyright 2019-present Facebook, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from cpython.ref cimport PyObject
from folly cimport cFollyExecutor, cFollyTry
cdef extern from "folly/experimental/coro/Task.h" namespace "folly::coro" nogil:
cdef cppclass cFollyCoroTask "folly::coroTask"[T]:
pass
cdef extern from "folly/python/coro.h" namespace "folly::python":
void bridgeCoroTask[T](
cFollyCoroTask[T]&& fut,
void(*)(cFollyTry[T]&&, PyObject*),
PyObject* pyFuture
)
# No clue but cython overloading is getting confused so we alias
void bridgeCoroTaskWith "folly::python::bridgeCoroTask"[T](
cFollyExecutor* executor,
cFollyCoroTask[T]&& fut,
void(*)(cFollyTry[T]&&, PyObject*),
PyObject* pyFuture
)
# Copyright 2019-present Facebook, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#!/usr/bin/env python3
# Copyright 2019-present Facebook, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import asyncio
import unittest
from . import simplebridgecoro
class Futures(unittest.TestCase):
def test_bridge_coro(self):
val = 1337
loop = asyncio.get_event_loop()
res = loop.run_until_complete(simplebridgecoro.get_value_x5_coro(val))
self.assertEqual(val * 5, res)
# Copyright 2019-present Facebook, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import asyncio
from folly.coro cimport cFollyCoroTask, bridgeCoroTask
from folly cimport cFollyTry
from libc.stdint cimport uint64_t
from cpython.ref cimport PyObject
from cython.operator cimport dereference as deref
cdef extern from "folly/python/test/simplecoro.h" namespace "folly::python::test":
cdef cFollyCoroTask[uint64_t] coro_getValueX5(uint64_t val)
def get_value_x5_coro(int val):
loop = asyncio.get_event_loop()
fut = loop.create_future()
bridgeCoroTask[uint64_t](
coro_getValueX5(val),
handle_uint64_t,
<PyObject *>fut
)
return fut
cdef void handle_uint64_t(cFollyTry[uint64_t]&& res, PyObject* userData):
future = <object> userData
if res.hasException():
try:
res.exception().throw_exception()
except Exception as ex:
future.set_exception(ex)
else:
future.set_result(res.value())
/*
* Copyright 2019-present Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <folly/experimental/coro/Task.h>
#include <cstdint>
namespace folly {
namespace python {
namespace test {
folly::coro::Task<uint64_t> coro_getValueX5(uint64_t val) {
if (val == 0) {
throw std::invalid_argument("0 is not allowed");
}
co_return val * 5;
}
} // namespace test
} // namespace python
} // namespace folly
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment