Skip to content

Commit

Permalink
Performance improvement
Browse files Browse the repository at this point in the history
- *** performance improvement:
      digital inputs, switches and buttons now set in separate threads in order to NOT wait until "slow file handling" is done before doing the next file handling
      to set the signals to zero or one.
      Note: sill, for some reason the "overall" performance improvement is not so big.
      Added __thread_set_one/zero() and __set_one/zero().
- BUG corrected: call to self.clock.updateGuiDefs() added where missing  # NOTE: self.CLOCK_PERIOD_SEC is set within this call
- BUG corrected: initialization of class variables now completely inside __init__()
- CLOCK_PERIOD_SEC removed as argument to some object creations as not needed (leds, digital_outputs)
- several small improvements
  • Loading branch information
ClarkFieseln committed Aug 17, 2022
1 parent cdb3772 commit de376f5
Show file tree
Hide file tree
Showing 9 changed files with 280 additions and 173 deletions.
128 changes: 103 additions & 25 deletions python/hw_sim_fwk/buttons.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,28 +13,35 @@
FILE_NAME_BTN_HIGH = []
FILE_NAME_BTN_LOW = []
BUTTON_PERIOD_SEC = None
# NOTE: we use oclock.Event.wait(timeout) i.o. time.sleep(timeout) otherwise the main thread is blocked.
# The following event is never set, its only used to wait on it up to timeout and not block the main thread.
evt_wake_up = oclock.Event()



class buttons:
##############
CLOCK_PERIOD_SEC = None
__event = None
__evt_all_btns_set = oclock.Event()
__wait_btn_set = 0 # count nr. of buttons yet to be set in thread..
toggle_button = True # TODO: create getter/setter
# events
# TODO: getter/setter?
evt_set_button_on = []
evt_set_button_off = []
# to avoid polling:
evt_set_button_on_or_off = []
# NOTE: __evt_set_one[] and __evt_set_one [] need to be declared even if BUTTON_TOGGLE_AUTO is currently False
# if configuration.BUTTON_TOGGLE_AUTO:
__evt_set_one = []
__evt_set_zero = []

def __init__(self, event, CLOCK_PERIOD_SEC_ARG):
logging.info('init buttons')
self.__event = event
self.CLOCK_PERIOD_SEC = CLOCK_PERIOD_SEC_ARG
if configuration.BUTTON_TOGGLE_AUTO:
for i in range(configuration.NR_BUTTONS):
self.__evt_set_one.append(oclock.Event())
self.__evt_set_zero.append(oclock.Event())
self.updateGuiDefs()
self.createTempFiles() # TODO: __createTempFiles() as private method ???
# create events
Expand All @@ -56,6 +63,14 @@ def __init__(self, event, CLOCK_PERIOD_SEC_ARG):
button_thread = threading.Thread(name=thread_name, target=self.thread_button,
args=(thread_name, i,))
button_thread.start()
else:
for i in range(configuration.NR_BUTTONS):
thread_name = "__thread_set_one_" + str(i)
thread_set_one = threading.Thread(name=thread_name, target=self.__thread_set_one, args=(thread_name, i))
thread_set_one.start()
thread_name = "__thread_set_zero_" + str(i)
thread_set_zero = threading.Thread(name=thread_name, target=self.__thread_set_zero, args=(thread_name, i))
thread_set_zero.start()

def updateGuiDefs(self):
global FILE_NAME_BTN_HIGH
Expand Down Expand Up @@ -84,36 +99,99 @@ def createTempFiles(self):
f = open(FILE_NAME_BTN_LOW[i], "w+")
f.close()

# Manage file-handling in a separate thread.
# Therefore, we have no blocking issues when different files are handled sequentially.
# This brings a "huge" performance improvement!
# TODO: investigate if it is possible to set DIs faster.
# Why does it take so much (1ms?) to rename/remove a file in Win11 ?
def __thread_set_one(self, name, i):
logging.info("Thread %s: starting", name)
# thread loop
while self.__event.evt_close_app.is_set() == False:
# blocking call
self.__evt_set_one[i].wait()
self.__evt_set_one[i].clear()
if os.path.isfile(FILE_NAME_BTN_LOW[i]):
renamed = False
while renamed == False:
try:
os.replace(FILE_NAME_BTN_LOW[i], FILE_NAME_BTN_HIGH[i])
renamed = True
except:
logging.warning("File cannot be renamed, we try again. File = " + FILE_NAME_BTN_LOW[i])
else:
created = False
while created == False:
try:
f = open(FILE_NAME_BTN_HIGH[i], "w+")
f.close()
created = True
except:
# logging.warning("File cannot be created, we try again. File = " + FILE_NAME_BTN_HIGH[i])
logging.debug("File cannot be created, we try again. File = " + FILE_NAME_BTN_HIGH[i])
# all synchronous DIs within this clock cycle already set?
self.__wait_btn_set = self.__wait_btn_set - 1
if self.__wait_btn_set == 0:
# inform calling function which in turn was called in scheduler
self.__evt_all_btns_set.set()
logging.info("Thread %s: finished!", name)

# Manage file-handling in a separate thread.
# Therefore, we have no blocking issues when different files are handled sequentially.
# This brings a "huge" performance improvement!
# TODO: investigate if it is possible to set files faster.
# Why does it take so much (1ms?) to rename/remove a file in Win11 ?
def __thread_set_zero(self, name, i):
logging.info("Thread %s: starting", name)
# thread loop
while self.__event.evt_close_app.is_set() == False:
# blocking call
self.__evt_set_zero[i].wait()
self.__evt_set_zero[i].clear()
if os.path.isfile(FILE_NAME_BTN_HIGH[i]):
renamed = False
while renamed == False:
try:
os.replace(FILE_NAME_BTN_HIGH[i], FILE_NAME_BTN_LOW[i])
renamed = True
except:
logging.warning("File cannot be renamed, we try again. File = " + FILE_NAME_BTN_HIGH[i])
else:
created = False
while created == False:
try:
f = open(FILE_NAME_BTN_LOW[i], "w+")
f.close()
created = True
except:
# logging.warning("File cannot be created, we try again. File = " + FILE_NAME_BTN_LOW[i])
logging.debug("File cannot be created, we try again. File = " + FILE_NAME_BTN_LOW[i])
# all synchronous DIs within this clock cycle already set?
self.__wait_btn_set = self.__wait_btn_set - 1
if self.__wait_btn_set == 0:
# inform calling function which in turn was called in scheduler
self.__evt_all_btns_set.set()
logging.info("Thread %s: finished!", name)

def do_button(self):
if self.toggle_button == False:
for i in range(configuration.NR_BUTTONS):
if os.path.isfile(FILE_NAME_BTN_HIGH[i]):
renamed = False
while renamed == False:
try:
os.replace(FILE_NAME_BTN_HIGH[i],FILE_NAME_BTN_LOW[i])
renamed = True
except:
logging.warning("File cannot be renamed, we try again. File = "+FILE_NAME_BTN_HIGH[i])
else:
f = open(FILE_NAME_BTN_LOW[i], "w+")
f.close()
self.__wait_btn_set = self.__wait_btn_set + 1
self.__evt_set_zero[i].set()
logging.debug("Buttons set to LOW (auto)")
else:
for i in range(configuration.NR_BUTTONS):
if os.path.isfile(FILE_NAME_BTN_LOW[i]):
renamed = False
while renamed == False:
try:
os.replace(FILE_NAME_BTN_LOW[i],FILE_NAME_BTN_HIGH[i])
renamed = True
except:
logging.warning("File cannot be renamed, we try again. File = "+FILE_NAME_BTN_LOW[i])
else:
f = open(FILE_NAME_BTN_HIGH[i], "w+")
f.close()
self.__wait_btn_set = self.__wait_btn_set + 1
self.__evt_set_one[i].set()
logging.debug("Buttons set to HIGH (auto)")
# toggle button
self.toggle_button = not self.toggle_button
# wait until all buttons have been set in the threads..
# this assures that "synchronous" buttons are set within the current clock cycle
if self.__wait_btn_set > 0:
self.__evt_all_btns_set.wait()
# update GUI
# self.__event.evt_gui_button_update.set()

def thread_button(self, name, i):
logging.info("Thread %s(%s): starting", name, str(i))
Expand Down
Loading

0 comments on commit de376f5

Please sign in to comment.