@@ -228,11 +228,14 @@ async def queue_set(self, func, field, value):
228228 value (float): The value to be set.
229229 """
230230 async with self ._new_data_lock :
231+ # Clear first otherwise it is possible to yield to another thread which will
232+ # then think the lattice is up to date with the most recently accepted caput
233+ # /lattice.set_value. when it isnt.
234+ self ._up_to_date .clear ()
231235 await self ._queue .put ((func , field , value ))
232236 # If this flag gets cleared while we are recalculating, then it can cause
233237 # everything to lock, so we setup a lock between this function and the
234238 # recalculate function
235- self ._up_to_date .clear ()
236239 logging .debug (f"Added task to async queue. qsize={ self ._queue .qsize ()} " )
237240
238241 async def _gather_one_sample (self ):
@@ -289,47 +292,45 @@ async def _recalculate_phys_data(self, callback):
289292 await self ._gather_one_sample ()
290293 logging .debug ("Recaulculating simulation with new setpoints." )
291294 if not self ._paused .is_set ():
292- with concurrent .futures .ProcessPoolExecutor () as pool :
293- try :
294- self ._lattice_data = await self ._loop .run_in_executor (
295- pool ,
296- calculate_optics ,
297- self ._at_lat ,
298- self ._rp ,
299- self ._linopt_function ,
300- self ._disable_emittance ,
301- self ._disable_chromaticity ,
302- self ._disable_radiation ,
303- )
304- except Exception as e :
305- # If an error is found while doing the calculations we dont
306- # update lattice data.
307- warn (at .AtWarning (e ), stacklevel = 1 )
308- logging .warning (
309- "PVs will not be updated due to simulation exception"
310- )
311- continue
312- # Signal the up to date flag since the physics data is now up to
313- # date. We do this before the callback is executed in case the
314- # callback checks the flag.
315- self ._up_to_date .set ()
316- logging .debug ("Simulation up to date." )
317295 async with self ._new_data_lock :
296+ with concurrent .futures .ProcessPoolExecutor () as pool :
297+ try :
298+ self ._lattice_data = await self ._loop .run_in_executor (
299+ pool ,
300+ calculate_optics ,
301+ self ._at_lat ,
302+ self ._rp ,
303+ self ._linopt_function ,
304+ self ._disable_emittance ,
305+ self ._disable_chromaticity ,
306+ self ._disable_radiation ,
307+ )
308+ except Exception as e :
309+ # If an error is found while doing the calculations we dont
310+ # update lattice data. TODO: We currently update the pvs
311+ # anyway but this wont do anything, so could be improved
312+ warn (at .AtWarning (e ), stacklevel = 1 )
313+ logging .warning (
314+ "PVs will not be updated due to simulation exception"
315+ )
316+ continue
317+ # Signal the up to date flag since the physics data is now up to
318+ # date. We do this before the callback is executed in case the
319+ # callback checks the flag.
320+ self ._up_to_date .set ()
321+ logging .debug ("Simulation up to date." )
318322 if callback is not None :
319323 logging .debug (
320324 f"Executing callback function: { callback .__name__ } "
321325 )
322326 # For Virtac this function calls update_pvs() which gets data
323327 # from the pytac datasource to update the softioc pvs with. The
324328 # data source is sim_data_sources.py and its get_value()
325- # function waits on the wait_for_calculation() function which waits for the
326- # up_to_date flag which currently will always be set, so this
327- # process is pointless.
329+ # function waits on the wait_for_calculation() function which
330+ # waits for the up_to_date flag which currently will always be
331+ # set, so this process is pointless.
328332 await callback ()
329333 logging .debug ("Callback completed." )
330- # After this point we assume new setpoints have made the data stale. We
331- # cant clear this flag in queue_set() as the callbacks can depend on
332- # this being set.
333334
334335 def toggle_calculations (self ):
335336 """Pause or unpause the physics calculations by setting or clearing the
0 commit comments