class MediaPlayerPiFaceCAD: def __init__(self, config): """ Constructor :param config: instance of MediaPlayerConfig class """ self._config = config self._cad = pifacecad.PiFaceCAD() self._cad.lcd.blink_off() self._cad.lcd.cursor_off() self._media_player = None self._switch_listener = None self._ir_listener = None self._temp_text = None self._temp_text_Timer = None self._listeners_barrier = None self._listeners_wait_for_deactivation_thread = None self._write_info_thread = None def init(self, media_player): """ Sets up the PiFace CAD 2 module. :param media_player: instance of MediaPlayer class which is being controlled :return: None """ self._media_player = media_player # https://github.com/piface/pifacedigitalio/issues/27 self._listeners_barrier = Barrier(2) self._listeners_wait_for_deactivation_thread = Thread(target=self._switch_listener_wait_for_deactivation, args=[]) self._listeners_wait_for_deactivation_thread.setDaemon(True) self._listeners_wait_for_deactivation_thread.start() self._switch_listener = pifacecad.SwitchEventListener() self._switch_listener.register(0, pifacecad.IODIR_ON, lambda event: self._clear_and_call(media_player.prev_branch)) self._switch_listener.register(1, pifacecad.IODIR_ON, lambda event: self._clear_and_call(media_player.next_branch)) self._switch_listener.register(2, pifacecad.IODIR_ON, lambda event: media_player.volume_down()) self._switch_listener.register(3, pifacecad.IODIR_ON, lambda event: media_player.volume_up()) self._switch_listener.register(5, pifacecad.IODIR_ON, lambda event: media_player.play_pause()) self._switch_listener.register(6, pifacecad.IODIR_ON, lambda event: self._clear_and_call(media_player.prev_track)) self._switch_listener.register(7, pifacecad.IODIR_ON, lambda event: self._clear_and_call(media_player.next_track)) self._switch_listener.activate() try: self._ir_listener = pifacecad.IREventListener(self._config['NAME']) self._ir_listener.register('play_pause', lambda event: call_and_sleep(media_player.play_pause)) self._ir_listener.register('next_track', lambda event: call_and_sleep(self._clear_and_call, media_player.next_track)) self._ir_listener.register('prev_track', lambda event: call_and_sleep(self._clear_and_call, media_player.prev_track)) self._ir_listener.register('next_branch', lambda event: call_and_sleep(self._clear_and_call, media_player.next_branch)) self._ir_listener.register('prev_branch', lambda event: call_and_sleep(self._clear_and_call, media_player.prev_branch)) self._ir_listener.register('eject', lambda event: call_and_sleep(media_player.stop)) self._ir_listener.register('volume_up', lambda event: call_and_sleep(media_player.volume_up)) self._ir_listener.register('volume_down', lambda event: call_and_sleep(media_player.volume_down)) self._ir_listener.activate() except Exception: print('LIRC cannot be initialized.') self._cad.lcd.clear() self._cad.lcd.backlight_on() self._cad.lcd.write('Loading') self._write_info_thread = Thread(target=self._write_info_thread_func) self._write_info_thread.setDaemon(True) self._write_info_thread.start() def _write_info_thread_func(self): """ Meant to be run in separated thread, writes info to the display :return: None """ while self._media_player.is_running: self.write_info(self._media_player.get_current_info()) sleep(0.8) def _switch_listener_wait_for_deactivation(self): """ Meant to be run in separated thread, waits for destroy function call :return: None """ try: self._listeners_barrier.wait() except BrokenBarrierError: pass # expected self._switch_listener.deactivate() self._ir_listener.deactivate() def _clear_and_call(self, func): """ Clears the display and calls function from parameter :param func: function to be called :return: None """ self._cad.lcd.clear() func() def destroy(self): """ Deactivates the PiFace CAD 2 module :return: """ self._cad.lcd.clear() self._cad.lcd.backlight_off() self._listeners_barrier.reset() # should never wait def _reset_temp_text(self): """ Resets temporary text (first line on display) :return: None """ self._temp_text = None def set_temp_text(self, temp_text): """ Sets the temporary text for 1 second (first line on display) :param temp_text: :return: None """ self._temp_text = temp_text if self._temp_text_Timer is not None: self._temp_text_Timer.cancel() self._temp_text_Timer = Timer(1, lambda: self._reset_temp_text()) self._temp_text_Timer.start() def write_info(self, media_player_info): """ Writes info to the display :param media_player_info: instance of MediaPlayerInfo class - info to write :return: None """ first_row_text = '' if media_player_info.status == 'paused': first_row_text = 'Paused' elif media_player_info.status == 'waitingForCD': self._cad.lcd.clear() first_row_text = 'Waiting for CD' elif media_player_info.status == 'playing' and media_player_info.cur_track_info is not None: if media_player_info.cur_track_info.track_number is not None: track_list = self._media_player.current_track_list # track name track_info = track_list[media_player_info.cur_track_info.track_number] first_row_text = track_info.artist + ' - ' + track_info.title # track count total_tracks = len(track_list) cur_track = media_player_info.cur_track_info.track_number + 1 track_str_len = len(str(cur_track)) + len(str(total_tracks)) + 1 self._cad.lcd.set_cursor(9, 1) if track_str_len < 7: for i in range(0, 7 - track_str_len): self._cad.lcd.write(' ') self._cad.lcd.write(str(cur_track) + '/' + str(total_tracks)) if media_player_info.cur_track_info.cur_time is not None: # track time cur_track_time_total_millis = media_player_info.cur_track_info.cur_time cur_track_time_total_seconds = floor(cur_track_time_total_millis / 1000) cur_track_time_minutes = str(floor(cur_track_time_total_seconds / 60)) cur_track_time_seconds = str(cur_track_time_total_seconds % 60) self._cad.lcd.set_cursor(0, 1) self._cad.lcd.write(cur_track_time_minutes.zfill(2) + ':' + cur_track_time_seconds.zfill(2)) self._cad.lcd.home() if self._temp_text is not None: self._cad.lcd.write((self._temp_text + ' ')[:16]) else: self._cad.lcd.write((first_row_text + ' ')[:16]) @staticmethod def create_eject_listener(media_player): """ Creates listener to the eject button :param media_player: instance of MediaPlayer class - media player to destroy when the button is pushed :return: """ eject_listener = pifacecad.SwitchEventListener() eject_listener.register(4, pifacecad.IODIR_ON, lambda event: media_player.stop()) eject_listener.activate() return eject_listener
class TestWindowCreator(object): ''' Creates and cleans up windows to use for testing. ''' def __init__(self): ''' Constructor Attributes: windows (list): Holds references to the Frames from wxPython created for testing. ''' self.windows = [] self._syncBarrier = Barrier(2, timeout = 5) self._nextTitleNumber = 1 self._wxApp = None self._wxThread = None def create(self, titleBase = 'TestWindow', numWindows = 1): ''' Creates operating system windows (Frames in wxPython). Adds them to the list in the public 'windows' property. Every calls to create() should eventually end in a call to destroy_all(). This method cannot be called twice without a call to destroy_all() after the first call. Args: titleBase (Optional[str]): The left part of the created window titles. A number is added to the end (right) of the base title. Default is "TestWindow". numWindows (Optional[int]): The number of windows to create. Default is 1. Raises: RuntimeError: If two calls are made to create() without a destroy_all() call between them. ''' if self._wxApp: raise RuntimeError('Caught attempt to call create() a second ' 'time without first calling destroy_all().') self._wxApp = wx.App(False) # Create the windows (Frames) and add them to the public # windows list. for i in range(0, numWindows): windowTitle = titleBase + str(self._nextTitleNumber) self.windows.append( wx.Frame(None, wx.ID_ANY, windowTitle) ) self.windows[i].Show() self._nextTitleNumber += 1 # Run the wxPython main loop in a different thread. # One reason is that it loops indefinitely and would block # other code from running in the main thread. def wx_creation_thread_target(): nonlocal self self._wxApp.MainLoop() # Start the wxPython thread as a daemon so it should exit # even if the main thread unexpectedly exits first. self._wxThread = Thread( target = wx_creation_thread_target, daemon = True ) self._wxThread.start() # _Thread synchronization 1_ # Make sure the wxPython thread waits in the barrier after # processing the window (Frame) creation. wx.CallAfter(self._syncBarrier.wait) # Make sure this main thread waits in the barrier until the # wxPython thread is finished with the window (Frame) creation. self._syncBarrier.wait() # We synchronized at the barrier. Reset the barrier for next time. self._syncBarrier.reset() def destroy_all(self): ''' Destroys all created windows (wxPython Frames) and the wxPython App object. Does not reset the window title numbers. Note: As of 2015-6, this method doesn't actually work correctly. The spawned wxPython threads and windows only die when the main thread dies. ''' # Destroy the windows (Frames) in the wxPython thread. for window in self.windows: window.Destroy() wx.Exit() # We need some way to wake up the wxPython thread and tell it # to die, but an easy way does not seem to exist yet. #wx.WakeUpMainThread() # Empty the public list of windows. self.windows.clear() # Mark the wxPython App and thread as killed. self._wxApp = None self._wxThread = None
from threading import Condition,Thread,Lock,Event,Barrier import threading import logging FORMAT= '%(asctime)s %(threadName)s %(thread)d %(message)s' logging.basicConfig(format=FORMAT,level=logging.INFO) bar = Barrier(3) #number of parties,every 3 threads will start work def worker(bar:Barrier): logging.info("I am working-Number of waiting: {}".format(bar.n_waiting)) # numbers of threads stuck at barrier: once it;s 3, it will start try: bar.wait() # if timeout, barrier will abort and broken except threading.BrokenBarrierError: logging.info('Broken Error') logging.info("Job done - Number of waiting: {}".format(bar.n_waiting)) for i in range(10): #10 threads if i ==2 : bar.abort() #abort: barrier is broken. if i == 4: bar.reset() #reset barrier Thread(target=worker,args=(bar,),name='Barrier').start() print('=====end========')
class BarrierDemo(Thread): def __init__(self, name, b): Thread.__init__(self) self.name = name self.b = b def run(self): print("Thread name : ", self.name) sleep(1) print("Parties (number of threads) : ", b.parties) sleep(2) print( "n_waiting (The number of threads currently waiting in the barrier) : ", b.n_waiting) b.wait() if __name__ == "__main__": b = Barrier(3) t1 = BarrierDemo("Thread-1", b) t2 = BarrierDemo("Thread-2", b) t1.start() sleep(1) t2.start() b.wait() print("Barrier Broken (True if barrier is broken): ", b.broken) sleep(1) b.reset() print("n_waiting after barrier.reset() call : ", b.n_waiting) b.abort() print("Barrier Aborted")
class SimulationMaster: def __init__(self, n_threads=4, initial_port=19997, q_table_version=0, batch_size=None, learner=None, explorer=None): self.barrier = Barrier(n_threads + 1, timeout=720) self.n_threads = n_threads self.initial_port = initial_port self.batch_size = batch_size self.controller = MyActionValueTable(q_table_version) if learner is None: self.learner = Q(0.5, 0.9) else: self.learner = learner if explorer is None: self.explorer = self.learner.explorer = EpsilonGreedyExplorer(0.2, 0.998) else: self.explorer = self.learner.explorer = explorer self.agent = LearningAgent(self.controller, self.learner) # Logger initialization self.logger = logging.getLogger('master_logger') self.logger.setLevel(logging.DEBUG) self.logger.addHandler(logging.FileHandler(Utils.DATA_PATH + 'learning-tables/master.log')) self.failed_simulations = [] self.n_episodes = 0 self.simulations = [] self.initialize_simulations() def initialize_simulations(self): self.simulations = [] for i in range(self.n_threads): if self.batch_size is not None: self.simulations.append(Simulation(self, self.initial_port + i, self.batch_size)) else: self.simulations.append(Simulation(self, self.initial_port + i)) def get_action(self, observation): action = self.controller.activate(observation) action = self.explorer.activate(observation, action) return action def add_observation(self, obs): """ Adds observation in the agent memory :param obs: 3 dimensional vector containing [observation, action, reward] """ self.agent.integrateObservation(obs[0]) self.agent.lastaction = obs[1] self.agent.giveReward(obs[2]) def update_q_table(self): """ Updates the q table with the new simulators observations """ for sim in self.simulations: for trace in sim.traces: for obs in trace: self.add_observation(obs) self.agent.learn() self.agent.reset() self.n_episodes += 1 sim.traces.clear() if self.explorer.epsilon > 0.1: self.explorer.epsilon=self.explorer.epsilon*self.explorer.decay if self.learner.alpha > 0.1: self.learner.alpha *= 0.999 self.logger.info('new epsilon: {}'.format(self.explorer.epsilon)) self.logger.info('new alpha: {}'.format(self.learner.alpha)) self.logger.info('n episodes: {}'.format(self.n_episodes)) def save_t_table(self): """ Saves t tables, one for each thread """ for sim in self.simulations: sim.save_t_table() def run(self): self.controller.initialize(self.agent) for sim in self.simulations: sim.start() counter = 0 while True: try: self.barrier.wait() # wait until all simulations are done self.update_q_table() self.save_t_table() self.barrier.wait() # Free simulations threads and start a new cycle # Counter to avoid to save q-table too often if counter == 5: self.controller.save() counter = 0 else: counter += 1 while self.failed_simulations: sim = self.failed_simulations.pop() self.restart_simulation(sim) except BrokenBarrierError as e: self.logger.error('Broken Barrier Error Occurred') for sim in self.simulations: sim.stop() for sim in self.simulations: sim.join() del self.simulations self.initialize_simulations() self.barrier.reset() self.failed_simulations.clear() for sim in self.simulations: sim.start() def restart_simulation(self, simulation): self.logger.info('Restarting simulation with port {}'.format(simulation.port)) self.simulations.remove(simulation) new_simulation = Simulation(self, simulation.port) self.simulations.append(new_simulation) new_simulation.start() del simulation