replace manual lock/unlock with lock_guard to ensure a lock is held in a scope, and released when a scope is closed;

pull/51/head
Bryan Biedenkapp 2 years ago
parent b7c6282767
commit 5571a71e4e

@ -7,7 +7,7 @@
* @package DVM / Common Library * @package DVM / Common Library
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) * @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
* *
* Copyright (C) 2018-2022 Bryan Biedenkapp, N2PLL * Copyright (C) 2018-2022,2024 Bryan Biedenkapp, N2PLL
* Copyright (c) 2024 Patrick McDonnell, W3AXL * Copyright (c) 2024 Patrick McDonnell, W3AXL
* *
*/ */
@ -21,6 +21,12 @@ using namespace lookups;
#include <vector> #include <vector>
#include <fstream> #include <fstream>
// ---------------------------------------------------------------------------
// Static Class Members
// ---------------------------------------------------------------------------
std::mutex IdenTableLookup::m_mutex;
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// Public Class Members // Public Class Members
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@ -35,6 +41,15 @@ IdenTableLookup::IdenTableLookup(const std::string& filename, uint32_t reloadTim
/* stub */ /* stub */
} }
/// <summary>
/// Clears all entries from the lookup table.
/// </summary>
void IdenTableLookup::clear()
{
std::lock_guard<std::mutex> lock(m_mutex);
m_table.clear();
}
/// <summary> /// <summary>
/// Finds a table entry in this lookup table. /// Finds a table entry in this lookup table.
/// </summary> /// </summary>
@ -44,15 +59,12 @@ IdenTable IdenTableLookup::find(uint32_t id)
{ {
IdenTable entry; IdenTable entry;
m_mutex.lock(); std::lock_guard<std::mutex> lock(m_mutex);
{ try {
try { entry = m_table.at(id);
entry = m_table.at(id); } catch (...) {
} catch (...) { /* stub */
/* stub */
}
} }
m_mutex.unlock();
float chBandwidthKhz = entry.chBandwidthKhz(); float chBandwidthKhz = entry.chBandwidthKhz();
if (chBandwidthKhz == 0.0F) if (chBandwidthKhz == 0.0F)
@ -105,57 +117,55 @@ bool IdenTableLookup::load()
// clear table // clear table
clear(); clear();
m_mutex.lock(); std::lock_guard<std::mutex> lock(m_mutex);
{
// read lines from file // read lines from file
std::string line; std::string line;
while (std::getline(file, line)) { while (std::getline(file, line)) {
if (line.length() > 0) { if (line.length() > 0) {
if (line.at(0) == '#') if (line.at(0) == '#')
continue; continue;
// tokenize line // tokenize line
std::string next; std::string next;
std::vector<std::string> parsed; std::vector<std::string> parsed;
char delim = ','; char delim = ',';
for (auto it = line.begin(); it != line.end(); it++) { for (auto it = line.begin(); it != line.end(); it++) {
if (*it == delim) { if (*it == delim) {
if (!next.empty()) { if (!next.empty()) {
parsed.push_back(next); parsed.push_back(next);
next.clear(); next.clear();
}
} }
else
next += *it;
} }
if (!next.empty()) else
parsed.push_back(next); next += *it;
}
if (!next.empty())
parsed.push_back(next);
// parse tokenized line // parse tokenized line
uint8_t channelId = (uint8_t)::atoi(parsed[0].c_str()); uint8_t channelId = (uint8_t)::atoi(parsed[0].c_str());
uint32_t baseFrequency = (uint32_t)::atoi(parsed[1].c_str()); uint32_t baseFrequency = (uint32_t)::atoi(parsed[1].c_str());
float chSpaceKhz = float(::atof(parsed[2].c_str())); float chSpaceKhz = float(::atof(parsed[2].c_str()));
float txOffsetMhz = float(::atof(parsed[3].c_str())); float txOffsetMhz = float(::atof(parsed[3].c_str()));
float chBandwidthKhz = float(::atof(parsed[4].c_str())); float chBandwidthKhz = float(::atof(parsed[4].c_str()));
if (chSpaceKhz == 0.0F) if (chSpaceKhz == 0.0F)
chSpaceKhz = chBandwidthKhz / 2; chSpaceKhz = chBandwidthKhz / 2;
if (chSpaceKhz < 0.125F) // clamp to 125 Hz if (chSpaceKhz < 0.125F) // clamp to 125 Hz
chSpaceKhz = 0.125F; chSpaceKhz = 0.125F;
if (chSpaceKhz > 125000.0F) // clamp to 125 kHz if (chSpaceKhz > 125000.0F) // clamp to 125 kHz
chSpaceKhz = 125000.0F; chSpaceKhz = 125000.0F;
IdenTable entry = IdenTable(channelId, baseFrequency, chSpaceKhz, txOffsetMhz, chBandwidthKhz); IdenTable entry = IdenTable(channelId, baseFrequency, chSpaceKhz, txOffsetMhz, chBandwidthKhz);
LogMessage(LOG_HOST, "Channel Id %u: BaseFrequency = %uHz, TXOffsetMhz = %fMHz, BandwidthKhz = %fKHz, SpaceKhz = %fKHz", LogMessage(LOG_HOST, "Channel Id %u: BaseFrequency = %uHz, TXOffsetMhz = %fMHz, BandwidthKhz = %fKHz, SpaceKhz = %fKHz",
entry.channelId(), entry.baseFrequency(), entry.txOffsetMhz(), entry.chBandwidthKhz(), entry.chSpaceKhz()); entry.channelId(), entry.baseFrequency(), entry.txOffsetMhz(), entry.chBandwidthKhz(), entry.chSpaceKhz());
m_table[channelId] = entry; m_table[channelId] = entry;
}
} }
} }
m_mutex.unlock();
file.close(); file.close();
@ -174,6 +184,5 @@ bool IdenTableLookup::load()
/// <returns>True, if lookup table was saved, otherwise false.</returns> /// <returns>True, if lookup table was saved, otherwise false.</returns>
bool IdenTableLookup::save() bool IdenTableLookup::save()
{ {
/// TODO TODO TODO actually save stuff
return false; return false;
} }

@ -7,7 +7,7 @@
* @package DVM / Common Library * @package DVM / Common Library
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) * @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
* *
* Copyright (C) 2018-2022 Bryan Biedenkapp, N2PLL * Copyright (C) 2018-2022,2024 Bryan Biedenkapp, N2PLL
* Copyright (c) 2024 Patrick McDonnell, W3AXL * Copyright (c) 2024 Patrick McDonnell, W3AXL
* *
*/ */
@ -96,6 +96,9 @@ namespace lookups
/// <summary>Initializes a new instance of the IdenTableLookup class.</summary> /// <summary>Initializes a new instance of the IdenTableLookup class.</summary>
IdenTableLookup(const std::string& filename, uint32_t reloadTime); IdenTableLookup(const std::string& filename, uint32_t reloadTime);
/// <summary>Clears all entries from the lookup table.</summary>
void clear() override;
/// <summary>Finds a table entry in this lookup table.</summary> /// <summary>Finds a table entry in this lookup table.</summary>
IdenTable find(uint32_t id) override; IdenTable find(uint32_t id) override;
/// <summary>Returns the list of entries in this lookup table.</summary> /// <summary>Returns the list of entries in this lookup table.</summary>
@ -109,6 +112,9 @@ namespace lookups
/// <summary>Saves the table to the passed lookup table file.</summary> /// <summary>Saves the table to the passed lookup table file.</summary>
/// <returns>True, if lookup table was saved, otherwise false.</returns> /// <returns>True, if lookup table was saved, otherwise false.</returns>
bool save() override; bool save() override;
private:
static std::mutex m_mutex;
}; };
} // namespace lookups } // namespace lookups

@ -7,7 +7,7 @@
* @package DVM / Common Library * @package DVM / Common Library
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) * @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
* *
* Copyright (C) 2018-2022 Bryan Biedenkapp, N2PLL * Copyright (C) 2018-2022,2024 Bryan Biedenkapp, N2PLL
* Copyright (c) 2024 Patrick McDonnell, W3AXL * Copyright (c) 2024 Patrick McDonnell, W3AXL
* *
*/ */
@ -98,11 +98,9 @@ namespace lookups
/// <summary>Clears all entries from the lookup table.</summary> /// <summary>Clears all entries from the lookup table.</summary>
virtual void clear() virtual void clear()
{ {
m_mutex.lock(); // bryanb: this is not thread-safe and thread saftey should be implemented
{ // on the derived class
m_table.clear(); m_table.clear();
}
m_mutex.unlock();
} }
/// <summary>Helper to check if this lookup table has the specified unique ID.</summary> /// <summary>Helper to check if this lookup table has the specified unique ID.</summary>
@ -110,19 +108,13 @@ namespace lookups
/// <returns>True, if the lookup table has an entry by the specified unique ID, otherwise false.</returns> /// <returns>True, if the lookup table has an entry by the specified unique ID, otherwise false.</returns>
virtual bool hasEntry(uint32_t id) virtual bool hasEntry(uint32_t id)
{ {
m_mutex.lock(); try {
{ m_table.at(id);
try { return true;
m_table.at(id); }
m_mutex.unlock(); catch (...) {
return true; return false;
}
catch (...) {
m_mutex.unlock();
return false;
}
} }
m_mutex.unlock();
return false; return false;
} }
@ -140,7 +132,6 @@ namespace lookups
std::string m_filename; std::string m_filename;
uint32_t m_reloadTime; uint32_t m_reloadTime;
std::unordered_map<uint32_t, T> m_table; std::unordered_map<uint32_t, T> m_table;
std::mutex m_mutex;
bool m_stop; bool m_stop;
/// <summary>Loads the table from the passed lookup table file.</summary> /// <summary>Loads the table from the passed lookup table file.</summary>

@ -24,6 +24,12 @@ using namespace lookups;
#include <vector> #include <vector>
#include <fstream> #include <fstream>
// ---------------------------------------------------------------------------
// Static Class Members
// ---------------------------------------------------------------------------
std::mutex RadioIdLookup::m_mutex;
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// Public Class Members // Public Class Members
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@ -40,6 +46,15 @@ RadioIdLookup::RadioIdLookup(const std::string& filename, uint32_t reloadTime, b
/* stub */ /* stub */
} }
/// <summary>
/// Clears all entries from the lookup table.
/// </summary>
void RadioIdLookup::clear()
{
std::lock_guard<std::mutex> lock(m_mutex);
m_table.clear();
}
/// <summary> /// <summary>
/// Toggles the specified radio ID enabled or disabled. /// Toggles the specified radio ID enabled or disabled.
/// </summary> /// </summary>
@ -65,21 +80,18 @@ void RadioIdLookup::addEntry(uint32_t id, bool enabled, const std::string& alias
RadioId entry = RadioId(enabled, false, alias); RadioId entry = RadioId(enabled, false, alias);
m_mutex.lock(); std::lock_guard<std::mutex> lock(m_mutex);
{ try {
try { RadioId _entry = m_table.at(id);
RadioId _entry = m_table.at(id);
// if the enabled value doesn't match -- override with the intended // if the enabled value doesn't match -- override with the intended
if (_entry.radioEnabled() != enabled) { if (_entry.radioEnabled() != enabled) {
_entry = RadioId(enabled, false, alias); _entry = RadioId(enabled, false, alias);
m_table[id] = _entry; m_table[id] = _entry;
}
} catch (...) {
m_table[id] = entry;
} }
} catch (...) {
m_table[id] = entry;
} }
m_mutex.unlock();
} }
/// <summary> /// <summary>
@ -88,16 +100,13 @@ void RadioIdLookup::addEntry(uint32_t id, bool enabled, const std::string& alias
/// <param name="id">Unique ID to erase.</param> /// <param name="id">Unique ID to erase.</param>
void RadioIdLookup::eraseEntry(uint32_t id) void RadioIdLookup::eraseEntry(uint32_t id)
{ {
m_mutex.lock(); std::lock_guard<std::mutex> lock(m_mutex);
{ try {
try { m_table.at(id);
m_table.at(id); m_table.erase(id);
m_table.erase(id); } catch (...) {
} catch (...) { /* stub */
/* stub */
}
} }
m_mutex.unlock();
} }
/// <summary> /// <summary>
@ -113,15 +122,12 @@ RadioId RadioIdLookup::find(uint32_t id)
return RadioId(true, false); return RadioId(true, false);
} }
m_mutex.lock(); std::lock_guard<std::mutex> lock(m_mutex);
{ try {
try { entry = m_table.at(id);
entry = m_table.at(id); } catch (...) {
} catch (...) { entry = RadioId(false, true);
entry = RadioId(false, true);
}
} }
m_mutex.unlock();
return entry; return entry;
} }
@ -166,51 +172,49 @@ bool RadioIdLookup::load()
// clear table // clear table
clear(); clear();
m_mutex.lock(); std::lock_guard<std::mutex> lock(m_mutex);
{
// read lines from file // read lines from file
std::string line; std::string line;
while (std::getline(file, line)) { while (std::getline(file, line)) {
if (line.length() > 0) { if (line.length() > 0) {
// Skip comments with # // Skip comments with #
if (line.at(0) == '#') if (line.at(0) == '#')
continue; continue;
// tokenize line // tokenize line
std::string next; std::string next;
std::vector<std::string> parsed; std::vector<std::string> parsed;
char delim = ','; char delim = ',';
for (char c : line) { for (char c : line) {
if (c == delim) { if (c == delim) {
if (!next.empty()) { if (!next.empty()) {
parsed.push_back(next); parsed.push_back(next);
next.clear(); next.clear();
}
} }
else
next += c;
}
if (!next.empty())
parsed.push_back(next);
// parse tokenized line
uint32_t id = ::atoi(parsed[0].c_str());
bool radioEnabled = ::atoi(parsed[1].c_str()) == 1;
bool radioDefault = false;
// Check for an optional alias field
if (parsed.size() >= 3) {
m_table[id] = RadioId(radioEnabled, radioDefault, parsed[2]);
LogDebug(LOG_HOST, "Loaded RID %u (%s) into RID lookup table", id, parsed[2].c_str());
} else {
m_table[id] = RadioId(radioEnabled, radioDefault);
LogDebug(LOG_HOST, "Loaded RID %u into RID lookup table", id);
} }
else
next += c;
}
if (!next.empty())
parsed.push_back(next);
// parse tokenized line
uint32_t id = ::atoi(parsed[0].c_str());
bool radioEnabled = ::atoi(parsed[1].c_str()) == 1;
bool radioDefault = false;
// Check for an optional alias field
if (parsed.size() >= 3) {
m_table[id] = RadioId(radioEnabled, radioDefault, parsed[2]);
LogDebug(LOG_HOST, "Loaded RID %u (%s) into RID lookup table", id, parsed[2].c_str());
} else {
m_table[id] = RadioId(radioEnabled, radioDefault);
LogDebug(LOG_HOST, "Loaded RID %u into RID lookup table", id);
} }
} }
} }
m_mutex.unlock();
file.close(); file.close();
@ -244,32 +248,30 @@ bool RadioIdLookup::save()
// Counter for lines written // Counter for lines written
unsigned int lines = 0; unsigned int lines = 0;
m_mutex.lock(); std::lock_guard<std::mutex> lock(m_mutex);
{
// String for writing // String for writing
std::string line; std::string line;
// iterate over each entry in the RID lookup and write it to the open file // iterate over each entry in the RID lookup and write it to the open file
for (auto& entry: m_table) { for (auto& entry: m_table) {
// Get the parameters // Get the parameters
uint32_t rid = entry.first; uint32_t rid = entry.first;
bool enabled = entry.second.radioEnabled(); bool enabled = entry.second.radioEnabled();
std::string alias = entry.second.radioAlias(); std::string alias = entry.second.radioAlias();
// Format into a string // Format into a string
line = std::to_string(rid) + "," + std::to_string(enabled) + ","; line = std::to_string(rid) + "," + std::to_string(enabled) + ",";
// Add the alias if we have one // Add the alias if we have one
if (alias.length() > 0) { if (alias.length() > 0) {
line += alias; line += alias;
line += ","; line += ",";
}
// Add the newline
line += "\n";
// Write to file
file << line;
// Increment
lines++;
} }
// Add the newline
line += "\n";
// Write to file
file << line;
// Increment
lines++;
} }
m_mutex.unlock();
file.close(); file.close();

@ -9,7 +9,7 @@
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) * @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
* *
* Copyright (C) 2016 Jonathan Naylor, G4KLX * Copyright (C) 2016 Jonathan Naylor, G4KLX
* Copyright (C) 2017-2022 Bryan Biedenkapp, N2PLL * Copyright (C) 2017-2022,2024 Bryan Biedenkapp, N2PLL
* Copyright (c) 2024 Patrick McDonnell, W3AXL * Copyright (c) 2024 Patrick McDonnell, W3AXL
* *
*/ */
@ -114,6 +114,9 @@ namespace lookups
/// <summary>Initializes a new instance of the RadioIdLookup class.</summary> /// <summary>Initializes a new instance of the RadioIdLookup class.</summary>
RadioIdLookup(const std::string& filename, uint32_t reloadTime, bool ridAcl); RadioIdLookup(const std::string& filename, uint32_t reloadTime, bool ridAcl);
/// <summary>Clears all entries from the lookup table.</summary>
void clear() override;
/// <summary>Toggles the specified radio ID enabled or disabled.</summary> /// <summary>Toggles the specified radio ID enabled or disabled.</summary>
void toggleEntry(uint32_t id, bool enabled); void toggleEntry(uint32_t id, bool enabled);
@ -141,6 +144,9 @@ namespace lookups
/// <summary>Saves the table to the passed lookup table file.</summary> /// <summary>Saves the table to the passed lookup table file.</summary>
/// <returns>True, if lookup table was saved, otherwise false.</returns> /// <returns>True, if lookup table was saved, otherwise false.</returns>
bool save() override; bool save() override;
private:
static std::mutex m_mutex;
}; };
} // namespace lookups } // namespace lookups

@ -21,6 +21,12 @@ using namespace lookups;
#include <string> #include <string>
#include <vector> #include <vector>
// ---------------------------------------------------------------------------
// Static Class Members
// ---------------------------------------------------------------------------
std::mutex TalkgroupRulesLookup::m_mutex;
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// Public Class Members // Public Class Members
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@ -105,11 +111,8 @@ bool TalkgroupRulesLookup::read()
/// </summary> /// </summary>
void TalkgroupRulesLookup::clear() void TalkgroupRulesLookup::clear()
{ {
m_mutex.lock(); std::lock_guard<std::mutex> lock(m_mutex);
{ m_groupVoice.clear();
m_groupVoice.clear();
}
m_mutex.unlock();
} }
/// <summary> /// <summary>
@ -126,40 +129,37 @@ void TalkgroupRulesLookup::addEntry(uint32_t id, uint8_t slot, bool enabled)
source.tgSlot(slot); source.tgSlot(slot);
config.active(enabled); config.active(enabled);
m_mutex.lock(); std::lock_guard<std::mutex> lock(m_mutex);
{ auto it = std::find_if(m_groupVoice.begin(), m_groupVoice.end(),
auto it = std::find_if(m_groupVoice.begin(), m_groupVoice.end(), [&](TalkgroupRuleGroupVoice x)
[&](TalkgroupRuleGroupVoice x) {
{ if (slot != 0U) {
if (slot != 0U) { return x.source().tgId() == id && x.source().tgSlot() == slot;
return x.source().tgId() == id && x.source().tgSlot() == slot; }
}
return x.source().tgId() == id;
});
if (it != m_groupVoice.end()) {
source = it->source();
source.tgId(id);
source.tgSlot(slot);
config = it->config();
config.active(enabled);
TalkgroupRuleGroupVoice entry = *it;
entry.config(config);
entry.source(source);
m_groupVoice[it - m_groupVoice.begin()] = entry;
}
else {
TalkgroupRuleGroupVoice entry;
entry.config(config);
entry.source(source);
m_groupVoice.push_back(entry); return x.source().tgId() == id;
} });
if (it != m_groupVoice.end()) {
source = it->source();
source.tgId(id);
source.tgSlot(slot);
config = it->config();
config.active(enabled);
TalkgroupRuleGroupVoice entry = *it;
entry.config(config);
entry.source(source);
m_groupVoice[it - m_groupVoice.begin()] = entry;
}
else {
TalkgroupRuleGroupVoice entry;
entry.config(config);
entry.source(source);
m_groupVoice.push_back(entry);
} }
m_mutex.unlock();
} }
/// <summary> /// <summary>
@ -175,25 +175,22 @@ void TalkgroupRulesLookup::addEntry(TalkgroupRuleGroupVoice groupVoice)
uint32_t id = entry.source().tgId(); uint32_t id = entry.source().tgId();
uint8_t slot = entry.source().tgSlot(); uint8_t slot = entry.source().tgSlot();
m_mutex.lock(); std::lock_guard<std::mutex> lock(m_mutex);
{ auto it = std::find_if(m_groupVoice.begin(), m_groupVoice.end(),
auto it = std::find_if(m_groupVoice.begin(), m_groupVoice.end(), [&](TalkgroupRuleGroupVoice x)
[&](TalkgroupRuleGroupVoice x) {
{ if (slot != 0U) {
if (slot != 0U) { return x.source().tgId() == id && x.source().tgSlot() == slot;
return x.source().tgId() == id && x.source().tgSlot() == slot; }
}
return x.source().tgId() == id;
return x.source().tgId() == id; });
}); if (it != m_groupVoice.end()) {
if (it != m_groupVoice.end()) { m_groupVoice[it - m_groupVoice.begin()] = entry;
m_groupVoice[it - m_groupVoice.begin()] = entry; }
} else {
else { m_groupVoice.push_back(entry);
m_groupVoice.push_back(entry);
}
} }
m_mutex.unlock();
} }
/// <summary> /// <summary>
@ -203,14 +200,11 @@ void TalkgroupRulesLookup::addEntry(TalkgroupRuleGroupVoice groupVoice)
/// <param name="slot">DMR slot this talkgroup is valid on.</param> /// <param name="slot">DMR slot this talkgroup is valid on.</param>
void TalkgroupRulesLookup::eraseEntry(uint32_t id, uint8_t slot) void TalkgroupRulesLookup::eraseEntry(uint32_t id, uint8_t slot)
{ {
m_mutex.lock(); std::lock_guard<std::mutex> lock(m_mutex);
{ auto it = std::find_if(m_groupVoice.begin(), m_groupVoice.end(), [&](TalkgroupRuleGroupVoice x) { return x.source().tgId() == id && x.source().tgSlot() == slot; });
auto it = std::find_if(m_groupVoice.begin(), m_groupVoice.end(), [&](TalkgroupRuleGroupVoice x) { return x.source().tgId() == id && x.source().tgSlot() == slot; }); if (it != m_groupVoice.end()) {
if (it != m_groupVoice.end()) { m_groupVoice.erase(it);
m_groupVoice.erase(it);
}
} }
m_mutex.unlock();
} }
/// <summary> /// <summary>
@ -223,24 +217,21 @@ TalkgroupRuleGroupVoice TalkgroupRulesLookup::find(uint32_t id, uint8_t slot)
{ {
TalkgroupRuleGroupVoice entry; TalkgroupRuleGroupVoice entry;
m_mutex.lock(); std::lock_guard<std::mutex> lock(m_mutex);
{ auto it = std::find_if(m_groupVoice.begin(), m_groupVoice.end(),
auto it = std::find_if(m_groupVoice.begin(), m_groupVoice.end(), [&](TalkgroupRuleGroupVoice x)
[&](TalkgroupRuleGroupVoice x) {
{ if (slot != 0U) {
if (slot != 0U) { return x.source().tgId() == id && x.source().tgSlot() == slot;
return x.source().tgId() == id && x.source().tgSlot() == slot; }
}
return x.source().tgId() == id;
return x.source().tgId() == id; });
}); if (it != m_groupVoice.end()) {
if (it != m_groupVoice.end()) { entry = *it;
entry = *it; } else {
} else { entry = TalkgroupRuleGroupVoice();
entry = TalkgroupRuleGroupVoice();
}
} }
m_mutex.unlock();
return entry; return entry;
} }
@ -256,36 +247,33 @@ TalkgroupRuleGroupVoice TalkgroupRulesLookup::findByRewrite(uint32_t peerId, uin
{ {
TalkgroupRuleGroupVoice entry; TalkgroupRuleGroupVoice entry;
m_mutex.lock(); std::lock_guard<std::mutex> lock(m_mutex);
{ auto it = std::find_if(m_groupVoice.begin(), m_groupVoice.end(),
auto it = std::find_if(m_groupVoice.begin(), m_groupVoice.end(), [&](TalkgroupRuleGroupVoice x)
[&](TalkgroupRuleGroupVoice x) {
{ if (x.config().rewrite().size() == 0)
if (x.config().rewrite().size() == 0)
return false;
std::vector<TalkgroupRuleRewrite> rewrite = x.config().rewrite();
auto innerIt = std::find_if(rewrite.begin(), rewrite.end(),
[&](TalkgroupRuleRewrite y)
{
if (slot != 0U) {
return y.peerId() == peerId && y.tgId() == id && y.tgSlot() == slot;
}
return y.peerId() == peerId && y.tgId() == id;
});
if (innerIt != rewrite.end())
return true;
return false; return false;
});
if (it != m_groupVoice.end()) { std::vector<TalkgroupRuleRewrite> rewrite = x.config().rewrite();
entry = *it; auto innerIt = std::find_if(rewrite.begin(), rewrite.end(),
} else { [&](TalkgroupRuleRewrite y)
entry = TalkgroupRuleGroupVoice(); {
} if (slot != 0U) {
return y.peerId() == peerId && y.tgId() == id && y.tgSlot() == slot;
}
return y.peerId() == peerId && y.tgId() == id;
});
if (innerIt != rewrite.end())
return true;
return false;
});
if (it != m_groupVoice.end()) {
entry = *it;
} else {
entry = TalkgroupRuleGroupVoice();
} }
m_mutex.unlock();
return entry; return entry;
} }
@ -336,37 +324,34 @@ bool TalkgroupRulesLookup::load()
// clear table // clear table
clear(); clear();
m_mutex.lock(); std::lock_guard<std::mutex> lock(m_mutex);
{ yaml::Node& groupVoiceList = m_rules["groupVoice"];
yaml::Node& groupVoiceList = m_rules["groupVoice"];
if (groupVoiceList.size() == 0U) { if (groupVoiceList.size() == 0U) {
::LogError(LOG_HOST, "No group voice rules list defined!"); ::LogError(LOG_HOST, "No group voice rules list defined!");
return false; return false;
} }
for (size_t i = 0; i < groupVoiceList.size(); i++) {
TalkgroupRuleGroupVoice groupVoice = TalkgroupRuleGroupVoice(groupVoiceList[i]);
m_groupVoice.push_back(groupVoice);
std::string groupName = groupVoice.name(); for (size_t i = 0; i < groupVoiceList.size(); i++) {
uint32_t tgId = groupVoice.source().tgId(); TalkgroupRuleGroupVoice groupVoice = TalkgroupRuleGroupVoice(groupVoiceList[i]);
uint8_t tgSlot = groupVoice.source().tgSlot(); m_groupVoice.push_back(groupVoice);
bool active = groupVoice.config().active();
bool parrot = groupVoice.config().parrot();
uint32_t incCount = groupVoice.config().inclusion().size(); std::string groupName = groupVoice.name();
uint32_t excCount = groupVoice.config().exclusion().size(); uint32_t tgId = groupVoice.source().tgId();
uint32_t rewrCount = groupVoice.config().rewrite().size(); uint8_t tgSlot = groupVoice.source().tgSlot();
bool active = groupVoice.config().active();
bool parrot = groupVoice.config().parrot();
if (incCount > 0 && excCount > 0) { uint32_t incCount = groupVoice.config().inclusion().size();
::LogWarning(LOG_HOST, "Talkgroup (%s) defines both inclusions and exclusions! Inclusions take precedence and exclusions will be ignored.", groupName.c_str()); uint32_t excCount = groupVoice.config().exclusion().size();
} uint32_t rewrCount = groupVoice.config().rewrite().size();
::LogInfoEx(LOG_HOST, "Talkgroup NAME: %s SRC_TGID: %u SRC_TS: %u ACTIVE: %u PARROT: %u INCLUSIONS: %u EXCLUSIONS: %u REWRITES: %u", groupName.c_str(), tgId, tgSlot, active, parrot, incCount, excCount, rewrCount); if (incCount > 0 && excCount > 0) {
::LogWarning(LOG_HOST, "Talkgroup (%s) defines both inclusions and exclusions! Inclusions take precedence and exclusions will be ignored.", groupName.c_str());
} }
::LogInfoEx(LOG_HOST, "Talkgroup NAME: %s SRC_TGID: %u SRC_TS: %u ACTIVE: %u PARROT: %u INCLUSIONS: %u EXCLUSIONS: %u REWRITES: %u", groupName.c_str(), tgId, tgSlot, active, parrot, incCount, excCount, rewrCount);
} }
m_mutex.unlock();
size_t size = m_groupVoice.size(); size_t size = m_groupVoice.size();
if (size == 0U) if (size == 0U)
@ -388,7 +373,7 @@ bool TalkgroupRulesLookup::save()
return false; return false;
} }
m_mutex.lock(); std::lock_guard<std::mutex> lock(m_mutex);
// New list for our new group voice rules // New list for our new group voice rules
yaml::Node groupVoiceList; yaml::Node groupVoiceList;
@ -405,8 +390,6 @@ bool TalkgroupRulesLookup::save()
// Set the new rules // Set the new rules
newRules["groupVoice"] = groupVoiceList; newRules["groupVoice"] = groupVoiceList;
m_mutex.unlock();
// Make sure we actually did stuff right // Make sure we actually did stuff right
if (newRules["groupVoice"].size() != m_groupVoice.size()) { if (newRules["groupVoice"].size() != m_groupVoice.size()) {
LogError(LOG_HOST, "Generated YAML node for group lists did not match loaded group size! (%u != %u)", newRules["groupVoice"].size(), m_groupVoice.size()); LogError(LOG_HOST, "Generated YAML node for group lists did not match loaded group size! (%u != %u)", newRules["groupVoice"].size(), m_groupVoice.size());

@ -371,7 +371,7 @@ namespace lookups
bool m_acl; bool m_acl;
std::mutex m_mutex; static std::mutex m_mutex;
bool m_stop; bool m_stop;
/// <summary>Loads the table from the passed lookup table file.</summary> /// <summary>Loads the table from the passed lookup table file.</summary>

@ -21,6 +21,12 @@ using namespace network;
#include <cassert> #include <cassert>
#include <cstring> #include <cstring>
// ---------------------------------------------------------------------------
// Static Class Members
// ---------------------------------------------------------------------------
std::mutex RawFrameQueue::m_flushMutex;
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// Public Class Members // Public Class Members
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@ -32,7 +38,6 @@ using namespace network;
/// <param name="debug"></param> /// <param name="debug"></param>
RawFrameQueue::RawFrameQueue(udp::Socket* socket, bool debug) : RawFrameQueue::RawFrameQueue(udp::Socket* socket, bool debug) :
m_socket(socket), m_socket(socket),
m_flushMutex(),
m_buffers(), m_buffers(),
m_debug(debug) m_debug(debug)
{ {
@ -147,32 +152,27 @@ void RawFrameQueue::enqueueMessage(const uint8_t* message, uint32_t length, sock
bool RawFrameQueue::flushQueue() bool RawFrameQueue::flushQueue()
{ {
bool ret = true; bool ret = true;
m_flushMutex.lock(); std::lock_guard<std::mutex> lock(m_flushMutex);
{
if (m_buffers.empty()) {
m_flushMutex.unlock();
return false;
}
// bryanb: this is the same as above -- but for some assinine reason prevents if (m_buffers.empty()) {
// weirdness return false;
if (m_buffers.size() == 0U) { }
m_flushMutex.unlock();
return false;
}
// LogDebug(LOG_NET, "m_buffers len = %u", m_buffers.size()); // bryanb: this is the same as above -- but for some assinine reason prevents
// weirdness
if (m_buffers.size() == 0U) {
return false;
}
ret = true; // LogDebug(LOG_NET, "m_buffers len = %u", m_buffers.size());
if (!m_socket->write(m_buffers)) {
LogError(LOG_NET, "Failed writing data to the network");
ret = false;
}
deleteBuffers(); ret = true;
if (!m_socket->write(m_buffers)) {
LogError(LOG_NET, "Failed writing data to the network");
ret = false;
} }
m_flushMutex.unlock();
deleteBuffers();
return ret; return ret;
} }

@ -59,7 +59,7 @@ namespace network
uint32_t m_addrLen; uint32_t m_addrLen;
udp::Socket* m_socket; udp::Socket* m_socket;
std::mutex m_flushMutex; static std::mutex m_flushMutex;
udp::BufferVector m_buffers; udp::BufferVector m_buffers;
bool m_debug; bool m_debug;

@ -37,6 +37,12 @@ const uint32_t MAX_HARD_CONN_CAP = 250U;
const uint8_t MAX_PEER_LIST_BEFORE_FLUSH = 10U; const uint8_t MAX_PEER_LIST_BEFORE_FLUSH = 10U;
const uint32_t MAX_RID_LIST_CHUNK = 50U; const uint32_t MAX_RID_LIST_CHUNK = 50U;
// ---------------------------------------------------------------------------
// Static Class Members
// ---------------------------------------------------------------------------
std::mutex FNENetwork::m_peerMutex;
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// Public Class Members // Public Class Members
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@ -80,7 +86,6 @@ FNENetwork::FNENetwork(HostFNE* host, const std::string& address, uint16_t port,
m_ridLookup(nullptr), m_ridLookup(nullptr),
m_tidLookup(nullptr), m_tidLookup(nullptr),
m_status(NET_STAT_INVALID), m_status(NET_STAT_INVALID),
m_peerMutex(),
m_peers(), m_peers(),
m_peerAffiliations(), m_peerAffiliations(),
m_maintainenceTimer(1000U, pingTime), m_maintainenceTimer(1000U, pingTime),
@ -975,19 +980,15 @@ void* FNENetwork::threadedNetworkRx(void* arg)
/// <returns></returns> /// <returns></returns>
bool FNENetwork::erasePeerAffiliations(uint32_t peerId) bool FNENetwork::erasePeerAffiliations(uint32_t peerId)
{ {
m_peerMutex.lock(); std::lock_guard<std::mutex> lock(m_peerMutex);
{ auto it = std::find_if(m_peerAffiliations.begin(), m_peerAffiliations.end(), [&](PeerAffiliationMapPair x) { return x.first == peerId; });
auto it = std::find_if(m_peerAffiliations.begin(), m_peerAffiliations.end(), [&](PeerAffiliationMapPair x) { return x.first == peerId; }); if (it != m_peerAffiliations.end()) {
if (it != m_peerAffiliations.end()) { lookups::AffiliationLookup* aff = m_peerAffiliations[peerId];
lookups::AffiliationLookup* aff = m_peerAffiliations[peerId]; m_peerAffiliations.erase(peerId);
m_peerAffiliations.erase(peerId); delete aff;
delete aff;
return true;
m_peerMutex.unlock();
return true;
}
} }
m_peerMutex.unlock();
return false; return false;
} }
@ -999,16 +1000,12 @@ bool FNENetwork::erasePeerAffiliations(uint32_t peerId)
/// <returns></returns> /// <returns></returns>
bool FNENetwork::erasePeer(uint32_t peerId) bool FNENetwork::erasePeer(uint32_t peerId)
{ {
m_peerMutex.lock(); std::lock_guard<std::mutex> lock(m_peerMutex);
{ auto it = std::find_if(m_peers.begin(), m_peers.end(), [&](PeerMapPair x) { return x.first == peerId; });
auto it = std::find_if(m_peers.begin(), m_peers.end(), [&](PeerMapPair x) { return x.first == peerId; }); if (it != m_peers.end()) {
if (it != m_peers.end()) { m_peers.erase(peerId);
m_peers.erase(peerId); return true;
m_peerMutex.unlock();
return true;
}
} }
m_peerMutex.unlock();
return false; return false;
} }

@ -270,7 +270,7 @@ namespace network
NET_CONN_STATUS m_status; NET_CONN_STATUS m_status;
std::mutex m_peerMutex; static std::mutex m_peerMutex;
typedef std::pair<const uint32_t, network::FNEPeerConnection*> PeerMapPair; typedef std::pair<const uint32_t, network::FNEPeerConnection*> PeerMapPair;
std::unordered_map<uint32_t, FNEPeerConnection*> m_peers; std::unordered_map<uint32_t, FNEPeerConnection*> m_peers;
typedef std::pair<const uint32_t, lookups::AffiliationLookup*> PeerAffiliationMapPair; typedef std::pair<const uint32_t, lookups::AffiliationLookup*> PeerAffiliationMapPair;

@ -714,7 +714,7 @@ int Host::run()
} }
bool hasTxShutdown = false; bool hasTxShutdown = false;
std::mutex clockingMutex; static std::mutex clockingMutex;
// Macro to start DMR duplex idle transmission (or beacon) // Macro to start DMR duplex idle transmission (or beacon)
#define START_DMR_DUPLEX_IDLE(x) \ #define START_DMR_DUPLEX_IDLE(x) \
@ -734,8 +734,10 @@ int Host::run()
if (dmr != nullptr) { if (dmr != nullptr) {
LogDebug(LOG_HOST, "DMR, started slot 1 frame processor (modem write)"); LogDebug(LOG_HOST, "DMR, started slot 1 frame processor (modem write)");
while (!g_killed) { while (!g_killed) {
clockingMutex.lock(); // scope is intentional
{ {
std::lock_guard<std::mutex> lock(clockingMutex);
// ------------------------------------------------------ // ------------------------------------------------------
// -- Write to Modem Processing -- // -- Write to Modem Processing --
// ------------------------------------------------------ // ------------------------------------------------------
@ -757,7 +759,6 @@ int Host::run()
} }
}); });
} }
clockingMutex.unlock();
if (m_state != STATE_IDLE) if (m_state != STATE_IDLE)
Thread::sleep(m_activeTickDelay); Thread::sleep(m_activeTickDelay);
@ -776,8 +777,10 @@ int Host::run()
if (dmr != nullptr) { if (dmr != nullptr) {
LogDebug(LOG_HOST, "DMR, started slot 2 frame processor (modem write)"); LogDebug(LOG_HOST, "DMR, started slot 2 frame processor (modem write)");
while (!g_killed) { while (!g_killed) {
clockingMutex.lock(); // scope is intentional
{ {
std::lock_guard<std::mutex> lock(clockingMutex);
// ------------------------------------------------------ // ------------------------------------------------------
// -- Write to Modem Processing -- // -- Write to Modem Processing --
// ------------------------------------------------------ // ------------------------------------------------------
@ -799,7 +802,6 @@ int Host::run()
} }
}); });
} }
clockingMutex.unlock();
if (m_state != STATE_IDLE) if (m_state != STATE_IDLE)
Thread::sleep(m_activeTickDelay); Thread::sleep(m_activeTickDelay);
@ -819,8 +821,10 @@ int Host::run()
if (p25 != nullptr) { if (p25 != nullptr) {
LogDebug(LOG_HOST, "P25, started frame processor (modem write)"); LogDebug(LOG_HOST, "P25, started frame processor (modem write)");
while (!g_killed) { while (!g_killed) {
clockingMutex.lock(); // scope is intentional
{ {
std::lock_guard<std::mutex> lock(clockingMutex);
// ------------------------------------------------------ // ------------------------------------------------------
// -- Write to Modem Processing -- // -- Write to Modem Processing --
// ------------------------------------------------------ // ------------------------------------------------------
@ -839,7 +843,6 @@ int Host::run()
} }
}); });
} }
clockingMutex.unlock();
if (m_state != STATE_IDLE) if (m_state != STATE_IDLE)
Thread::sleep(m_activeTickDelay); Thread::sleep(m_activeTickDelay);
@ -859,8 +862,10 @@ int Host::run()
if (nxdn != nullptr) { if (nxdn != nullptr) {
LogDebug(LOG_HOST, "NXDN, started frame processor (modem write)"); LogDebug(LOG_HOST, "NXDN, started frame processor (modem write)");
while (!g_killed) { while (!g_killed) {
clockingMutex.lock(); // scope is intentional
{ {
std::lock_guard<std::mutex> lock(clockingMutex);
// ------------------------------------------------------ // ------------------------------------------------------
// -- Write to Modem Processing -- // -- Write to Modem Processing --
// ------------------------------------------------------ // ------------------------------------------------------
@ -879,7 +884,6 @@ int Host::run()
} }
}); });
} }
clockingMutex.unlock();
if (m_state != STATE_IDLE) if (m_state != STATE_IDLE)
Thread::sleep(m_activeTickDelay); Thread::sleep(m_activeTickDelay);
@ -928,8 +932,10 @@ int Host::run()
} }
} }
clockingMutex.lock(); // scope is intentional
{ {
std::lock_guard<std::mutex> lock(clockingMutex);
// ------------------------------------------------------ // ------------------------------------------------------
// -- Modem Clocking -- // -- Modem Clocking --
// ------------------------------------------------------ // ------------------------------------------------------
@ -939,7 +945,6 @@ int Host::run()
m_modem->clock(ms); m_modem->clock(ms);
} }
clockingMutex.unlock();
// ------------------------------------------------------ // ------------------------------------------------------
// -- Read from Modem Processing -- // -- Read from Modem Processing --
@ -1057,7 +1062,7 @@ int Host::run()
LogDebug(LOG_HOST, "CW, start transmitting"); LogDebug(LOG_HOST, "CW, start transmitting");
m_isTxCW = true; m_isTxCW = true;
clockingMutex.lock(); std::lock_guard<std::mutex> lock(clockingMutex);
setState(STATE_IDLE); setState(STATE_IDLE);
m_modem->sendCWId(m_cwCallsign); m_modem->sendCWId(m_cwCallsign);
@ -1088,7 +1093,6 @@ int Host::run()
Thread::sleep(CW_IDLE_SLEEP_MS); Thread::sleep(CW_IDLE_SLEEP_MS);
} while (true); } while (true);
clockingMutex.unlock();
m_isTxCW = false; m_isTxCW = false;
m_cwIdTimer.setTimeout(m_cwIdTime); m_cwIdTimer.setTimeout(m_cwIdTime);
m_cwIdTimer.start(); m_cwIdTimer.start();

Loading…
Cancel
Save

Powered by TurnKey Linux.