diff --git a/Results - Debug.html b/Results - Debug.html
new file mode 100644
index 00000000..9b2baac6
--- /dev/null
+++ b/Results - Debug.html
@@ -0,0 +1,433 @@
+
+
+
+
+ Sol - Functions (Debug) - nonius report
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Results - Release.html b/Results - Release.html
new file mode 100644
index 00000000..2e1fceea
--- /dev/null
+++ b/Results - Release.html
@@ -0,0 +1,433 @@
+
+
+
+
+ Sol - Functions (Release) - nonius report
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/bench.cpp b/bench.cpp
index 69120430..ed433788 100644
--- a/bench.cpp
+++ b/bench.cpp
@@ -1,6 +1,60 @@
#define NONIUS_RUNNER
#include "nonius/nonius.h++"
+#include "sol.hpp"
-NONIUS_BENCHMARK( "Function Calls", []() {
+struct sol_function_result_bench {
+ void operator () ( nonius::chronometer meter ) const {
+ sol::state lua;
+ lua.script( R"(
+function r ()
+ return 1 + 1
+end
+)" );
+ sol::function r = lua[ "r" ];
+ meter.measure( [ & ] ( int run_index ) {
+ // Measure cost of lua calling and returning a function
+ return r( );
+ } );
+ }
+};
-} );
\ No newline at end of file
+struct sol_direct_bench {
+ void operator () ( nonius::chronometer meter ) const {
+ sol::state lua;
+ lua.script( R"(
+function r ()
+ return 1 + 1
+end
+)" );
+ auto fun = [ & ] ( int run_index ) {
+ // Measure cost of lua calling and returning a function
+ sol::function r = lua[ "r" ];
+ return r.call( );
+ };
+ meter.measure( fun );
+ }
+};
+
+struct c_direct_bench {
+ void operator () ( nonius::chronometer meter ) const {
+ sol::state lua;
+ lua.script( R"(
+function r ()
+ return 1 + 1
+end
+)" );
+
+ lua_State* L = lua.lua_state( );
+ meter.measure( [ & ] ( int run_index ) {
+ lua_getglobal( L, "r" );
+ lua_call( L, 0, 1 );
+ int lua_out = (int)lua_tonumber( L, -1 );
+ lua_pop( L, 1 );
+ return lua_out;
+ } );
+ }
+};
+
+NONIUS_BENCHMARK( "sol - function_result", sol_function_result_bench() );
+NONIUS_BENCHMARK( "sol - int", sol_direct_bench() );
+NONIUS_BENCHMARK( "C - int", c_direct_bench( ) );
diff --git a/sol/function.hpp b/sol/function.hpp
index db6bfc7a..beca7969 100644
--- a/sol/function.hpp
+++ b/sol/function.hpp
@@ -128,40 +128,40 @@ private:
int stack;
handler(const reference& target) : target(target), stack(0) {
if (target.valid()) {
- stack = lua_gettop(target.state()) + 1;
+ stack = lua_gettop(target.lua_state()) + 1;
target.push();
}
}
~handler() {
if (stack > 0) {
- lua_remove(target.state(), stack);
+ lua_remove(target.lua_state(), stack);
}
}
};
int luacodecall(std::ptrdiff_t argcount, std::ptrdiff_t resultcount, handler& h) const {
- return lua_pcallk(state(), static_cast(argcount), static_cast(resultcount), h.stack, 0, nullptr);
+ return lua_pcallk(lua_state(), static_cast(argcount), static_cast(resultcount), h.stack, 0, nullptr);
}
void luacall(std::ptrdiff_t argcount, std::ptrdiff_t resultcount, handler& h) const {
- lua_callk(state(), static_cast(argcount), static_cast(resultcount), 0, nullptr);
+ lua_callk(lua_state(), static_cast(argcount), static_cast(resultcount), 0, nullptr);
}
template
std::tuple invoke(indices, types, std::ptrdiff_t n, handler& h) const {
luacall(n, sizeof...(Ret), h);
const int nreturns = static_cast(sizeof...(Ret));
- const int stacksize = lua_gettop(state());
+ const int stacksize = lua_gettop(lua_state());
const int firstreturn = std::max(0, stacksize - nreturns) + 1;
- auto r = std::make_tuple(stack::get(state(), firstreturn + I)...);
- lua_pop(state(), nreturns);
+ auto r = std::make_tuple(stack::get(lua_state(), firstreturn + I)...);
+ lua_pop(lua_state(), nreturns);
return r;
}
template
Ret invoke(indices, types, std::ptrdiff_t n, handler& h) const {
luacall(n, 1, h);
- return stack::pop(state());
+ return stack::pop(lua_state());
}
template
@@ -171,7 +171,7 @@ private:
function_result invoke(indices<>, types<>, std::ptrdiff_t n, handler& h) const {
const bool handlerpushed = error_handler.valid();
- const int stacksize = lua_gettop(state());
+ const int stacksize = lua_gettop(lua_state());
const int firstreturn = std::max(0, stacksize - static_cast(n) - 1);
int code = LUA_OK;
try {
@@ -181,27 +181,27 @@ private:
catch (const std::exception& error) {
code = LUA_ERRRUN;
h.stack = 0;
- stack::push(state(), error.what());
+ stack::push(lua_state(), error.what());
}
// TODO: handle idiots?
/*catch (const char* error) {
code = LUA_ERRRUN;
- stack::push(state(), error);
+ stack::push(lua_state(), error);
}
catch (const std::string& error) {
code = LUA_ERRRUN;
- stack::push(state(), error);
+ stack::push(lua_state(), error);
}
catch (...) {
code = LUA_ERRRUN;
- stack::push( state(), "[sol] an unknownable runtime exception occurred" );
+ stack::push( lua_state(), "[sol] an unknownable runtime exception occurred" );
}*/
catch (...) {
throw;
}
- const int poststacksize = lua_gettop(state());
+ const int poststacksize = lua_gettop(lua_state());
const int returncount = poststacksize - firstreturn;
- return function_result(state(), firstreturn + ( handlerpushed ? 0 : 1 ), returncount, static_cast(code));
+ return function_result(lua_state(), firstreturn + ( handlerpushed ? 0 : 1 ), returncount, static_cast(code));
}
public:
@@ -232,7 +232,7 @@ public:
-> decltype(invoke(types(), types(), 0, std::declval())) {
handler h(error_handler);
push();
- int pushcount = stack::push_args(state(), std::forward(args)...);
+ int pushcount = stack::push_args(lua_state(), std::forward(args)...);
auto tr = types();
return invoke(tr, tr, pushcount, h);
}
diff --git a/sol/object.hpp b/sol/object.hpp
index 02759208..142060aa 100644
--- a/sol/object.hpp
+++ b/sol/object.hpp
@@ -33,14 +33,14 @@ public:
object() = default;
template
- auto as() const -> decltype(stack::get(state())) const {
+ auto as() const -> decltype(stack::get(lua_state())) const {
push();
- type actual = stack::get(state());
+ type actual = stack::get(lua_state());
// This code is actually present
// in almost all of the type-getters,
// and it thus insanely redundant
- // type_assert(state(), -1, type_of(), actual);
- return stack::pop(state());
+ // type_assert(lua_state(), -1, type_of(), actual);
+ return stack::pop(lua_state());
}
template
diff --git a/sol/reference.hpp b/sol/reference.hpp
index 4d44636a..69e41720 100644
--- a/sol/reference.hpp
+++ b/sol/reference.hpp
@@ -97,7 +97,7 @@ public:
return static_cast(result);
}
- lua_State* state() const noexcept {
+ lua_State* lua_state() const noexcept {
return L;
}
};
diff --git a/sol/state.hpp b/sol/state.hpp
index 6b83d60a..b4700ef6 100644
--- a/sol/state.hpp
+++ b/sol/state.hpp
@@ -30,7 +30,7 @@ namespace sol {
namespace detail {
inline int atpanic(lua_State* L) {
const char* message = lua_tostring(L, -1);
- std::string err = message ? message : "An unexpected error occured and forced the lua state to call atpanic";
+ std::string err = message ? message : "An unexpected error occurred and forced the lua state to call atpanic";
throw error(err);
}
} // detail
@@ -53,18 +53,12 @@ class state {
private:
std::unique_ptr L;
table reg;
- table global;
+ global_table globals;
public:
state(lua_CFunction panic = detail::atpanic):
L(luaL_newstate(), lua_close),
reg(L.get(), LUA_REGISTRYINDEX),
-#if SOL_LUA_VERSION < 502
- // Global table is just a special index
- global(L.get(), LUA_GLOBALSINDEX) {
-#else
- // Global tables are stored in the environment/registry table
- global(reg.get(LUA_RIDX_GLOBALS)) {
-#endif // Lua 5.2
+ globals(detail::global_overload, reg) {
set_panic(panic);
}
@@ -152,13 +146,13 @@ public:
template
auto get(Keys&&... keys) const
- -> decltype(global.get(std::forward(keys)...)) {
- return global.get(std::forward(keys)...);
+ -> decltype(globals.get(std::forward(keys)...)) {
+ return globals.get(std::forward(keys)...);
}
template
state& set(T&& key, U&& value) {
- global.set(std::forward(key), std::forward(value));
+ globals.set(std::forward(key), std::forward(value));
return *this;
}
@@ -189,7 +183,7 @@ public:
template
state& set_usertype(Key&& key, usertype& user) {
- global.set_usertype(std::forward(key), user);
+ globals.set_usertype(std::forward(key), user);
return *this;
}
@@ -208,7 +202,7 @@ public:
template
void for_each(Fx&& fx) {
- global.for_each(std::forward(fx));
+ globals.for_each(std::forward(fx));
}
template
@@ -216,7 +210,7 @@ public:
lua_createtable(L.get(), narr, nrec);
table result(L.get());
lua_pop(L.get(), 1);
- global.set(std::forward(key), result);
+ globals.set(std::forward(key), result);
return result;
}
@@ -227,8 +221,8 @@ public:
return result;
}
- table global_table() const {
- return global;
+ global_table global() const {
+ return globals;
}
table registry() const {
@@ -240,42 +234,42 @@ public:
}
template
- proxy operator[](T&& key) {
- return global[std::forward(key)];
+ proxy operator[](T&& key) {
+ return globals[std::forward(key)];
}
template
- proxy operator[](T&& key) const {
- return global[std::forward(key)];
+ proxy operator[](T&& key) const {
+ return globals[std::forward(key)];
}
template
state& set_function(Key&& key, R fun_ptr(Args...)){
- global.set_function(std::forward(key), fun_ptr);
+ globals.set_function(std::forward(key), fun_ptr);
return *this;
}
template
state& set_function(Key&& key, Sig* fun_ptr){
- global.set_function(std::forward(key), fun_ptr);
+ globals.set_function(std::forward(key), fun_ptr);
return *this;
}
template
state& set_function(Key&& key, R (C::*mem_ptr)(Args...), T&& obj) {
- global.set_function(std::forward(key), mem_ptr, std::forward(obj));
+ globals.set_function(std::forward(key), mem_ptr, std::forward(obj));
return *this;
}
template
state& set_function(Key&& key, Sig C::* mem_ptr, T&& obj) {
- global.set_function(std::forward(key), mem_ptr, std::forward(obj));
+ globals.set_function(std::forward(key), mem_ptr, std::forward(obj));
return *this;
}
template
state& set_function(Key&& key, Fx&& fx) {
- global.set_function(std::forward(key), std::forward(fx));
+ globals.set_function(std::forward(key), std::forward(fx));
return *this;
}
};
diff --git a/sol/table.hpp b/sol/table.hpp
index 174bee83..6bf20226 100644
--- a/sol/table.hpp
+++ b/sol/table.hpp
@@ -22,167 +22,10 @@
#ifndef SOL_TABLE_HPP
#define SOL_TABLE_HPP
-#include "proxy.hpp"
-#include "stack.hpp"
-#include "function_types.hpp"
-#include "usertype.hpp"
+#include "table_core.hpp"
namespace sol {
-class table : public reference {
- friend class state;
- template
- stack::get_return single_get(Key&& key) const {
- push();
- stack::push(state(), std::forward(key));
- lua_gettable(state(), -2);
- stack::get_return result = stack::pop(state());
- pop();
- return result;
- }
-
- template
- stack::get_return tuple_get(types, indices, Keys&& keys) const {
- return stack::get_return(single_get(std::get(keys))...);
- }
-
- template
- stack::get_return tuple_get(types, indices, Keys&& keys) const {
- return single_get(std::get(keys));
- }
-
-public:
- table() noexcept : reference() {}
- table(lua_State* L, int index = -1) : reference(L, index) {
- type_assert(L, index, type::table);
- }
-
- template
- stack::get_return get( Keys&&... keys ) const {
- return tuple_get(types(), build_indices(), std::tie(keys...));
- }
-
- template
- table& set(T&& key, U&& value) {
- push();
- stack::push(state(), std::forward(key));
- stack::push(state(), std::forward(value));
- lua_settable(state(), -3);
- lua_pop(state(), 1);
- return *this;
- }
-
- template
- SOL_DEPRECATED table& set_userdata(usertype& user) {
- return set_usertype(user);
- }
-
- template
- SOL_DEPRECATED table& set_userdata(Key&& key, usertype& user) {
- return set_usertype(std::forward(key), user);
- }
-
- template
- table& set_usertype(usertype& user) {
- return set_usertype(usertype_traits::name, user);
- }
-
- template
- table& set_usertype(Key&& key, usertype& user) {
- push();
- stack::push(state(), std::forward(key));
- stack::push(state(), user);
- lua_settable(state(), -3);
- lua_pop(state(), 1);
- return *this;
- }
-
- template
- void for_each(Fx&& fx) const {
- push();
- stack::push(state(), nil);
- while (lua_next(this->state(), -2)) {
- sol::object key(state(), -2);
- sol::object value(state(), -1);
- fx(key, value);
- lua_pop(state(), 1);
- }
- pop();
- }
-
- size_t size() const {
- push();
- size_t result = lua_rawlen(state(), -1);
- pop();
- return result;
- }
-
- template
- proxy operator[]( T&& key ) {
- return proxy( *this, std::forward( key ) );
- }
-
- template
- proxy operator[]( T&& key ) const {
- return proxy( *this, std::forward( key ) );
- }
-
- void pop(int n = 1) const noexcept {
- lua_pop(state(), n);
- }
-
- template
- table& set_function(Key&& key, R fun_ptr(Args...)){
- set_resolved_function(std::forward(key), fun_ptr);
- return *this;
- }
-
- template
- table& set_function(Key&& key, Sig* fun_ptr){
- set_resolved_function(std::forward(key), fun_ptr);
- return *this;
- }
-
- template
- table& set_function(Key&& key, R (C::*mem_ptr)(Args...), T&& obj) {
- set_resolved_function(std::forward(key), mem_ptr, std::forward(obj));
- return *this;
- }
-
- template
- table& set_function(Key&& key, Sig C::* mem_ptr, T&& obj) {
- set_resolved_function(std::forward(key), mem_ptr, std::forward(obj));
- return *this;
- }
-
- template
- table& set_function(Key&& key, Fx&& fx) {
- set_fx(types(), std::forward(key), std::forward(fx));
- return *this;
- }
-
-private:
- template::type>
- void set_fx(types, Key&& key, Fx&& fx) {
- set_resolved_function(std::forward(key), std::forward(fx));
- }
-
- template
- void set_fx(types<>, Key&& key, Fx&& fx) {
- typedef Unqualified> fx_t;
- typedef decltype(&fx_t::operator()) Sig;
- set_fx(types>(), std::forward(key), std::forward(fx));
- }
-
- template
- void set_resolved_function(Key&& key, Args&&... args) {
- std::string fkey(std::forward(key));
- push();
- int tabletarget = lua_gettop(state());
- stack::push>(state(), std::forward(args)...);
- lua_setfield(state(), tabletarget, fkey.c_str());
- pop();
- }
-};
+ typedef table_core table;
} // sol
#endif // SOL_TABLE_HPP
diff --git a/sol/table_core.hpp b/sol/table_core.hpp
new file mode 100644
index 00000000..0ecd1e85
--- /dev/null
+++ b/sol/table_core.hpp
@@ -0,0 +1,224 @@
+// The MIT License (MIT)
+
+// Copyright (c) 2013-2015 Danny Y., Rapptz
+
+// 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_TABLE_CORE_HPP
+#define SOL_TABLE_CORE_HPP
+
+#include "proxy.hpp"
+#include "stack.hpp"
+#include "function_types.hpp"
+#include "usertype.hpp"
+
+namespace sol {
+namespace detail {
+ struct global_overload_tag { } const global_overload;
+} // detail
+
+template
+class table_core : public reference {
+ friend class state;
+ template>>, Bool> = 0>
+ stack::get_return single_get( Key&& key ) const {
+ lua_getglobal( lua_state( ), &key[ 0 ] );
+ stack::get_return result = stack::pop( lua_state( ) );
+ return result;
+ }
+
+ template>>, Bool> = 0>
+ stack::get_return single_get( Key&& key ) const {
+ push( );
+ stack::push( lua_state( ), std::forward( key ) );
+ lua_gettable( lua_state( ), -2 );
+ stack::get_return result = stack::pop( lua_state( ) );
+ pop( );
+ return result;
+ }
+
+ template
+ stack::get_return tuple_get( types, indices, Keys&& keys ) const {
+ return stack::get_return( single_get( std::get( keys ) )... );
+ }
+
+ template
+ stack::get_return tuple_get( types, indices, Keys&& keys ) const {
+ return single_get( std::get( keys ) );
+ }
+
+#if SOL_LUA_VERSION < 502
+ table_core( detail::global_overload_tag, const table_core& reg ) noexcept : reference( reg.lua_state(), LUA_GLOBALSINDEX ) { }
+#else
+ table_core( detail::global_overload_tag, const table& reg ) noexcept : reference( reg.get( LUA_RIDX_GLOBALS ) ) { }
+#endif
+public:
+ table_core( ) noexcept : reference( ) { }
+ table_core( const table_core& global ) : reference( global ) { }
+ table_core( lua_State* L, int index = -1 ) : reference( L, index ) {
+ type_assert( L, index, type::table );
+ }
+
+ template
+ stack::get_return get( Keys&&... keys ) const {
+ return tuple_get( types( ), build_indices( ), std::tie( keys... ) );
+ }
+
+ template
+ table_core& set( T&& key, U&& value ) {
+ if ( top_level ) {
+ stack::push( lua_state( ), std::forward( value ) );
+ lua_setglobal( lua_state( ), &key[0] );
+ }
+ else {
+ push( );
+ stack::push( lua_state( ), std::forward( key ) );
+ stack::push( lua_state( ), std::forward( value ) );
+ lua_settable( lua_state( ), -3 );
+ pop( );
+ }
+ return *this;
+ }
+
+ template
+ SOL_DEPRECATED table_core& set_userdata( usertype& user ) {
+ return set_usertype( user );
+ }
+
+ template
+ SOL_DEPRECATED table_core& set_userdata( Key&& key, usertype& user ) {
+ return set_usertype( std::forward( key ), user );
+ }
+
+ template
+ table_core& set_usertype( usertype& user ) {
+ return set_usertype( usertype_traits::name, user );
+ }
+
+ template
+ table_core& set_usertype( Key&& key, usertype& user ) {
+ if ( top_level ) {
+ stack::push( lua_state( ), user );
+ lua_setglobal( lua_state( ), &key[ 0 ] );
+ pop( );
+ }
+ else {
+ push( );
+ stack::push( lua_state( ), std::forward( key ) );
+ stack::push( lua_state( ), user );
+ lua_settable( lua_state( ), -3 );
+ pop( );
+ }
+ return *this;
+ }
+
+ template
+ void for_each( Fx&& fx ) const {
+ push( );
+ stack::push( lua_state( ), nil );
+ while ( lua_next( this->lua_state( ), -2 ) ) {
+ sol::object key( lua_state( ), -2 );
+ sol::object value( lua_state( ), -1 );
+ fx( key, value );
+ lua_pop( lua_state( ), 1 );
+ }
+ pop( );
+ }
+
+ size_t size( ) const {
+ push( );
+ size_t result = lua_rawlen( lua_state( ), -1 );
+ pop( );
+ return result;
+ }
+
+ template
+ proxy operator[]( T&& key ) {
+ return proxy( *this, std::forward( key ) );
+ }
+
+ template
+ proxy operator[]( T&& key ) const {
+ return proxy( *this, std::forward( key ) );
+ }
+
+ void pop( int n = 1 ) const noexcept {
+ lua_pop( lua_state( ), n );
+ }
+
+ template
+ table_core& set_function( Key&& key, R fun_ptr( Args... ) ) {
+ set_resolved_function( std::forward( key ), fun_ptr );
+ return *this;
+ }
+
+ template
+ table_core& set_function( Key&& key, Sig* fun_ptr ) {
+ set_resolved_function( std::forward( key ), fun_ptr );
+ return *this;
+ }
+
+ template
+ table_core& set_function( Key&& key, R( C::*mem_ptr )( Args... ), T&& obj ) {
+ set_resolved_function( std::forward( key ), mem_ptr, std::forward( obj ) );
+ return *this;
+ }
+
+ template
+ table_core& set_function( Key&& key, Sig C::* mem_ptr, T&& obj ) {
+ set_resolved_function( std::forward( key ), mem_ptr, std::forward( obj ) );
+ return *this;
+ }
+
+ template
+ table_core& set_function( Key&& key, Fx&& fx ) {
+ set_fx( types( ), std::forward( key ), std::forward( fx ) );
+ return *this;
+ }
+
+private:
+ template::type>
+ void set_fx( types, Key&& key, Fx&& fx ) {
+ set_resolved_function( std::forward( key ), std::forward( fx ) );
+ }
+
+ template
+ void set_fx( types<>, Key&& key, Fx&& fx ) {
+ typedef Unqualified> fx_t;
+ typedef decltype( &fx_t::operator() ) Sig;
+ set_fx( types>( ), std::forward