88from typing import Dict , Callable , Any
99from simulation_server .virtual_accelerator import VirtualAccelerator
1010import threading
11+ from .utils .timer import Timer
1112
1213class SimServer (SimpleServer ):
1314 """
@@ -83,6 +84,10 @@ def __init__(self, pvdb: dict, prefix: str = "", threading: bool = True):
8384 self ._db [self .sim_pv_name ] = {
8485 "value" : 0
8586 }
87+ self .sim_timeout_name = "VIRT:BEAM:SIMULATE_TIMEOUT"
88+ self ._db [self .sim_timeout_name ] = {
89+ "value" : 0.5
90+ }
8691
8792 # Create CA PVs
8893 self .createPV (prefix , self ._db )
@@ -287,6 +292,8 @@ def __init__(
287292 self .thread = threading .Thread (target = self ._model_update_thread )
288293 self .new_data = {}
289294
295+ self .timer = Timer (0.5 , self ._trigger_sim , periodic = True , manual = True )
296+
290297 # get list of pvs that should be updated every time we write to a PV
291298 self .measurement_pvs = self .get_measurement_pvs ()
292299
@@ -299,6 +306,12 @@ def __init__(
299306 self .update_cache (self .measurement_pvs , True )
300307
301308 self .thread .start ()
309+ if self .server .threaded :
310+ self .timer .start ()
311+
312+ def _trigger_sim (self ):
313+ with self .write_guard :
314+ self .thread_cond .notify_all ()
302315
303316 def _set_and_simulate (self , new_data : dict ):
304317 """Updates PVs on the model, then updates the PV cache with results"""
@@ -316,9 +329,11 @@ def _model_update_thread(self):
316329 # Unlocked by thread_cond.wait()
317330 self .write_guard .acquire ()
318331
319- # Wait for a trigger
332+ # Wait for a trigger (unlocks write_guard)
320333 self .thread_cond .wait ()
321334
335+ print ('Simulation triggered' )
336+
322337 start = time .time ()
323338
324339 # run simulation
@@ -435,24 +450,32 @@ def write(self, reason, value):
435450 """write to a PV, run the simulation, and then update all other PVs"""
436451 print (f"Writing { value } to { reason } " )
437452
453+ # Update internal values quickly so readbacks dont fail
454+ self .set_cached_value (reason , value , True )
455+
456+ # Halt countdown
457+ self .timer .cancel ()
458+
438459 # Re-run the entire simulation if requested
439460 if reason == self .server .sim_pv_name :
440461 with self .write_guard :
441- self .set_cached_value (reason , value , True )
442462 self .thread_cond .notify_all ()
443463 return
444464
465+ # Adjust simulation timeout
466+ if reason == self .server .sim_timeout_name :
467+ self .timer .interval = int (value )
468+ return
469+
445470 # Single threaded mode; do all updates immediately
446471 if not self .server .threaded :
447- # Set new value for this PV and update monitors to make caput readback behave nicely
448- self .set_cached_value (reason , value , True )
449472 # Set changed PVs, and update the new values
450473 self ._set_and_simulate ({reason : value })
451474 return
452475
453476 with self .write_guard :
454- # update the control PV fast
455- self .set_cached_value (reason , value , True )
456-
457477 # this is sent to the updater thread
458478 self .new_data [reason ] = value
479+
480+ # Begin simulation timeout period
481+ self .timer .reset ()
0 commit comments