Commit ad00be70 authored by Kirill Smelkov's avatar Kirill Smelkov

libgolang: Introduce runtimes

Libgolang will be generic library and it will adapt itself to particular
execution environment by way of runtime plugin. This commit introduces
stubs for two such runtimes - "thread" and "gevent" - and initializes
libgolang with particular runtime depending on whether golang is
imported with gevent preactivated or not.

The runtimes themselves are empty at this step. We'll be adding runtime
functionality in the following patches.
parent 8fa3c15b
...@@ -28,6 +28,9 @@ See _golang.pxd for package overview. ...@@ -28,6 +28,9 @@ See _golang.pxd for package overview.
from __future__ import print_function, absolute_import from __future__ import print_function, absolute_import
# init libgolang runtime early
_init_libgolang()
from cpython cimport PY_MAJOR_VERSION from cpython cimport PY_MAJOR_VERSION
from cython cimport final from cython cimport final
...@@ -59,3 +62,34 @@ cdef void topyexc() except *: ...@@ -59,3 +62,34 @@ cdef void topyexc() except *:
cdef extern from "golang/libgolang.h" nogil: cdef extern from "golang/libgolang.h" nogil:
const char *recover_ "golang::recover" () except + const char *recover_ "golang::recover" () except +
# ---- init libgolang runtime ---
cdef extern from "golang/libgolang.h" namespace "golang" nogil:
struct _libgolang_runtime_ops
void _libgolang_init(const _libgolang_runtime_ops*)
from cpython cimport PyCapsule_Import
cdef void _init_libgolang() except*:
# detect whether we are running under gevent or OS threads mode
# -> use golang.runtime._runtime_(gevent|thread) as libgolang runtime.
threadmod = "thread"
if PY_MAJOR_VERSION >= 3:
threadmod = "_thread"
t = __import__(threadmod)
runtime = "thread"
if "gevent" in t.start_new_thread.__module__:
runtime = "gevent"
runtimemod = "golang.runtime." + "_runtime_" + runtime
# PyCapsule_Import("golang.X") does not work properly while we are in the
# process of importing golang (it tries to access "X" attribute of half-created
# golang module). -> preimport runtimemod via regular import first.
__import__(runtimemod)
runtimecaps = (runtimemod + ".libgolang_runtime_ops").encode("utf-8") # py3
cdef const _libgolang_runtime_ops *runtime_ops = \
<const _libgolang_runtime_ops*>PyCapsule_Import(runtimecaps, 0)
if runtime_ops == NULL:
pypanic("init: %s: libgolang_runtime_ops=NULL" % runtimemod)
_libgolang_init(runtime_ops)
...@@ -43,6 +43,20 @@ ...@@ -43,6 +43,20 @@
// //
// //
// C-level API // C-level API
//
// Runtimes
//
// Libgolang, before being used, must be initialized with particular runtime
// plugin, which tailors Libgolang to particular execution environment. See
// `_libgolang_init` and `_libgolang_runtime_ops` for description of a runtime.
//
// Pygolang - the parent project of Libgolang - comes with two Libgolang runtimes:
//
// - "thread" - a runtime that is based on OS threads, and
// - "gevent" - a runtime that is based on greenlet and gevent.
//
// Once again, Libgolang itself is independent from Python, and other runtimes
// are possible.
#include <stdbool.h> #include <stdbool.h>
#include <stddef.h> #include <stddef.h>
...@@ -78,6 +92,14 @@ extern "C" { ...@@ -78,6 +92,14 @@ extern "C" {
LIBGOLANG_API void panic(const char *arg); LIBGOLANG_API void panic(const char *arg);
LIBGOLANG_API const char *recover(void); LIBGOLANG_API const char *recover(void);
// libgolang runtime - the runtime must be initialized before any other libgolang use.
typedef struct _libgolang_runtime_ops {
} _libgolang_runtime_ops;
LIBGOLANG_API void _libgolang_init(const _libgolang_runtime_ops *runtime_ops);
#ifdef __cplusplus #ifdef __cplusplus
}} }}
#endif #endif
......
/_runtime_gevent.c
/_runtime_thread.c
# cython: language_level=2
# Copyright (C) 2019 Nexedi SA and Contributors.
# Kirill Smelkov <kirr@nexedi.com>
#
# This program is free software: you can Use, Study, Modify and Redistribute
# it under the terms of the GNU General Public License version 3, or (at your
# option) any later version, as published by the Free Software Foundation.
#
# You can also Link and Combine this program with other software covered by
# the terms of any of the Free Software licenses or any of the Open Source
# Initiative approved licenses and Convey the resulting work. Corresponding
# source of such a combination shall include the source code for all other
# software used.
#
# This program is distributed WITHOUT ANY WARRANTY; without even the implied
# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
#
# See COPYING file for full licensing terms.
# See https://www.nexedi.com/licensing for rationale and options.
"""pyx declarations for libgolang bits that are only interesting for runtimes."""
cdef extern from "golang/libgolang.h" nogil:
struct _libgolang_runtime_ops:
pass
# cython: language_level=2
# Copyright (C) 2019 Nexedi SA and Contributors.
# Kirill Smelkov <kirr@nexedi.com>
#
# This program is free software: you can Use, Study, Modify and Redistribute
# it under the terms of the GNU General Public License version 3, or (at your
# option) any later version, as published by the Free Software Foundation.
#
# You can also Link and Combine this program with other software covered by
# the terms of any of the Free Software licenses or any of the Open Source
# Initiative approved licenses and Convey the resulting work. Corresponding
# source of such a combination shall include the source code for all other
# software used.
#
# This program is distributed WITHOUT ANY WARRANTY; without even the implied
# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
#
# See COPYING file for full licensing terms.
# See https://www.nexedi.com/licensing for rationale and options.
"""_runtime_gevent.pyx provides libgolang runtime based on gevent greenlets."""
from __future__ import print_function, absolute_import
from golang.runtime._libgolang cimport _libgolang_runtime_ops
cdef nogil:
# XXX const
_libgolang_runtime_ops gevent_ops = _libgolang_runtime_ops(
)
from cpython cimport PyCapsule_New
libgolang_runtime_ops = PyCapsule_New(&gevent_ops,
"golang.runtime._runtime_gevent.libgolang_runtime_ops", NULL)
# cython: language_level=2
# Copyright (C) 2019 Nexedi SA and Contributors.
# Kirill Smelkov <kirr@nexedi.com>
#
# This program is free software: you can Use, Study, Modify and Redistribute
# it under the terms of the GNU General Public License version 3, or (at your
# option) any later version, as published by the Free Software Foundation.
#
# You can also Link and Combine this program with other software covered by
# the terms of any of the Free Software licenses or any of the Open Source
# Initiative approved licenses and Convey the resulting work. Corresponding
# source of such a combination shall include the source code for all other
# software used.
#
# This program is distributed WITHOUT ANY WARRANTY; without even the implied
# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
#
# See COPYING file for full licensing terms.
# See https://www.nexedi.com/licensing for rationale and options.
"""_runtime_thread.pyx provides libgolang runtime based on OS threads."""
from __future__ import print_function, absolute_import
from golang.runtime._libgolang cimport _libgolang_runtime_ops
cdef nogil:
# XXX const
_libgolang_runtime_ops thread_ops = _libgolang_runtime_ops(
)
from cpython cimport PyCapsule_New
libgolang_runtime_ops = PyCapsule_New(&thread_ops,
"golang.runtime._runtime_thread.libgolang_runtime_ops", NULL)
...@@ -78,4 +78,15 @@ struct Bug : exception { ...@@ -78,4 +78,15 @@ struct Bug : exception {
throw Bug(msg); throw Bug(msg);
} }
// ---- runtime ----
// initially NULL to crash if runtime was not initialized
static const _libgolang_runtime_ops *_runtime = NULL;
void _libgolang_init(const _libgolang_runtime_ops *runtime_ops) {
if (_runtime != NULL) // XXX better check atomically
panic("libgolang: double init");
_runtime = runtime_ops;
}
} // golang:: } // golang::
...@@ -199,8 +199,15 @@ setup( ...@@ -199,8 +199,15 @@ setup(
ext_modules = [ ext_modules = [
Ext('golang._golang', Ext('golang._golang',
['golang/_golang.pyx']), ['golang/_golang.pyx']),
],
Ext('golang.runtime._runtime_thread',
['golang/runtime/_runtime_thread.pyx'],
language = "c"),
Ext('golang.runtime._runtime_gevent',
['golang/runtime/_runtime_gevent.pyx'],
language = 'c'),
],
include_package_data = True, include_package_data = True,
install_requires = ['gevent', 'six', 'decorator'], install_requires = ['gevent', 'six', 'decorator'],
......
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