mirror of
https://github.com/ThePhD/sol2.git
synced 2024-03-22 13:10:44 +08:00
as_args and threading API cleanliness.
This commit is contained in:
parent
7b63057ba8
commit
433e34cd9b
46
docs/source/api/as_args.rst
Normal file
46
docs/source/api/as_args.rst
Normal file
|
@ -0,0 +1,46 @@
|
|||
as_args
|
||||
=======
|
||||
turn an iterable argument into multiple arguments
|
||||
-------------------------------------------------
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
template <typename T>
|
||||
as_args_t { ... };
|
||||
|
||||
template <typename T>
|
||||
as_args_t<T> as_args( T&& );
|
||||
|
||||
|
||||
``sol::as_args`` is a function that that takes an iterable and turns it into multiple arguments to a function call. It forwards its arguments, and is meant to be used as shown below:
|
||||
|
||||
.. code-block:: cpp
|
||||
:caption: as_args.c++
|
||||
|
||||
#define SOL_CHECK_ARGUMENTS
|
||||
#include <sol.hpp>
|
||||
|
||||
#include <vector>
|
||||
#include <set>
|
||||
|
||||
int main(int argc, const char* argv[]) {
|
||||
|
||||
sol::state lua;
|
||||
lua.open_libraries();
|
||||
|
||||
lua.script("function f (a, b, c, d) print(a, b, c, d) end");
|
||||
|
||||
sol::function f = lua["f"];
|
||||
|
||||
std::vector<int> v2{ 3, 4 };
|
||||
f(1, 2, sol::as_args(v2));
|
||||
|
||||
std::set<int> v4{ 3, 1, 2, 4 };
|
||||
f(sol::as_args(v4));
|
||||
|
||||
int v3[] = { 2, 3, 4 };
|
||||
f(1, sol::as_args(v3));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -9,15 +9,21 @@ a separate state that can contain and run functions
|
|||
|
||||
``sol::thread`` is a separate runnable part of the Lua VM that can be used to execute work separately from the main thread, such as with :doc:`coroutines<coroutine>`. To take a table or a coroutine and run it specifically on the ``sol::thread`` you either pulled out of lua or created, just get that function through the :ref:`state of the thread<thread_state>`
|
||||
|
||||
.. note::
|
||||
|
||||
A CPU thread is not always equivalent to a new thread in Lua: ``std::this_thread::get_id()`` can be the same for 2 callbacks that have 2 distinct Lua threads. In order to know which thread a callback was called in, hook into :doc:`sol::this_state<this_state>` from your Lua callback and then construct a ``sol::thread``, passing in the ``sol::this_state`` for both the first and last arguments. Then examine the results of the status and ``is_...`` calls below.
|
||||
|
||||
members
|
||||
-------
|
||||
|
||||
.. code-block:: cpp
|
||||
:caption: constructor: thread
|
||||
|
||||
thread(stack_reference r);
|
||||
thread(lua_State* L, int index = -1);
|
||||
thread(lua_State* L, lua_State* actual_thread);
|
||||
|
||||
Takes a thread from the Lua stack at the specified index and allows a person to use all of the abstractions therein.
|
||||
Takes a thread from the Lua stack at the specified index and allows a person to use all of the abstractions therein. It can also take an actual thread state to make a thread from that as well.
|
||||
|
||||
.. code-block:: cpp
|
||||
:caption: function: view into thread_state()'s state
|
||||
|
@ -42,6 +48,13 @@ This function retrieves the ``lua_State*`` that represents the thread.
|
|||
|
||||
Retrieves the :doc:`thread status<types>` that describes the current state of the thread.
|
||||
|
||||
.. code-block:: cpp
|
||||
:caption: main thread status
|
||||
|
||||
bool is_main_thread () const;
|
||||
|
||||
Checks to see if the thread is the main Lua thread.
|
||||
|
||||
.. code-block:: cpp
|
||||
:caption: function: thread creation
|
||||
:name: thread-create
|
||||
|
|
|
@ -61,7 +61,7 @@ author = 'ThePhD'
|
|||
# The short X.Y version.
|
||||
version = '2.15'
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = '2.15.2'
|
||||
release = '2.15.3'
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
|
|
|
@ -20,8 +20,8 @@
|
|||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
// This file was generated with a script.
|
||||
// Generated 2016-11-26 08:32:10.873025 UTC
|
||||
// This header was generated with sol v2.15.2 (revision 289ded3)
|
||||
// Generated 2016-11-26 18:57:33.418806 UTC
|
||||
// This header was generated with sol v2.15.2 (revision 7b63057)
|
||||
// https://github.com/ThePhD/sol2
|
||||
|
||||
#ifndef SOL_SINGLE_INCLUDE_HPP
|
||||
|
@ -7041,6 +7041,35 @@ namespace sol {
|
|||
|
||||
// end of sol/stack.hpp
|
||||
|
||||
// beginning of sol/as_args.hpp
|
||||
|
||||
namespace sol {
|
||||
template <typename T>
|
||||
struct to_args_t {
|
||||
T src;
|
||||
};
|
||||
|
||||
template <typename Source>
|
||||
auto as_args(Source&& source) {
|
||||
return to_args_t<Source>{ std::forward<Source>(source) };
|
||||
}
|
||||
|
||||
namespace stack {
|
||||
template <typename T>
|
||||
struct pusher<to_args_t<T>> {
|
||||
int push(lua_State* L, const to_args_t<T>& e) {
|
||||
int p = 0;
|
||||
for (const auto& i : e.src) {
|
||||
p += stack::push(L, i);
|
||||
}
|
||||
return p;
|
||||
}
|
||||
};
|
||||
}
|
||||
} // sol
|
||||
|
||||
// end of sol/as_args.hpp
|
||||
|
||||
// beginning of sol/variadic_args.hpp
|
||||
|
||||
// beginning of sol/stack_proxy.hpp
|
||||
|
@ -12690,6 +12719,49 @@ namespace sol {
|
|||
// beginning of sol/thread.hpp
|
||||
|
||||
namespace sol {
|
||||
struct lua_thread_state {
|
||||
lua_State* L;
|
||||
operator lua_State* () const {
|
||||
return L;
|
||||
}
|
||||
lua_State* operator-> () const {
|
||||
return L;
|
||||
}
|
||||
};
|
||||
|
||||
namespace stack {
|
||||
|
||||
template <>
|
||||
struct pusher<lua_thread_state> {
|
||||
int push(lua_State*, lua_thread_state lts) {
|
||||
lua_pushthread(lts.L);
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct getter<lua_thread_state> {
|
||||
lua_thread_state get(lua_State* L, int index = -1) {
|
||||
lua_thread_state lts{ lua_tothread(L, index) };
|
||||
return lts;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct check_getter<lua_thread_state> {
|
||||
template <typename Handler>
|
||||
optional<lua_thread_state> get(lua_State* L, int index, Handler&& handler) {
|
||||
lua_thread_state lts{ lua_tothread(L, index) };
|
||||
if (lts.L == nullptr) {
|
||||
handler(L, index, type::thread, type_of(L, index));
|
||||
return nullopt;
|
||||
}
|
||||
return lts;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
class thread : public reference {
|
||||
public:
|
||||
thread() noexcept = default;
|
||||
|
@ -12704,11 +12776,25 @@ namespace sol {
|
|||
type_assert(L, index, type::thread);
|
||||
#endif // Safety
|
||||
}
|
||||
thread(lua_State* L, lua_State* actualthread) : thread(L, lua_thread_state{ actualthread }) {}
|
||||
thread(lua_State* L, sol::this_state actualthread) : thread(L, lua_thread_state{ actualthread.L }) {}
|
||||
thread(lua_State* L, lua_thread_state actualthread) : reference(L, -stack::push(L, actualthread)) {
|
||||
#ifdef SOL_CHECK_ARGUMENTS
|
||||
type_assert(L, -1, type::thread);
|
||||
#endif // Safety
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
state_view state() const {
|
||||
return state_view(this->thread_state());
|
||||
}
|
||||
|
||||
bool is_main_thread() const {
|
||||
int ismainthread = lua_pushthread(this->thread_state());
|
||||
lua_pop(this->thread_state(), 1);
|
||||
return ismainthread == 1;
|
||||
}
|
||||
|
||||
lua_State* thread_state() const {
|
||||
auto pp = stack::push_pop(*this);
|
||||
lua_State* lthread = lua_tothread(lua_state(), -1);
|
||||
|
|
52
sol/as_args.hpp
Normal file
52
sol/as_args.hpp
Normal file
|
@ -0,0 +1,52 @@
|
|||
// The MIT License (MIT)
|
||||
|
||||
// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors
|
||||
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
// this software and associated documentation files (the "Software"), to deal in
|
||||
// the Software without restriction, including without limitation the rights to
|
||||
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
// the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#ifndef SOL_TO_ARGS_HPP
|
||||
#define SOL_TO_ARGS_HPP
|
||||
|
||||
#include "stack.hpp"
|
||||
|
||||
namespace sol {
|
||||
template <typename T>
|
||||
struct to_args_t {
|
||||
T src;
|
||||
};
|
||||
|
||||
template <typename Source>
|
||||
auto as_args(Source&& source) {
|
||||
return to_args_t<Source>{ std::forward<Source>(source) };
|
||||
}
|
||||
|
||||
namespace stack {
|
||||
template <typename T>
|
||||
struct pusher<to_args_t<T>> {
|
||||
int push(lua_State* L, const to_args_t<T>& e) {
|
||||
int p = 0;
|
||||
for (const auto& i : e.src) {
|
||||
p += stack::push(L, i);
|
||||
}
|
||||
return p;
|
||||
}
|
||||
};
|
||||
}
|
||||
} // sol
|
||||
|
||||
#endif // SOL_TO_ARGS_HPP
|
|
@ -25,6 +25,7 @@
|
|||
#include "reference.hpp"
|
||||
#include "stack.hpp"
|
||||
#include "userdata.hpp"
|
||||
#include "as_args.hpp"
|
||||
#include "variadic_args.hpp"
|
||||
#include "optional.hpp"
|
||||
|
||||
|
|
|
@ -26,6 +26,49 @@
|
|||
#include "stack.hpp"
|
||||
|
||||
namespace sol {
|
||||
struct lua_thread_state {
|
||||
lua_State* L;
|
||||
operator lua_State* () const {
|
||||
return L;
|
||||
}
|
||||
lua_State* operator-> () const {
|
||||
return L;
|
||||
}
|
||||
};
|
||||
|
||||
namespace stack {
|
||||
|
||||
template <>
|
||||
struct pusher<lua_thread_state> {
|
||||
int push(lua_State*, lua_thread_state lts) {
|
||||
lua_pushthread(lts.L);
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct getter<lua_thread_state> {
|
||||
lua_thread_state get(lua_State* L, int index = -1) {
|
||||
lua_thread_state lts{ lua_tothread(L, index) };
|
||||
return lts;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct check_getter<lua_thread_state> {
|
||||
template <typename Handler>
|
||||
optional<lua_thread_state> get(lua_State* L, int index, Handler&& handler) {
|
||||
lua_thread_state lts{ lua_tothread(L, index) };
|
||||
if (lts.L == nullptr) {
|
||||
handler(L, index, type::thread, type_of(L, index));
|
||||
return nullopt;
|
||||
}
|
||||
return lts;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
class thread : public reference {
|
||||
public:
|
||||
thread() noexcept = default;
|
||||
|
@ -40,11 +83,25 @@ namespace sol {
|
|||
type_assert(L, index, type::thread);
|
||||
#endif // Safety
|
||||
}
|
||||
thread(lua_State* L, lua_State* actualthread) : thread(L, lua_thread_state{ actualthread }) {}
|
||||
thread(lua_State* L, sol::this_state actualthread) : thread(L, lua_thread_state{ actualthread.L }) {}
|
||||
thread(lua_State* L, lua_thread_state actualthread) : reference(L, -stack::push(L, actualthread)) {
|
||||
#ifdef SOL_CHECK_ARGUMENTS
|
||||
type_assert(L, -1, type::thread);
|
||||
#endif // Safety
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
state_view state() const {
|
||||
return state_view(this->thread_state());
|
||||
}
|
||||
|
||||
bool is_main_thread() const {
|
||||
int ismainthread = lua_pushthread(this->thread_state());
|
||||
lua_pop(this->thread_state(), 1);
|
||||
return ismainthread == 1;
|
||||
}
|
||||
|
||||
lua_State* thread_state() const {
|
||||
auto pp = stack::push_pop(*this);
|
||||
lua_State* lthread = lua_tothread(lua_state(), -1);
|
||||
|
|
|
@ -458,3 +458,35 @@ a.readonly_seq = value;
|
|||
)");
|
||||
REQUIRE_FALSE(result.valid());
|
||||
}
|
||||
|
||||
TEST_CASE("containers/to_args", "Test that the to_args abstractions works") {
|
||||
sol::state lua;
|
||||
lua.open_libraries();
|
||||
|
||||
lua.script("function f (a, b, c, d) print(a, b, c, d) return a, b, c, d end");
|
||||
|
||||
sol::function f = lua["f"];
|
||||
int a, b, c, d;
|
||||
|
||||
std::vector<int> v2{ 3, 4 };
|
||||
sol::tie(a, b, c, d) = f(1, 2, sol::as_args(v2));
|
||||
REQUIRE(a == 1);
|
||||
REQUIRE(b == 2);
|
||||
REQUIRE(c == 3);
|
||||
REQUIRE(d == 4);
|
||||
|
||||
std::set<int> v4{ 7, 6, 8, 5 };
|
||||
sol::tie(a, b, c, d) = f(sol::as_args(v4));
|
||||
REQUIRE(a == 5);
|
||||
REQUIRE(b == 6);
|
||||
REQUIRE(c == 7);
|
||||
REQUIRE(d == 8);
|
||||
|
||||
int v3[] = { 10, 11, 12 };
|
||||
sol::tie(a, b, c, d) = f(9, sol::as_args(v3));
|
||||
REQUIRE(a == 9);
|
||||
REQUIRE(b == 10);
|
||||
REQUIRE(c == 11);
|
||||
REQUIRE(d == 12);
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user