Add FalukantFamilyWorker and related SQL queries: Introduced the FalukantFamilyWorker to manage family-related logic, including marriage satisfaction and relationship states. Added new SQL queries for handling lover relationships and marriage updates, enhancing the overall functionality of family dynamics in the application.

This commit is contained in:
Torsten Schulz (local)
2026-03-20 10:26:15 +01:00
parent f9c80bbd6b
commit 6a5ff4557e
8 changed files with 1164 additions and 1 deletions

View File

@@ -0,0 +1,766 @@
//! Liebhaber, Ehezufriedenheit, Ansehen, Monatskosten (Handoff: docs/FALUKANT_DAEMON_HANDOFF.md).
//! Benötigt `migrations/001_falukant_family_lovers.sql` (ggf. `002` bei Altbestand).
use std::sync::atomic::Ordering;
use std::sync::Arc;
use std::time::{Duration, Instant};
use rand::distributions::{Distribution, Uniform};
use rand::rngs::StdRng;
use rand::SeedableRng;
use super::base::{BaseWorker, Worker, WorkerState};
use super::sql::{
QUERY_FAMILY_SCHEMA_READY, QUERY_GET_ACTIVE_LOVER_ROWS_FOR_DAILY,
QUERY_GET_ACTIVE_LOVER_ROWS_FOR_MONTHLY, QUERY_GET_LOVER_PREGNANCY_CANDIDATES,
QUERY_GET_MARRIAGE_ROWS, QUERY_INSERT_CHILD, QUERY_INSERT_CHILD_RELATION_LOVER,
QUERY_LOVER_BIRTH_PENALTY_MARRIAGE, QUERY_LOVER_BIRTH_PENALTY_REPUTATION,
QUERY_MARK_LOVER_DAILY_DONE, QUERY_MARK_LOVER_MONTHLY_DONE,
QUERY_MARRIAGE_SUBTRACT_SATISFACTION, QUERY_RESET_LOVER_UNDERPAY_COUNTERS,
QUERY_UPDATE_CHARACTER_REPUTATION, QUERY_UPDATE_LOVER_UNDERPAY_STATE,
QUERY_UPDATE_LOVER_VISIBILITY_DISCRETION, QUERY_UPDATE_MARRIAGE_STATE,
};
use crate::db::{ConnectionPool, DbError};
use crate::message_broker::MessageBroker;
const DAILY_INTERVAL: Duration = Duration::from_secs(24 * 3600);
const MONTHLY_INTERVAL: Duration = Duration::from_secs(30 * 24 * 3600);
pub struct FalukantFamilyWorker {
base: BaseWorker,
rng: StdRng,
dist: Uniform<f64>,
last_daily: Option<Instant>,
last_monthly: Option<Instant>,
schema_ready: bool,
}
impl FalukantFamilyWorker {
pub fn new(pool: ConnectionPool, broker: MessageBroker) -> Self {
Self {
base: BaseWorker::new("FalukantFamilyWorker", pool, broker),
rng: StdRng::from_entropy(),
dist: Uniform::from(0.0..1.0),
last_daily: None,
last_monthly: None,
schema_ready: false,
}
}
fn run_iteration(&mut self, state: &WorkerState) {
self.base.set_current_step("FalukantFamilyWorker iteration");
let now = Instant::now();
if !self.schema_ready {
if let Ok(true) = self.check_schema() {
self.schema_ready = true;
} else {
std::thread::sleep(Duration::from_secs(1));
return;
}
}
if Self::should_run(self.last_daily, now, DAILY_INTERVAL) {
if let Err(e) = self.process_daily() {
eprintln!("[FalukantFamilyWorker] process_daily: {e}");
}
self.last_daily = Some(now);
}
if Self::should_run(self.last_monthly, now, MONTHLY_INTERVAL) {
if let Err(e) = self.process_monthly() {
eprintln!("[FalukantFamilyWorker] process_monthly: {e}");
}
self.last_monthly = Some(now);
}
std::thread::sleep(Duration::from_secs(1));
if !state.running_worker.load(Ordering::Relaxed) {
// stopping
}
}
fn should_run(last: Option<Instant>, now: Instant, interval: Duration) -> bool {
match last {
None => true,
Some(t) => now.saturating_duration_since(t) >= interval,
}
}
fn check_schema(&mut self) -> Result<bool, DbError> {
let mut conn = self
.base
.pool
.get()
.map_err(|e| DbError::new(format!("DB-Verbindung fehlgeschlagen: {e}")))?;
conn.prepare("family_schema", QUERY_FAMILY_SCHEMA_READY)?;
let rows = conn.execute("family_schema", &[])?;
Ok(rows
.first()
.and_then(|r| r.get("ready"))
.map(|v| v == "true" || v == "t")
.unwrap_or(false))
}
fn process_daily(&mut self) -> Result<(), DbError> {
let mut conn = self
.base
.pool
.get()
.map_err(|e| DbError::new(format!("DB-Verbindung fehlgeschlagen: {e}")))?;
conn.prepare("get_lovers", QUERY_GET_ACTIVE_LOVER_ROWS_FOR_DAILY)?;
let lover_rows = conn.execute("get_lovers", &[])?;
conn.prepare("get_marriages", QUERY_GET_MARRIAGE_ROWS)?;
let marriage_rows = conn.execute("get_marriages", &[])?;
let marriages: Vec<MarriageData> = marriage_rows
.into_iter()
.filter_map(|r| {
Some(MarriageData {
id: parse_i32(&r, "marriage_id", -1),
m1: parse_i32(&r, "m1", -1),
m2: parse_i32(&r, "m2", -1),
satisfaction: parse_i32(&r, "marriage_satisfaction", 55),
drift_high: parse_i32(&r, "marriage_drift_high", 0),
drift_low: parse_i32(&r, "marriage_drift_low", 0),
title1_tr: r.get("title1_tr").cloned().unwrap_or_default(),
title2_tr: r.get("title2_tr").cloned().unwrap_or_default(),
})
})
.filter(|m| m.id > 0)
.collect();
let mut lovers: Vec<LoverData> = lover_rows
.into_iter()
.filter_map(|r| {
Some(LoverData {
rel_id: parse_i32(&r, "rel_id", -1),
c1: parse_i32(&r, "c1", -1),
c2: parse_i32(&r, "c2", -1),
lover_role: r.get("lover_role").cloned().unwrap_or_default(),
affection: parse_i32(&r, "affection", 50),
visibility: parse_i32(&r, "visibility", 0),
discretion: parse_i32(&r, "discretion", 50),
maintenance_level: parse_i32(&r, "maintenance_level", 50),
status_fit: parse_i32(&r, "status_fit", 0),
scandal_extra: parse_i32(&r, "scandal_extra_daily_pct", 0),
title1_tr: r.get("title1_tr").cloned().unwrap_or_default(),
title2_tr: r.get("title2_tr").cloned().unwrap_or_default(),
})
})
.filter(|l| l.rel_id > 0)
.collect();
let mut char_lover_count: std::collections::HashMap<i32, usize> =
std::collections::HashMap::new();
for l in &lovers {
*char_lover_count.entry(l.c1).or_insert(0) += 1;
*char_lover_count.entry(l.c2).or_insert(0) += 1;
}
conn.prepare("upd_vd", QUERY_UPDATE_LOVER_VISIBILITY_DISCRETION)?;
for l in &mut lovers {
let ehe_conflict = marriages.iter().any(|m| {
(m.m1 == l.c1 || m.m2 == l.c1 || m.m1 == l.c2 || m.m2 == l.c2) && m.satisfaction < 40
});
let mut v_net = 0i32;
if l.maintenance_level < 35 {
v_net += 1;
}
if l.affection < 30 {
v_net += 1;
}
if l.status_fit == -2 {
v_net += 2;
}
if ehe_conflict {
v_net += 1;
}
if l.discretion >= 60 {
v_net -= 1;
}
if l.maintenance_level >= 70 {
v_net -= 1;
}
let new_vis = clamp_i32(l.visibility + v_net, 0, 100);
let mut d_net = 0i32;
if l.maintenance_level >= 70 {
d_net += 1;
}
if l.maintenance_level < 35 {
d_net -= 1;
}
if l.visibility > 60 {
d_net -= 1;
}
let new_disc = clamp_i32(l.discretion + d_net, 0, 100);
conn.execute(
"upd_vd",
&[&new_vis, &new_disc, &l.rel_id],
)?;
l.visibility = new_vis;
l.discretion = new_disc;
}
conn.prepare("mark_daily", QUERY_MARK_LOVER_DAILY_DONE)?;
for l in &lovers {
conn.execute("mark_daily", &[&l.rel_id])?;
}
for m in &marriages {
let touching: Vec<&LoverData> = lovers
.iter()
.filter(|l| {
let (a, b) = (l.c1, l.c2);
((a == m.m1 && b != m.m2) || (b == m.m1 && a != m.m2))
|| ((a == m.m2 && b != m.m1) || (b == m.m2 && a != m.m1))
})
.collect();
if touching.is_empty() {
let mut sat = m.satisfaction;
let mut dh = m.drift_high;
let mut dl = m.drift_low;
if sat > 55 {
dh += 1;
if dh >= 3 {
sat = (sat - 1).max(0);
dh = 0;
}
} else if sat < 55 {
dl += 1;
if dl >= 5 {
sat = (sat + 1).min(100);
dl = 0;
}
}
conn.prepare("upd_marriage", QUERY_UPDATE_MARRIAGE_STATE)?;
conn.execute(
"upd_marriage",
&[&sat, &dh, &dl, &m.id],
)?;
continue;
}
let mg = marriage_rank_group(&m.title1_tr, &m.title2_tr);
let mistress_n = touching
.iter()
.filter(|l| l.lover_role == "mistress_or_favorite")
.count();
let total_lovers_here = touching.len();
let mut delta = 0i32;
for l in &touching {
delta += lover_marriage_daily_delta(
mg,
l,
m.satisfaction,
mistress_n,
total_lovers_here,
);
}
if touching.iter().any(|l| l.visibility >= 60) {
delta -= 2;
}
if total_lovers_here >= 2 {
delta -= 2;
}
if touching
.iter()
.any(|l| l.lover_role == "mistress_or_favorite" && l.maintenance_level < 35)
{
delta -= 1;
}
let sat = clamp_i32(m.satisfaction + delta, 0, 100);
conn.prepare("upd_marriage", QUERY_UPDATE_MARRIAGE_STATE)?;
conn.execute(
"upd_marriage",
&[&sat, &m.drift_high, &m.drift_low, &m.id],
)?;
}
conn.prepare("upd_rep", QUERY_UPDATE_CHARACTER_REPUTATION)?;
for l in &lovers {
let g = pair_rank_group(&l.title1_tr, &l.title2_tr);
let scandal = l.visibility > 70;
let rm = rank_rep_modifier(g, scandal);
let vf = 0.4 + (l.visibility as f64 / 100.0) * 1.6;
let base = match l.lover_role.as_str() {
"secret_affair" => -0.2,
"lover" => -0.4,
"mistress_or_favorite" => -0.6,
_ => -0.4,
};
let mut delta = base * vf * rm;
let order_ok = l.maintenance_level >= 65
&& l.discretion >= 60
&& l.visibility <= 35
&& mistress_count_for_pair(&lovers, l.c1, l.c2) <= 1;
if l.lover_role == "mistress_or_favorite" && order_ok {
if g == 2 {
delta = 0.1;
} else if g == 3 {
delta = 0.2;
}
}
delta = delta.clamp(-3.0, 1.0);
for cid in [l.c1, l.c2] {
let cur = fetch_reputation(&mut conn, cid)?;
let new_rep = (cur + delta).clamp(0.0, 100.0);
let s = format!("{:.2}", new_rep);
conn.execute("upd_rep", &[&s, &cid])?;
}
let married_c1 = marriages
.iter()
.any(|m| m.m1 == l.c1 || m.m2 == l.c1);
let married_c2 = marriages
.iter()
.any(|m| m.m1 == l.c2 || m.m2 == l.c2);
let mut p = 1.0
+ (l.visibility as f64) / 25.0
+ if married_c1 || married_c2 { 2.0 } else { 0.0 }
+ if l.status_fit == -2 { 2.0 } else { 0.0 }
+ if l.maintenance_level < 25 { 3.0 } else { 0.0 }
+ if char_lover_count.get(&l.c1).copied().unwrap_or(0) >= 2
|| char_lover_count.get(&l.c2).copied().unwrap_or(0) >= 2
{
3.0
} else {
0.0
}
+ l.scandal_extra as f64;
if l.discretion >= 75 {
p -= 2.0;
}
if g == 3
&& l.lover_role == "mistress_or_favorite"
&& l.maintenance_level >= 65
&& l.visibility <= 40
{
p -= 2.0;
}
p = p.clamp(0.0, 25.0);
if self.dist.sample(&mut self.rng) * 100.0 < p {
let _ = self.base.broker.publish(format!(
r#"{{"event":"falukant_family_scandal_hint","relationship_id":{}}}"#,
l.rel_id
));
}
}
Ok(())
}
fn process_monthly(&mut self) -> Result<(), DbError> {
let mut conn = self
.base
.pool
.get()
.map_err(|e| DbError::new(format!("DB-Verbindung fehlgeschlagen: {e}")))?;
conn.prepare("get_lovers_m", QUERY_GET_ACTIVE_LOVER_ROWS_FOR_MONTHLY)?;
let lover_rows = conn.execute("get_lovers_m", &[])?;
conn.prepare("upd_under", QUERY_UPDATE_LOVER_UNDERPAY_STATE)?;
conn.prepare("reset_under", QUERY_RESET_LOVER_UNDERPAY_COUNTERS)?;
conn.prepare("mar_sub", QUERY_MARRIAGE_SUBTRACT_SATISFACTION)?;
conn.prepare("mark_monthly", QUERY_MARK_LOVER_MONTHLY_DONE)?;
for r in lover_rows {
let rel_id = parse_i32(&r, "rel_id", -1);
if rel_id < 0 {
continue;
}
let lover_role = r.get("lover_role").cloned().unwrap_or_default();
let maintenance_level = parse_i32(&r, "maintenance_level", 50);
let status_fit = parse_i32(&r, "status_fit", 0);
let mut base = parse_i32(&r, "monthly_base_cost", 0);
if base <= 0 {
base = match lover_role.as_str() {
"secret_affair" => 10,
"lover" => 30,
"mistress_or_favorite" => 80,
_ => 30,
};
}
let title1 = r.get("title1_tr").cloned().unwrap_or_default();
let title2 = r.get("title2_tr").cloned().unwrap_or_default();
let g = pair_rank_group(&title1, &title2);
let rank_m = rank_cost_multiplier(g);
let maint_f = 0.6 + (maintenance_level as f64 / 100.0) * 1.2;
let sf_m = match status_fit {
-2 => 1.35,
-1 => 1.15,
_ => 1.0,
};
let cost = ((base as f64) * rank_m * maint_f * sf_m).round() as i32;
let u1 = parse_opt_i32(&r, "user1_id");
let u2 = parse_opt_i32(&r, "user2_id");
let payer = u1.or(u2).filter(|x| *x > 0);
let affection = parse_i32(&r, "affection", 50);
let visibility = parse_i32(&r, "visibility", 0);
let discretion = parse_i32(&r, "discretion", 50);
let mut consec = parse_i32(&r, "months_underfunded", 0);
let mut scandal_extra = parse_i32(&r, "scandal_extra_daily_pct", 0);
if let Some(uid) = payer {
let money = self.get_user_money(uid)?;
if money >= cost as f64 {
self.base.change_falukant_user_money(
uid,
-(cost as f64),
"lover maintenance",
)?;
conn.execute("reset_under", &[&rel_id])?;
} else {
let new_aff = clamp_i32(affection - 8, 0, 100);
let new_disc = clamp_i32(discretion - 6, 0, 100);
let new_vis = clamp_i32(visibility + 8, 0, 100);
consec += 1;
if consec >= 2 {
scandal_extra = (scandal_extra + 2).min(100);
}
conn.execute(
"upd_under",
&[
&new_aff,
&new_disc,
&new_vis,
&consec,
&scandal_extra,
&rel_id,
],
)?;
for cid in [parse_i32(&r, "c1", 0), parse_i32(&r, "c2", 0)] {
if cid <= 0 {
continue;
}
if let Ok(Some(mid)) = marriage_id_for_character(&mut conn, cid) {
conn.execute("mar_sub", &[&mid, &4])?;
}
}
if visibility >= 40 {
for cid in [parse_i32(&r, "c1", 0), parse_i32(&r, "c2", 0)] {
if cid > 0 {
let cur = fetch_reputation(&mut conn, cid)?;
let s = format!("{:.2}", (cur - 1.0).max(0.0));
conn.prepare("upd_rep", QUERY_UPDATE_CHARACTER_REPUTATION)?;
conn.execute("upd_rep", &[&s, &cid])?;
}
}
}
}
}
conn.execute("mark_monthly", &[&rel_id])?;
}
drop(conn);
self.process_lover_births()?;
Ok(())
}
fn get_user_money(&mut self, user_id: i32) -> Result<f64, DbError> {
use super::sql::{QUERY_GET_CURRENT_MONEY};
let mut conn = self
.base
.pool
.get()
.map_err(|e| DbError::new(format!("DB-Verbindung fehlgeschlagen: {e}")))?;
conn.prepare("gcm", QUERY_GET_CURRENT_MONEY)?;
let rows = conn.execute("gcm", &[&user_id])?;
Ok(rows
.first()
.and_then(|r| r.get("sum"))
.and_then(|v| v.parse::<f64>().ok())
.unwrap_or(0.0))
}
fn process_lover_births(&mut self) -> Result<(), DbError> {
let mut conn = self
.base
.pool
.get()
.map_err(|e| DbError::new(format!("DB-Verbindung fehlgeschlagen: {e}")))?;
conn.prepare("lover_preg", QUERY_GET_LOVER_PREGNANCY_CANDIDATES)?;
let rows = conn.execute("lover_preg", &[])?;
conn.prepare("insert_child", QUERY_INSERT_CHILD)?;
conn.prepare("insert_child_rel_lover", QUERY_INSERT_CHILD_RELATION_LOVER)?;
conn.prepare("pen_mar", QUERY_LOVER_BIRTH_PENALTY_MARRIAGE)?;
conn.prepare("pen_rep", QUERY_LOVER_BIRTH_PENALTY_REPUTATION)?;
for row in rows {
let father_cid = parse_i32(&row, "father_cid", -1);
let mother_cid = parse_i32(&row, "mother_cid", -1);
if father_cid < 0 || mother_cid < 0 {
continue;
}
let title_of_nobility = parse_i32(&row, "title_of_nobility", 0);
let last_name = parse_i32(&row, "last_name", 0);
let region_id = parse_i32(&row, "region_id", 0);
let father_uid = parse_opt_i32(&row, "father_uid");
let mother_uid = parse_opt_i32(&row, "mother_uid");
let gender = if self.dist.sample(&mut self.rng) < 0.5 {
"male"
} else {
"female"
};
let inserted =
conn.execute("insert_child", &[&region_id, &gender, &last_name, &title_of_nobility])?;
let child_cid = inserted
.first()
.and_then(|r| r.get("child_cid"))
.and_then(|v| v.parse::<i32>().ok())
.unwrap_or(-1);
if child_cid < 0 {
continue;
}
conn.execute(
"insert_child_rel_lover",
&[&father_cid, &mother_cid, &child_cid],
)?;
conn.execute("pen_mar", &[&father_cid])?;
conn.execute("pen_mar", &[&mother_cid])?;
conn.execute("pen_rep", &[&father_cid])?;
conn.execute("pen_rep", &[&mother_cid])?;
if let Some(uid) = father_uid {
self.publish_children(uid);
}
if let Some(uid) = mother_uid {
self.publish_children(uid);
}
}
Ok(())
}
fn publish_children(&self, user_id: i32) {
let children_update =
format!(r#"{{"event":"children_update","user_id":{}}}"#, user_id);
self.base.broker.publish(children_update);
let update_status =
format!(r#"{{"event":"falukantUpdateStatus","user_id":{}}}"#, user_id);
self.base.broker.publish(update_status);
}
}
struct MarriageData {
id: i32,
m1: i32,
m2: i32,
satisfaction: i32,
drift_high: i32,
drift_low: i32,
title1_tr: String,
title2_tr: String,
}
struct LoverData {
rel_id: i32,
c1: i32,
c2: i32,
lover_role: String,
affection: i32,
visibility: i32,
discretion: i32,
maintenance_level: i32,
status_fit: i32,
scandal_extra: i32,
title1_tr: String,
title2_tr: String,
}
fn parse_i32(row: &crate::db::Row, key: &str, default: i32) -> i32 {
row.get(key)
.and_then(|v| v.parse::<i32>().ok())
.unwrap_or(default)
}
fn parse_opt_i32(row: &crate::db::Row, key: &str) -> Option<i32> {
row.get(key).and_then(|v| v.parse::<i32>().ok())
}
fn clamp_i32(v: i32, lo: i32, hi: i32) -> i32 {
v.max(lo).min(hi)
}
fn title_group(tr: &str) -> u8 {
match tr {
"noncivil" | "civil" | "sir" => 0,
"townlord" | "by" | "landlord" => 1,
"knight" | "baron" | "count" | "palsgrave" | "margrave" | "landgrave" => 2,
"ruler" | "elector"
| "imperial-prince"
| "duke"
| "grand-duke"
| "prince-regent"
| "king" => 3,
_ => 0,
}
}
fn marriage_rank_group(t1: &str, t2: &str) -> u8 {
title_group(t1).max(title_group(t2))
}
fn pair_rank_group(t1: &str, t2: &str) -> u8 {
title_group(t1).max(title_group(t2))
}
fn rank_cost_multiplier(g: u8) -> f64 {
match g {
0 => 1.0,
1 => 1.6,
2 => 2.6,
3 => 4.0,
_ => 1.0,
}
}
fn rank_rep_modifier(g: u8, scandal: bool) -> f64 {
if g == 3 && scandal {
return 1.5;
}
match g {
0 => 1.8,
1 => 1.3,
2 => 1.0,
3 => 0.7,
_ => 1.0,
}
}
fn lover_marriage_daily_delta(
mg: u8,
l: &LoverData,
m_sat: i32,
mistress_n: usize,
total_lovers: usize,
) -> i32 {
let role = l.lover_role.as_str();
match mg {
0 => match role {
"secret_affair" => -1,
"lover" => -2,
"mistress_or_favorite" => -3,
_ => -2,
},
1 => match role {
"secret_affair" => -1,
"lover" => -1,
"mistress_or_favorite" => -2,
_ => -1,
},
2 => match role {
"secret_affair" => -1,
"lover" => -1,
"mistress_or_favorite" => -1,
_ => -1,
},
3 => {
if role == "mistress_or_favorite" {
if l.visibility <= 35
&& l.maintenance_level >= 65
&& m_sat >= 45
&& mistress_n <= 1
&& total_lovers <= 1
{
return 1;
}
if l.visibility > 50 || l.maintenance_level < 40 {
return -1;
}
return 0;
}
if role == "secret_affair" {
return 0;
}
if role == "lover" {
return 0;
}
0
}
_ => -1,
}
}
fn mistress_count_for_pair(lovers: &[LoverData], c1: i32, c2: i32) -> usize {
lovers
.iter()
.filter(|l| {
(l.c1 == c1 || l.c2 == c1 || l.c1 == c2 || l.c2 == c2)
&& l.lover_role == "mistress_or_favorite"
})
.count()
}
fn fetch_reputation(conn: &mut crate::db::DbConnection, cid: i32) -> Result<f64, DbError> {
conn.prepare("fr", "SELECT COALESCE(reputation, 50)::float8 AS r FROM falukant_data.character WHERE id = $1")?;
let rows = conn.execute("fr", &[&cid])?;
Ok(rows
.first()
.and_then(|r| r.get("r"))
.and_then(|v| v.parse::<f64>().ok())
.unwrap_or(50.0))
}
fn marriage_id_for_character(
conn: &mut crate::db::DbConnection,
cid: i32,
) -> Result<Option<i32>, DbError> {
conn.prepare(
"mid",
r#"SELECT r.id FROM falukant_data.relationship r
JOIN falukant_type.relationship rt ON rt.id = r.relationship_type_id
AND rt.tr IN ('married', 'engaged', 'wooing')
WHERE r.character1_id = $1 OR r.character2_id = $1 LIMIT 1"#,
)?;
let rows = conn.execute("mid", &[&cid])?;
Ok(rows
.first()
.and_then(|r| r.get("id"))
.and_then(|v| v.parse::<i32>().ok()))
}
impl Worker for FalukantFamilyWorker {
fn start_worker_thread(&mut self) {
let pool = self.base.pool.clone();
let broker = self.base.broker.clone();
self.base
.start_worker_with_loop(move |state: Arc<WorkerState>| {
let mut worker = FalukantFamilyWorker::new(pool.clone(), broker.clone());
while state.running_worker.load(Ordering::Relaxed) {
worker.run_iteration(&state);
}
});
}
fn stop_worker_thread(&mut self) {
self.base.stop_worker();
}
fn enable_watchdog(&mut self) {
self.base.start_watchdog();
}
}