aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBenoit Germain <benoit.germain@ubisoft.com>2024-05-14 10:05:54 +0200
committerBenoit Germain <benoit.germain@ubisoft.com>2024-05-14 10:05:54 +0200
commit1013970853e6acfd60591a89ae08cc40c64bee06 (patch)
tree7ca081e6adcecebc41e68a659741e0cc0caf77eb /src
parent0567dc0fc6da09467f65ee2f3c10ab68bb76832c (diff)
downloadlanes-1013970853e6acfd60591a89ae08cc40c64bee06.tar.gz
lanes-1013970853e6acfd60591a89ae08cc40c64bee06.tar.bz2
lanes-1013970853e6acfd60591a89ae08cc40c64bee06.zip
Moved Lane tracking implementation in a separate file
Diffstat (limited to 'src')
-rw-r--r--src/Makefile4
-rw-r--r--src/lanes.cpp91
-rw-r--r--src/tools.cpp1
-rw-r--r--src/tracker.cpp108
-rw-r--r--src/tracker.h35
-rw-r--r--src/universe.h7
6 files changed, 156 insertions, 90 deletions
diff --git a/src/Makefile b/src/Makefile
index bbe7b23..fddc45e 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -7,9 +7,9 @@
7 7
8MODULE=lanes 8MODULE=lanes
9 9
10SRC=lanes.c cancel.cpp compat.cpp threading.cpp tools.cpp state.cpp linda.cpp lindafactory.cpp deep.cpp keeper.cpp universe.cpp intercopycontext.cpp 10SRC=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
11 11
12OBJ=$(SRC:.c=.o) 12OBJ=$(SRC:.cpp=.o)
13 13
14# LuaRocks gives 'LIBFLAG' from the outside 14# LuaRocks gives 'LIBFLAG' from the outside
15# 15#
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.
104 104
105// ################################################################################################# 105// #################################################################################################
106 106
107#if HAVE_LANE_TRACKING()
108
109// The chain is ended by '(Lane*)(-1)', not nullptr:
110// 'trackingFirst -> ... -> ... -> (-1)'
111#define TRACKING_END ((Lane*) (-1))
112
113/*
114 * Add the lane to tracking chain; the ones still running at the end of the
115 * whole process will be cancelled.
116 */
117static void tracking_add(Lane* lane_)
118{
119 std::lock_guard<std::mutex> _guard{ lane_->U->trackingMutex };
120 assert(lane_->tracking_next == nullptr);
121
122 lane_->tracking_next = lane_->U->trackingFirst;
123 lane_->U->trackingFirst = lane_;
124}
125
126// #################################################################################################
127
128/*
129 * A free-running lane has ended; remove it from tracking chain
130 */
131[[nodiscard]] static bool tracking_remove(Lane* lane_)
132{
133 bool _found{ false };
134 std::lock_guard<std::mutex> _guard{ lane_->U->trackingMutex };
135 // Make sure (within the MUTEX) that we actually are in the chain
136 // still (at process exit they will remove us from chain and then
137 // cancel/kill).
138 //
139 if (lane_->tracking_next != nullptr) {
140 Lane** _ref = (Lane**) &lane_->U->trackingFirst;
141
142 while (*_ref != TRACKING_END) {
143 if (*_ref == lane_) {
144 *_ref = lane_->tracking_next;
145 lane_->tracking_next = nullptr;
146 _found = true;
147 break;
148 }
149 _ref = (Lane**) &((*_ref)->tracking_next);
150 }
151 assert(_found);
152 }
153 return _found;
154}
155
156#endif // HAVE_LANE_TRACKING()
157
158// #################################################################################################
159
160Lane::Lane(Universe* U_, lua_State* L_) 107Lane::Lane(Universe* U_, lua_State* L_)
161: U{ U_ } 108: U{ U_ }
162, L{ L_ } 109, L{ L_ }
163{ 110{
164#if HAVE_LANE_TRACKING() 111#if HAVE_LANE_TRACKING()
165 if (U->trackingFirst) { 112 U->tracker.tracking_add(this);
166 tracking_add(this);
167 }
168#endif // HAVE_LANE_TRACKING() 113#endif // HAVE_LANE_TRACKING()
169} 114}
170 115
@@ -241,10 +186,7 @@ Lane::~Lane()
241 // Clean up after a (finished) thread 186 // Clean up after a (finished) thread
242 // 187 //
243#if HAVE_LANE_TRACKING() 188#if HAVE_LANE_TRACKING()
244 if (U->trackingFirst != nullptr) { 189 std::ignore = U->tracker.tracking_remove(this);
245 // Lane was cleaned up, no need to handle at process termination
246 std::ignore = tracking_remove(this);
247 }
248#endif // HAVE_LANE_TRACKING() 190#endif // HAVE_LANE_TRACKING()
249} 191}
250 192
@@ -1428,27 +1370,8 @@ LUAG_FUNC(thread_index)
1428// Return a list of all known lanes 1370// Return a list of all known lanes
1429LUAG_FUNC(threads) 1371LUAG_FUNC(threads)
1430{ 1372{
1431 int const _top{ lua_gettop(L_) }; 1373 LaneTracker const& _tracker = universe_get(L_)->tracker;
1432 Universe* const _U{ universe_get(L_) }; 1374 return _tracker.pushThreadsTable(L_);
1433
1434 // List _all_ still running threads
1435 std::lock_guard<std::mutex> _guard{ _U->trackingMutex };
1436 if (_U->trackingFirst && _U->trackingFirst != TRACKING_END) {
1437 Lane* _lane{ _U->trackingFirst };
1438 int _index{ 0 };
1439 lua_newtable(L_); // L_: {}
1440 while (_lane != TRACKING_END) {
1441 // insert a { name='<name>', status='<status>' } tuple, so that several lanes with the same name can't clobber each other
1442 lua_createtable(L_, 0, 2); // L_: {} {}
1443 lua_pushstring(L_, _lane->debugName); // L_: {} {} "name"
1444 lua_setfield(L_, -2, "name"); // L_: {} {}
1445 _lane->pushThreadStatus(L_); // L_: {} {} "status"
1446 lua_setfield(L_, -2, "status"); // L_: {} {}
1447 lua_rawseti(L_, -2, ++_index); // L_: {}
1448 _lane = _lane->tracking_next;
1449 }
1450 }
1451 return lua_gettop(L_) - _top; // L_: 0 or 1
1452} 1375}
1453#endif // HAVE_LANE_TRACKING() 1376#endif // HAVE_LANE_TRACKING()
1454 1377
@@ -1668,7 +1591,9 @@ LUAG_FUNC(configure)
1668 lua_pop(L_, 1); // L_: settings 1591 lua_pop(L_, 1); // L_: settings
1669#if HAVE_LANE_TRACKING() 1592#if HAVE_LANE_TRACKING()
1670 lua_getfield(L_, 1, "track_lanes"); // L_: settings track_lanes 1593 lua_getfield(L_, 1, "track_lanes"); // L_: settings track_lanes
1671 _U->trackingFirst = lua_toboolean(L_, -1) ? TRACKING_END : nullptr; 1594 if (lua_toboolean(L_, -1)) {
1595 _U->tracker.activate();
1596 }
1672 lua_pop(L_, 1); // L_: settings 1597 lua_pop(L_, 1); // L_: settings
1673#endif // HAVE_LANE_TRACKING() 1598#endif // HAVE_LANE_TRACKING()
1674 // Linked chains handling 1599 // Linked chains handling
@@ -1704,7 +1629,7 @@ LUAG_FUNC(configure)
1704 luaG_registerlibfuncs(L_, global::sLanesFunctions); 1629 luaG_registerlibfuncs(L_, global::sLanesFunctions);
1705#if HAVE_LANE_TRACKING() 1630#if HAVE_LANE_TRACKING()
1706 // register core.threads() only if settings say it should be available 1631 // register core.threads() only if settings say it should be available
1707 if (_U->trackingFirst != nullptr) { 1632 if (_U->tracker.isActive()) {
1708 lua_pushcfunction(L_, LG_threads); // L_: settings M LG_threads() 1633 lua_pushcfunction(L_, LG_threads); // L_: settings M LG_threads()
1709 lua_setfield(L_, -2, "threads"); // L_: settings M 1634 lua_setfield(L_, -2, "threads"); // L_: settings M
1710 } 1635 }
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_)
523 lua_replace(L_, -3); // L_: "type" "result" 523 lua_replace(L_, -3); // L_: "type" "result"
524 return 2; 524 return 2;
525} 525}
526 \ 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 @@
1/*
2===============================================================================
3
4Copyright (C) 2024 Benoit Germain <bnt.germain@gmail.com>
5
6Permission is hereby granted, free of charge, to any person obtaining a copy
7of this software and associated documentation files (the "Software"), to deal
8in the Software without restriction, including without limitation the rights
9to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10copies of the Software, and to permit persons to whom the Software is
11furnished to do so, subject to the following conditions:
12
13The above copyright notice and this permission notice shall be included in
14all copies or substantial portions of the Software.
15
16THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22THE SOFTWARE.
23
24===============================================================================
25*/
26#include "tracker.h"
27#include "lanes_private.h"
28
29// #################################################################################################
30
31#if HAVE_LANE_TRACKING()
32
33/*
34 * Add the lane to tracking chain; the ones still running at the end of the
35 * whole process will be cancelled.
36 */
37void LaneTracker::tracking_add(Lane* lane_)
38{
39 if (!isActive()) {
40 return;
41 }
42 std::lock_guard<std::mutex> _guard{ trackingMutex };
43 assert(lane_->tracking_next == nullptr);
44
45 lane_->tracking_next = trackingFirst;
46 trackingFirst = lane_;
47}
48
49// #################################################################################################
50
51/*
52 * A free-running lane has ended; remove it from tracking chain
53 */
54[[nodiscard]] bool LaneTracker::tracking_remove(Lane* lane_)
55{
56 if (!isActive()) {
57 return false;
58 }
59
60 bool _found{ false };
61 std::lock_guard<std::mutex> _guard{ trackingMutex };
62 // Make sure (within the MUTEX) that we actually are in the chain
63 // still (at process exit they will remove us from chain and then
64 // cancel/kill).
65 //
66 if (lane_->tracking_next != nullptr) {
67 Lane** _ref = (Lane**) &trackingFirst;
68
69 while (*_ref != TRACKING_END) {
70 if (*_ref == lane_) {
71 *_ref = lane_->tracking_next;
72 lane_->tracking_next = nullptr;
73 _found = true;
74 break;
75 }
76 _ref = (Lane**) &((*_ref)->tracking_next);
77 }
78 assert(_found);
79 }
80 return _found;
81}
82
83// ################################################################################################
84
85[[nodiscard]] int LaneTracker::pushThreadsTable(lua_State* L_) const
86{
87 int const _top{ lua_gettop(L_) };
88 // List _all_ still running threads
89 std::lock_guard<std::mutex> _guard{ trackingMutex };
90 if (trackingFirst && trackingFirst != TRACKING_END) {
91 Lane* _lane{ trackingFirst };
92 int _index{ 0 };
93 lua_newtable(L_); // L_: {}
94 while (_lane != TRACKING_END) {
95 // insert a { name='<name>', status='<status>' } tuple, so that several lanes with the same name can't clobber each other
96 lua_createtable(L_, 0, 2); // L_: {} {}
97 lua_pushstring(L_, _lane->debugName); // L_: {} {} "name"
98 lua_setfield(L_, -2, "name"); // L_: {} {}
99 _lane->pushThreadStatus(L_); // L_: {} {} "status"
100 lua_setfield(L_, -2, "status"); // L_: {} {}
101 lua_rawseti(L_, -2, ++_index); // L_: {}
102 _lane = _lane->tracking_next;
103 }
104 }
105 return lua_gettop(L_) - _top; // L_: 0 or 1
106}
107
108#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 @@
1#pragma once
2
3#include <mutex>
4
5// Do we want to activate full lane tracking feature?
6#define HAVE_LANE_TRACKING() 1
7
8#if HAVE_LANE_TRACKING()
9
10class Lane;
11struct lua_State;
12
13// The chain is ended by '(Lane*)(-1)', not nullptr:
14// 'trackingFirst -> ... -> ... -> (-1)'
15#define TRACKING_END ((Lane*) (-1))
16
17class LaneTracker
18{
19 private:
20 mutable std::mutex trackingMutex;
21 Lane* volatile trackingFirst{ nullptr }; // will change to TRACKING_END if we want to activate tracking
22
23 public:
24 void tracking_add(Lane* lane_);
25 [[nodiscard]] bool tracking_remove(Lane* lane_);
26 [[nodiscard]] int pushThreadsTable(lua_State* L_) const;
27 void activate() {
28 trackingFirst = TRACKING_END;
29 }
30 [[nodiscard]] bool isActive() const {
31 return trackingFirst != nullptr;
32 }
33};
34
35#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"
10#endif // __cplusplus 10#endif // __cplusplus
11 11
12#include "macros_and_utils.h" 12#include "macros_and_utils.h"
13#include "tracker.h"
13#include "uniquekey.h" 14#include "uniquekey.h"
14 15
15#include <mutex> 16#include <mutex>
@@ -22,9 +23,6 @@ struct DeepPrelude;
22struct Keepers; 23struct Keepers;
23class Lane; 24class Lane;
24 25
25// Do we want to activate full lane tracking feature?
26#define HAVE_LANE_TRACKING() 1
27
28// ################################################################################################# 26// #################################################################################################
29 27
30// everything we need to provide to lua_newstate() 28// everything we need to provide to lua_newstate()
@@ -158,8 +156,7 @@ class Universe
158 DeepPrelude* timerLinda{ nullptr }; 156 DeepPrelude* timerLinda{ nullptr };
159 157
160#if HAVE_LANE_TRACKING() 158#if HAVE_LANE_TRACKING()
161 std::mutex trackingMutex; 159 LaneTracker tracker;
162 Lane* volatile trackingFirst{ nullptr }; // will change to TRACKING_END if we want to activate tracking
163#endif // HAVE_LANE_TRACKING() 160#endif // HAVE_LANE_TRACKING()
164 161
165 // Protects modifying the selfdestruct chain 162 // Protects modifying the selfdestruct chain