The reason for your problem is that, at it's core, it's not threadsafe - you have a shared data value that 2 distinct things are trying to update.
[EMAIL PROTECTED] wrote: ... > from threading import Thread The following value is updated by 2 things trying to run in parallel. > c = Console.getconsole() The following value is used for communications. > turn = 0 > class timer (Thread): > def run ( self ): > global turn .... > go = True > while go: > newTime = time.time() > timeLeft[turn] -= newTime - oldTime[turn] > oldTime[turn] = newTime value that "turn" relates to here is merely read. On the surface this looks safe, but if turn changes in value between any of these 3 "reads" of the value of "turn", then it will go wrong. > c.text(3,3,minutes[0] + ':' + seconds[0]) > c.text(12,3,minutes[1] + ':' + seconds[1]) c gets updated here. > class eventMonitor (Thread): > def run ( self ): > global turn Shared data, but this is the only writer to this value. > go = True > while go: > event = c.peek() > if event != None: > c.get() ... (turn gets updated here as well, which can cause a race hazard in timer) > c.text(10,20,'1') c effectively changes in value here as well. > timer().start() > eventMonitor().start() Now you *could* introduce locks into this if you wanted. The alternative approach is to recognise that the real reason you're hitting problems is because you're using shared data, and that an alternative is to send messages between the things you're using. ie collect events from the keyboard, send them to something handling the logic, have that send a message (as you essentially do with "turn" above) to the timer logic, and then have that send a message to the display. That way, since you have explicit hand off of data you don't run the risk of your code crashing. (you also avoid a few other classes of problems :) The way this would work with Kamaelia (given I've just posted elsewhere in the thread about that) is you could build a simple pipeline as follows: Pipeline( KeyEvent(key_events = { pygame.K_SPACE: ("SPACE", "outbox")} ), ChessTurnLogic(), TimerLogic(), Ticker(background_colour=(128,48,128), render_left = 1, render_top = 1, render_right = 600, render_bottom = 200, position = (100, 300), ) ).run() This uses pygame for the display instead of the console which you're using. It takes keypresses and turns them into a message to trigger the chess turn logic to emit whose turn it is. This then feeds into somethin that manages the timer logic - which in this case emits a message (to be displayed by the ticker) about whose just finished their turn, and how much time they spent on their turn. KeyEvent and Ticker are pre-existing components. The ChessTurnLogic looks like this: class ChessTurnLogic(Axon.Component.component): def main(self): myturn, notmyturn = "white", "black" self.send(myturn, "outbox") while 1: while self.dataReady("inbox"): self.recv("inbox") myturn, notmyturn = notmyturn, myturn self.send(myturn, "outbox") if not self.anyReady(): self.pause() yield 1 The Timer Logic looks like this: class TimerLogic(Axon.Component.component): def main(self): times_info = {} player = None while 1: while self.dataReady("inbox"): new_player = self.recv("inbox") now = time.time() if player is not None: (total, last) = times_info[player] total = total + (now - last) times_info[player] = (total, now) self.send(player + " " + str(total) + "\n\n", "outbox") player = new_player try: (total, last) = times_info[player] times_info[player] = (total, now) except KeyError: times_info[player] = (0, now) if not self.anyReady(): self.pause() yield 1 There's probably shorter ways of dealing with the timer logic, but it'll also work for a draughts (checkers) logic component: class DraughtsTurnLogic(Axon.Component.component): def main(self): myturn, notmyturn = "black", "white" self.send(myturn, "outbox") while 1: while self.dataReady("inbox"): self.recv("inbox") myturn, notmyturn = notmyturn, myturn self.send(myturn, "outbox") if not self.anyReady(): self.pause() yield 1 Or indeed a game where there are more than 2 players. (Which is a nice sideeffect of decoupling your code like this) The full thing including imports looks like this for reference: #!/usr/bin/python import Axon import time import pygame from Kamaelia.Chassis.Pipeline import Pipeline from Kamaelia.UI.Pygame.Ticker import Ticker from Kamaelia.UI.Pygame.KeyEvent import KeyEvent class ChessTurnLogic(Axon.Component.component): def main(self): myturn, notmyturn = "white", "black" self.send(myturn, "outbox") while 1: while self.dataReady("inbox"): self.recv("inbox") myturn, notmyturn = notmyturn, myturn self.send(myturn, "outbox") if not self.anyReady(): self.pause() yield 1 class TimerLogic(Axon.Component.component): def main(self): times_info = {} player = None while 1: while self.dataReady("inbox"): new_player = self.recv("inbox") now = time.time() if player is not None: (total, last) = times_info[player] total = total + (now - last) times_info[player] = (total, now) self.send(player + " " + str(total) + "\n\n", "outbox") player = new_player try: (total, last) = times_info[player] times_info[player] = (total, now) except KeyError: times_info[player] = (0, now) if not self.anyReady(): self.pause() yield 1 Pipeline( KeyEvent(key_events = { pygame.K_SPACE: ("SPACE", "outbox")} ), ChessTurnLogic(), TimerLogic(), Ticker(background_colour=(128,48,128), render_left = 1, render_top = 1, render_right = 600, render_bottom = 200, position = (100, 300), ) ).run() (I've tested the above code BTW. It's not pretty, but it works :). Prettiness could be added in all sorts of ways though :-) Regards, Michael. -- Kamaelia Project Lead/Dust Puppy http://kamaelia.sourceforge.net/Home http://yeoldeclue.com/blog -- http://mail.python.org/mailman/listinfo/python-list