From 6ceb71591280cff74aa5608eed630cc06637f923 Mon Sep 17 00:00:00 2001 From: ThePhD Date: Wed, 22 Mar 2017 22:34:24 -0400 Subject: [PATCH] Ownership documentation. --- docs/source/api/reference.rst | 8 ++++-- docs/source/api/stack_reference.rst | 2 ++ docs/source/safety.rst | 6 ++++- docs/source/tutorial/all-the-things.rst | 2 +- docs/source/tutorial/ownership.rst | 35 ++++++++++++++++++++++++- 5 files changed, 48 insertions(+), 5 deletions(-) diff --git a/docs/source/api/reference.rst b/docs/source/api/reference.rst index 57869de7..43c163a7 100644 --- a/docs/source/api/reference.rst +++ b/docs/source/api/reference.rst @@ -8,9 +8,13 @@ general purpose reference to Lua object in registry class reference; -This type keeps around a reference to something that was on the stack and places it in the Lua registry. It is the backbone for all things that reference items on the stack and needs to keep them around beyond their appearance and lifetime on said Lua stack. Its progeny include :doc:`sol::coroutine`, :doc:`sol::function`, :doc:`sol::protected_function`, :doc:`sol::object`, :doc:`sol::table`/:doc:`sol::global_table
`, :doc:`sol::thread`, and :doc:`sol::userdata`. +This type keeps around a reference to something inside of Lua, whether that object was on the stack or already present as an object in the Lua Runtime. It places the object Lua registry and will keep it alive. -For all of these types, there's also a ``stack_{x}`` version of them, such as ``stack_table`` +It is the backbone for all things that reference items on the stack and needs to keep them around beyond their appearance and lifetime on said Lua stack or need to be kept alive outside of a script beyond garbage collection times. Its progeny include :doc:`sol::coroutine`, :doc:`sol::function`, :doc:`sol::protected_function`, :doc:`sol::object`, :doc:`sol::table
`/:doc:`sol::global_table
`, :doc:`sol::thread`, and :doc:`sol::userdata`, which are type-specific versions of ``sol::reference``. + +Note that if you need to keep a reference to something inside of Lua, it is better to use ``sol::reference`` or :doc:`sol::object` to keep a reference to it and then use the ``obj.as()`` member function to retrieve what you need than to take a direct dependency on the memory by retrieving a pointer or reference to the userdata itself. This will ensure that if a script or the Lua Runtime is finished with an object, it will not be garbage collected. Do this only if you need long-term storage. + +For all of these types, there's also a ``sol::stack_{x}`` version of them, such as ``sol::stack_table``. members diff --git a/docs/source/api/stack_reference.rst b/docs/source/api/stack_reference.rst index db5359d1..ebac5256 100644 --- a/docs/source/api/stack_reference.rst +++ b/docs/source/api/stack_reference.rst @@ -5,4 +5,6 @@ zero-overhead object on the stack When you work with a :doc:`sol::reference`, the object gotten from the stack has a reference to it made in the registry, keeping it alive. If you want to work with the Lua stack directly without having any additional references made, ``sol::stack_reference`` is for you. Its API is identical to ``sol::reference`` in every way, except it contains a ``int stack_index()`` member function that allows you to retrieve the stack index. +Note that this will not pin the object since a copy is not made in the registry, meaning things can be pulled out from under it, the stack can shrink under it, things can be added onto the stack before this object's position, and what ``sol::stack_reference`` will point to will change. Please know what the Lua stack is and have discipline while managing your Lua stack when working at this level. + All of the base types have ``stack`` versions of themselves, and the APIs are identical to their non-stack forms. This includes :doc:`sol::stack_table
`, :doc:`sol::stack_function`, :doc:`sol::stack_protected_function`, :doc:`sol::stack_(light\_)userdata` and :doc:`sol::stack_object`. \ No newline at end of file diff --git a/docs/source/safety.rst b/docs/source/safety.rst index a6b1a59b..f9baac55 100644 --- a/docs/source/safety.rst +++ b/docs/source/safety.rst @@ -23,8 +23,12 @@ Note that you can obtain safety with regards to functions you bind by using the Tests are compiled with this on to ensure everything is going as expected. Remember that if you want these features, you must explicitly turn them on all of them to be sure you are getting them. -Finally, some warnings that may help with errors when working with Sol: +memory +------ +Memory safety can be tricky. Lua is handled by a garbage-collected runtime, meaning object deletion is not cleary defined or deterministic. If you need to keep an object from the Lua Runtime alive, use :doc:`sol::reference` or one of its derived types, such as :doc:`sol::table`, :doc:`sol::object`, or similar. These will pin a reference down to an object controlled in C++, and Lua will not delete an object that you still have a reference to through one of these types. You can then retrieve whatever you need from that Lua slot using object's ``obj.as()`` member function or other things, and work on the memory from there. + +The usertype memory layout for all Lua-instantiated userdata and for all objects pushed/set into the Lua Runtime is also described :doc:`here`. Things before or after that specified memory slot is implementation-defined and no assumptions are to be made about it. functions --------- diff --git a/docs/source/tutorial/all-the-things.rst b/docs/source/tutorial/all-the-things.rst index d95f60c7..cd7ec63a 100644 --- a/docs/source/tutorial/all-the-things.rst +++ b/docs/source/tutorial/all-the-things.rst @@ -613,7 +613,7 @@ advanced Some more advanced things you can do/read about: * :doc:`metatable manipulations<../api/metatable_key>` allow a user to change how indexing, function calls, and other things work on a single type. - * :doc:`ownership semantics` are described for how lua deals with (raw) pointers. + * :doc:`ownership semantics` are described for how Lua deals with its own internal references and (raw) pointers. * :doc:`stack manipulation<../api/stack>` to safely play with the stack. You can also define customization points for ``stack::get``/``stack::check``/``stack::push`` for your type. * :doc:`make_reference/make_object convenience function<../api/make_reference>` to get the same benefits and conveniences as the low-level stack API but put into objects you can specify. * :doc:`stack references<../api/stack_reference>` to have zero-overhead Sol abstractions while not copying to the Lua registry. diff --git a/docs/source/tutorial/ownership.rst b/docs/source/tutorial/ownership.rst index 96eb350d..a70112ba 100644 --- a/docs/source/tutorial/ownership.rst +++ b/docs/source/tutorial/ownership.rst @@ -1,7 +1,40 @@ ownership ========= -Sol will not take ownership of raw pointers: raw pointers do not own anything. +You can take a reference to something that exists in Lua by pulling out a :doc:`sol::reference<../api/reference>` or a :doc:`sol::object<../api/object>`: + +.. code-block:: cpp + + sol::state lua; + lua.open_libraries(sol::lib::base); + + lua.script(R"( + obj = "please don't let me die"; + )"); + + sol::object keep_alive = lua["obj"]; + lua.script(R"( + obj = nil; + function say(msg) + print(msg) + end + )"); + + lua.collect_garbage(); + + lua["say"](lua["obj"]); + // still accessible here and still alive in Lua + // even though the name was cleared + std::string message = keep_alive.as(); + std::cout << message << std::endl; + + // Can be pushed back into Lua as an argument + // or set to a new name, + // whatever you like! + lua["say"](keep_alive); + + +Sol will not take ownership of raw pointers: raw pointers do not own anything. Sol will not delete raw pointers, because they do not (and are not supposed to) own anything: .. code-block:: cpp