as_args and threading API cleanliness.

This commit is contained in:
ThePhD 2016-11-26 13:58:06 -05:00
parent 7b63057ba8
commit 433e34cd9b
8 changed files with 291 additions and 4 deletions

View 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;
}

View File

@ -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

View File

@ -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.

View File

@ -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
View 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

View File

@ -25,6 +25,7 @@
#include "reference.hpp"
#include "stack.hpp"
#include "userdata.hpp"
#include "as_args.hpp"
#include "variadic_args.hpp"
#include "optional.hpp"

View File

@ -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);

View File

@ -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);
}