Skip to content

Commit bde5f92

Browse files
Merge pull request #14 from NikolasK-source/main
update 1.2.0
2 parents 150198e + d245704 commit bde5f92

8 files changed

+73
-6
lines changed

.gitmodules

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,6 @@
77
[submodule "libs/cxxendian"]
88
path = libs/cxxendian
99
url = https://github.com/NikolasK-source/cxxendian.git
10+
[submodule "libs/cxxsemaphore"]
11+
path = libs/cxxsemaphore
12+
url = https://github.com/NikolasK-source/cxxsemaphore.git

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ cmake_minimum_required(VERSION 3.13.4 FATAL_ERROR)
44
# ======================================================================================================================
55

66
# project
7-
project(stdin-to-modbus-shm LANGUAGES CXX VERSION 1.1.3)
7+
project(stdin-to-modbus-shm LANGUAGES CXX VERSION 1.2.0)
88

99
# settings
1010
set(Target "stdin-to-modbus-shm") # Executable name (without file extension!)

docs/index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ The application is available as [stdin-to-modbus-shm](https://aur.archlinux.org/
139139
See the [Arch Wiki](https://wiki.archlinux.org/title/Arch_User_Repository) for information about how to install AUR packages.
140140

141141

142-
### Using the Modbus Collection Flapak Package: Shared Memory Modbus (recommended)
142+
### Using the Modbus Collection Flatpak Package: Shared Memory Modbus (recommended)
143143
[SHM-Modbus](https://nikolask-source.github.io/SHM_Modbus/) is a collection of the shared memory modbus tools.
144144
It is available as flatpak and published on flathub as ```network.koesling.shm-modbs```.
145145

libs/CMakeLists.txt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66

77
# ---------------------------------------- link libraries --------------------------------------------------------------
88
# ======================================================================================================================
9+
target_link_libraries(${Target} PRIVATE rt)
10+
911
add_subdirectory(cxxopts EXCLUDE_FROM_ALL)
1012
target_link_libraries(${Target} PRIVATE cxxopts)
1113

@@ -17,4 +19,5 @@ target_link_libraries(${Target} PRIVATE cxxendian)
1719

1820
target_link_libraries(${Target} PRIVATE readline)
1921

20-
target_link_libraries(${Target} PRIVATE rt)
22+
add_subdirectory(cxxsemaphore EXCLUDE_FROM_ALL)
23+
target_link_libraries(${Target} PRIVATE cxxsemaphore)

libs/cxxsemaphore

Submodule cxxsemaphore added at 9e7ea69

network.koesling.stdin-to-modbus-shm.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
id: network.koesling.stdin-to-modbus-shm
22
runtime: org.freedesktop.Platform
3-
runtime-version: '21.08'
3+
runtime-version: '23.08'
44
sdk: org.freedesktop.Sdk
55
command: stdin-to-modbus-shm
66
finish-args:

network.koesling.test-stdin-to-modbus-shm.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
id: network.koesling.test-stdin-to-modbus-shm
22
runtime: org.freedesktop.Platform
3-
runtime-version: '21.08'
3+
runtime-version: '23.08'
44
sdk: org.freedesktop.Sdk
55
command: stdin-to-modbus-shm
66
finish-args:

src/main.cpp

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,11 @@
77
#include "license.hpp"
88
#include "readline.hpp"
99

10+
#include "cxxsemaphore.hpp"
1011
#include "cxxshm.hpp"
1112
#include <array>
1213
#include <chrono>
14+
#include <cmath>
1315
#include <csignal>
1416
#include <cxxendian/endian.hpp>
1517
#include <cxxopts.hpp>
@@ -30,6 +32,15 @@ static constexpr double MIN_BASH_SLEEP = 0.1;
3032
//! number of digits that have to be printed for bash sleep instructions
3133
constexpr int SLEEP_DIGITS = 1;
3234

35+
//* value to increment error counter if semaphore could not be acquired
36+
static constexpr long SEMAPHORE_ERROR_INC = 10;
37+
38+
//* value to decrement error counter if semaphore could be acquired
39+
static constexpr long SEMAPHORE_ERROR_DEC = 1;
40+
41+
//* maximum value of semaphore error counter
42+
static constexpr long SEMAPHORE_ERROR_MAX = 100;
43+
3344
constexpr std::array<int, 10> TERM_SIGNALS = {SIGINT,
3445
SIGTERM,
3546
SIGHUP,
@@ -90,6 +101,12 @@ int main(int argc, char **argv) {
90101
options.add_options()("license", "show licenses");
91102
options.add_options()("data-types", "show list of supported data type identifiers");
92103
options.add_options()("constants", "list string constants that can be used as value");
104+
options.add_options()("semaphore",
105+
"protect the shared memory with an existing named semaphore against simultaneous access",
106+
cxxopts::value<std::string>());
107+
options.add_options()("semaphore-timeout",
108+
"maximum time (in seconds) to wait for semaphore (default: 0.1)",
109+
cxxopts::value<double>()->default_value("0.1"));
93110

94111
// parse arguments
95112
cxxopts::ParseResult args;
@@ -133,7 +150,7 @@ int main(int argc, char **argv) {
133150
options.set_width(120);
134151
std::cout << options.help() << std::endl;
135152
std::cout << std::endl;
136-
print_format();
153+
print_format(true);
137154
std::cout << std::endl;
138155
std::cout << "This application uses the following libraries:" << std::endl;
139156
std::cout << " - cxxopts by jarro2783 (https://github.com/jarro2783/cxxopts)" << std::endl;
@@ -371,6 +388,29 @@ int main(int argc, char **argv) {
371388

372389
std::mutex m; // to ensure that the program is not terminated while it writes to a shared memory
373390

391+
std::unique_ptr<cxxsemaphore::Semaphore> semaphore;
392+
long semaphore_error_counter = 0;
393+
if (args.count("semaphore")) {
394+
try {
395+
semaphore = std::make_unique<cxxsemaphore::Semaphore>(args["semaphore"].as<std::string>());
396+
} catch (const std::exception &e) {
397+
std::cerr << e.what() << std::endl;
398+
return EX_SOFTWARE;
399+
}
400+
}
401+
402+
const double SEMAPHORE_TIMEOUT_S = args["semaphore-timeout"].as<double>();
403+
if (SEMAPHORE_TIMEOUT_S < 0.000'001) {
404+
std::cerr << "semaphore-timeout: invalid value" << std::endl;
405+
return EX_USAGE;
406+
}
407+
408+
double modf_dummy {};
409+
const timespec SEMAPHORE_MAX_TIME = {
410+
static_cast<time_t>(args["semaphore-timeout"].as<double>()),
411+
static_cast<suseconds_t>(std::modf(SEMAPHORE_TIMEOUT_S, &modf_dummy) * 1'000'000),
412+
};
413+
374414
std::cout << std::fixed;
375415

376416
auto last_time = std::chrono::steady_clock::now();
@@ -441,6 +481,24 @@ int main(int argc, char **argv) {
441481

442482
// write value to target
443483
std::lock_guard<std::mutex> guard(m);
484+
485+
if (semaphore) {
486+
while (!semaphore->wait(SEMAPHORE_MAX_TIME)) {
487+
std::cerr << " WARNING: Failed to acquire semaphore '" << semaphore->get_name() << "' within "
488+
<< SEMAPHORE_TIMEOUT_S << "s." << std::endl;
489+
490+
semaphore_error_counter += SEMAPHORE_ERROR_INC;
491+
492+
if (semaphore_error_counter >= SEMAPHORE_ERROR_MAX) {
493+
std::cerr << "ERROR: Repeatedly failed to acquire the semaphore" << std::endl;
494+
return EX_SOFTWARE;
495+
}
496+
}
497+
498+
semaphore_error_counter -= SEMAPHORE_ERROR_DEC;
499+
if (semaphore_error_counter < 0) semaphore_error_counter = 0;
500+
}
501+
444502
for (auto &input_data : instructions) {
445503
switch (input_data.register_type) {
446504
case InputParser::Instruction::register_type_t::DO: {
@@ -542,6 +600,8 @@ int main(int argc, char **argv) {
542600
break;
543601
}
544602
}
603+
604+
if (semaphore && semaphore->is_acquired()) semaphore->post();
545605
}
546606

547607
rl_clear_history();

0 commit comments

Comments
 (0)