From 1013970853e6acfd60591a89ae08cc40c64bee06 Mon Sep 17 00:00:00 2001
From: Benoit Germain
Date: Tue, 14 May 2024 10:05:54 +0200
Subject: Moved Lane tracking implementation in a separate file
---
docs/index.html | 4 +-
lanes-4.0.0-0.rockspec | 1 +
src/Makefile | 4 +-
src/lanes.cpp | 91 ++++-------------------------------------
src/tools.cpp | 1 +
src/tracker.cpp | 108 +++++++++++++++++++++++++++++++++++++++++++++++++
src/tracker.h | 35 ++++++++++++++++
src/universe.h | 7 +---
8 files changed, 159 insertions(+), 92 deletions(-)
create mode 100644 src/tracker.cpp
create mode 100644 src/tracker.h
diff --git a/docs/index.html b/docs/index.html
index 3c9cbcf..713955f 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -70,7 +70,7 @@
- This document was revised on 9-Apr-24, and applies to version 4.0.0.
+ This document was revised on 15-May-24, and applies to version 4.0.0.
@@ -1723,7 +1723,7 @@ static MyDeepFactory g_MyDeepFactory;
Take a look at LindaFactory in linda.cpp or MyDeepFactory in deep_test.cpp.
- Include "deep.h" and either link against Lanes or statically compile compat.cpp deep.cpp tools.cpp universe.cpp into your module if you want to avoid a runtime dependency for users that will use your module without Lanes.
+ Include "deep.h" and either link against Lanes or statically compile compat.cpp deep.cpp into your module if you want to avoid a runtime dependency for users that will use your module without Lanes.
Instanciate your userdata using yourFactoryObject.pushDeepUserdata(), instead of the regular lua_newuserdata(). Given a factory, it sets up the support structures and returns a state-specific proxy userdata for accessing your data. This proxy can also be copied over to other lanes.
Accessing the deep userdata from your C code, use yourFactoryObject.toDeep() instead of the regular lua_touserdata().
diff --git a/lanes-4.0.0-0.rockspec b/lanes-4.0.0-0.rockspec
index ccfaf86..1c056e8 100644
--- a/lanes-4.0.0-0.rockspec
+++ b/lanes-4.0.0-0.rockspec
@@ -71,6 +71,7 @@ build = {
"src/tools.cpp",
"src/state.cpp",
"src/threading.cpp",
+ "src/tracker.cpp",
"src/universe.cpp"
},
incdirs = { "src"},
diff --git a/src/Makefile b/src/Makefile
index bbe7b23..fddc45e 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -7,9 +7,9 @@
MODULE=lanes
-SRC=lanes.c cancel.cpp compat.cpp threading.cpp tools.cpp state.cpp linda.cpp lindafactory.cpp deep.cpp keeper.cpp universe.cpp intercopycontext.cpp
+SRC=cancel.cpp compat.cpp deep.cpp intercopycontext.cpp keeper.cpp lanes.cpp linda.cpp lindafactory.cpp state.cpp threading.cpp tools.cpp tracker.cpp universe.cpp
-OBJ=$(SRC:.c=.o)
+OBJ=$(SRC:.cpp=.o)
# LuaRocks gives 'LIBFLAG' from the outside
#
diff --git a/src/lanes.cpp b/src/lanes.cpp
index 9c9d7d1..f8efa42 100644
--- a/src/lanes.cpp
+++ b/src/lanes.cpp
@@ -104,67 +104,12 @@ THE SOFTWARE.
// #################################################################################################
-#if HAVE_LANE_TRACKING()
-
-// The chain is ended by '(Lane*)(-1)', not nullptr:
-// 'trackingFirst -> ... -> ... -> (-1)'
-#define TRACKING_END ((Lane*) (-1))
-
-/*
- * Add the lane to tracking chain; the ones still running at the end of the
- * whole process will be cancelled.
- */
-static void tracking_add(Lane* lane_)
-{
- std::lock_guard _guard{ lane_->U->trackingMutex };
- assert(lane_->tracking_next == nullptr);
-
- lane_->tracking_next = lane_->U->trackingFirst;
- lane_->U->trackingFirst = lane_;
-}
-
-// #################################################################################################
-
-/*
- * A free-running lane has ended; remove it from tracking chain
- */
-[[nodiscard]] static bool tracking_remove(Lane* lane_)
-{
- bool _found{ false };
- std::lock_guard _guard{ lane_->U->trackingMutex };
- // Make sure (within the MUTEX) that we actually are in the chain
- // still (at process exit they will remove us from chain and then
- // cancel/kill).
- //
- if (lane_->tracking_next != nullptr) {
- Lane** _ref = (Lane**) &lane_->U->trackingFirst;
-
- while (*_ref != TRACKING_END) {
- if (*_ref == lane_) {
- *_ref = lane_->tracking_next;
- lane_->tracking_next = nullptr;
- _found = true;
- break;
- }
- _ref = (Lane**) &((*_ref)->tracking_next);
- }
- assert(_found);
- }
- return _found;
-}
-
-#endif // HAVE_LANE_TRACKING()
-
-// #################################################################################################
-
Lane::Lane(Universe* U_, lua_State* L_)
: U{ U_ }
, L{ L_ }
{
#if HAVE_LANE_TRACKING()
- if (U->trackingFirst) {
- tracking_add(this);
- }
+ U->tracker.tracking_add(this);
#endif // HAVE_LANE_TRACKING()
}
@@ -241,10 +186,7 @@ Lane::~Lane()
// Clean up after a (finished) thread
//
#if HAVE_LANE_TRACKING()
- if (U->trackingFirst != nullptr) {
- // Lane was cleaned up, no need to handle at process termination
- std::ignore = tracking_remove(this);
- }
+ std::ignore = U->tracker.tracking_remove(this);
#endif // HAVE_LANE_TRACKING()
}
@@ -1428,27 +1370,8 @@ LUAG_FUNC(thread_index)
// Return a list of all known lanes
LUAG_FUNC(threads)
{
- int const _top{ lua_gettop(L_) };
- Universe* const _U{ universe_get(L_) };
-
- // List _all_ still running threads
- std::lock_guard _guard{ _U->trackingMutex };
- if (_U->trackingFirst && _U->trackingFirst != TRACKING_END) {
- Lane* _lane{ _U->trackingFirst };
- int _index{ 0 };
- lua_newtable(L_); // L_: {}
- while (_lane != TRACKING_END) {
- // insert a { name='', status='' } tuple, so that several lanes with the same name can't clobber each other
- lua_createtable(L_, 0, 2); // L_: {} {}
- lua_pushstring(L_, _lane->debugName); // L_: {} {} "name"
- lua_setfield(L_, -2, "name"); // L_: {} {}
- _lane->pushThreadStatus(L_); // L_: {} {} "status"
- lua_setfield(L_, -2, "status"); // L_: {} {}
- lua_rawseti(L_, -2, ++_index); // L_: {}
- _lane = _lane->tracking_next;
- }
- }
- return lua_gettop(L_) - _top; // L_: 0 or 1
+ LaneTracker const& _tracker = universe_get(L_)->tracker;
+ return _tracker.pushThreadsTable(L_);
}
#endif // HAVE_LANE_TRACKING()
@@ -1668,7 +1591,9 @@ LUAG_FUNC(configure)
lua_pop(L_, 1); // L_: settings
#if HAVE_LANE_TRACKING()
lua_getfield(L_, 1, "track_lanes"); // L_: settings track_lanes
- _U->trackingFirst = lua_toboolean(L_, -1) ? TRACKING_END : nullptr;
+ if (lua_toboolean(L_, -1)) {
+ _U->tracker.activate();
+ }
lua_pop(L_, 1); // L_: settings
#endif // HAVE_LANE_TRACKING()
// Linked chains handling
@@ -1704,7 +1629,7 @@ LUAG_FUNC(configure)
luaG_registerlibfuncs(L_, global::sLanesFunctions);
#if HAVE_LANE_TRACKING()
// register core.threads() only if settings say it should be available
- if (_U->trackingFirst != nullptr) {
+ if (_U->tracker.isActive()) {
lua_pushcfunction(L_, LG_threads); // L_: settings M LG_threads()
lua_setfield(L_, -2, "threads"); // L_: settings M
}
diff --git a/src/tools.cpp b/src/tools.cpp
index 0cfe1ab..3e6224a 100644
--- a/src/tools.cpp
+++ b/src/tools.cpp
@@ -523,3 +523,4 @@ int luaG_nameof(lua_State* L_)
lua_replace(L_, -3); // L_: "type" "result"
return 2;
}
+
\ No newline at end of file
diff --git a/src/tracker.cpp b/src/tracker.cpp
new file mode 100644
index 0000000..e6affb2
--- /dev/null
+++ b/src/tracker.cpp
@@ -0,0 +1,108 @@
+/*
+===============================================================================
+
+Copyright (C) 2024 Benoit Germain
+
+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.
+
+===============================================================================
+*/
+#include "tracker.h"
+#include "lanes_private.h"
+
+// #################################################################################################
+
+#if HAVE_LANE_TRACKING()
+
+/*
+ * Add the lane to tracking chain; the ones still running at the end of the
+ * whole process will be cancelled.
+ */
+void LaneTracker::tracking_add(Lane* lane_)
+{
+ if (!isActive()) {
+ return;
+ }
+ std::lock_guard _guard{ trackingMutex };
+ assert(lane_->tracking_next == nullptr);
+
+ lane_->tracking_next = trackingFirst;
+ trackingFirst = lane_;
+}
+
+// #################################################################################################
+
+/*
+ * A free-running lane has ended; remove it from tracking chain
+ */
+[[nodiscard]] bool LaneTracker::tracking_remove(Lane* lane_)
+{
+ if (!isActive()) {
+ return false;
+ }
+
+ bool _found{ false };
+ std::lock_guard _guard{ trackingMutex };
+ // Make sure (within the MUTEX) that we actually are in the chain
+ // still (at process exit they will remove us from chain and then
+ // cancel/kill).
+ //
+ if (lane_->tracking_next != nullptr) {
+ Lane** _ref = (Lane**) &trackingFirst;
+
+ while (*_ref != TRACKING_END) {
+ if (*_ref == lane_) {
+ *_ref = lane_->tracking_next;
+ lane_->tracking_next = nullptr;
+ _found = true;
+ break;
+ }
+ _ref = (Lane**) &((*_ref)->tracking_next);
+ }
+ assert(_found);
+ }
+ return _found;
+}
+
+// ################################################################################################
+
+[[nodiscard]] int LaneTracker::pushThreadsTable(lua_State* L_) const
+{
+ int const _top{ lua_gettop(L_) };
+ // List _all_ still running threads
+ std::lock_guard _guard{ trackingMutex };
+ if (trackingFirst && trackingFirst != TRACKING_END) {
+ Lane* _lane{ trackingFirst };
+ int _index{ 0 };
+ lua_newtable(L_); // L_: {}
+ while (_lane != TRACKING_END) {
+ // insert a { name='', status='' } tuple, so that several lanes with the same name can't clobber each other
+ lua_createtable(L_, 0, 2); // L_: {} {}
+ lua_pushstring(L_, _lane->debugName); // L_: {} {} "name"
+ lua_setfield(L_, -2, "name"); // L_: {} {}
+ _lane->pushThreadStatus(L_); // L_: {} {} "status"
+ lua_setfield(L_, -2, "status"); // L_: {} {}
+ lua_rawseti(L_, -2, ++_index); // L_: {}
+ _lane = _lane->tracking_next;
+ }
+ }
+ return lua_gettop(L_) - _top; // L_: 0 or 1
+}
+
+#endif // HAVE_LANE_TRACKING()
diff --git a/src/tracker.h b/src/tracker.h
new file mode 100644
index 0000000..087598c
--- /dev/null
+++ b/src/tracker.h
@@ -0,0 +1,35 @@
+#pragma once
+
+#include
+
+// Do we want to activate full lane tracking feature?
+#define HAVE_LANE_TRACKING() 1
+
+#if HAVE_LANE_TRACKING()
+
+class Lane;
+struct lua_State;
+
+// The chain is ended by '(Lane*)(-1)', not nullptr:
+// 'trackingFirst -> ... -> ... -> (-1)'
+#define TRACKING_END ((Lane*) (-1))
+
+class LaneTracker
+{
+ private:
+ mutable std::mutex trackingMutex;
+ Lane* volatile trackingFirst{ nullptr }; // will change to TRACKING_END if we want to activate tracking
+
+ public:
+ void tracking_add(Lane* lane_);
+ [[nodiscard]] bool tracking_remove(Lane* lane_);
+ [[nodiscard]] int pushThreadsTable(lua_State* L_) const;
+ void activate() {
+ trackingFirst = TRACKING_END;
+ }
+ [[nodiscard]] bool isActive() const {
+ return trackingFirst != nullptr;
+ }
+};
+
+#endif // HAVE_LANE_TRACKING()
diff --git a/src/universe.h b/src/universe.h
index 3adba4d..8244980 100644
--- a/src/universe.h
+++ b/src/universe.h
@@ -10,6 +10,7 @@ extern "C"
#endif // __cplusplus
#include "macros_and_utils.h"
+#include "tracker.h"
#include "uniquekey.h"
#include
@@ -22,9 +23,6 @@ struct DeepPrelude;
struct Keepers;
class Lane;
-// Do we want to activate full lane tracking feature?
-#define HAVE_LANE_TRACKING() 1
-
// #################################################################################################
// everything we need to provide to lua_newstate()
@@ -158,8 +156,7 @@ class Universe
DeepPrelude* timerLinda{ nullptr };
#if HAVE_LANE_TRACKING()
- std::mutex trackingMutex;
- Lane* volatile trackingFirst{ nullptr }; // will change to TRACKING_END if we want to activate tracking
+ LaneTracker tracker;
#endif // HAVE_LANE_TRACKING()
// Protects modifying the selfdestruct chain
--
cgit v1.2.3-55-g6feb