gthread.py 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. """
  2. @package core.gthread
  3. @brief Threading
  4. Classes:
  5. - gthread::gThread
  6. (C) 2013-2014 by the GRASS Development Team
  7. This program is free software under the GNU General Public License
  8. (>=v2). Read the file COPYING that comes with GRASS for details.
  9. @author Stepan Turek <stepan.turek seznam.cz> (mentor: Martin Landa)
  10. """
  11. import threading
  12. import time
  13. import wx
  14. import Queue
  15. from core.gconsole import EVT_CMD_DONE, wxCmdDone
  16. class gThread(threading.Thread, wx.EvtHandler):
  17. """Thread for various backends"""
  18. requestId = 0
  19. def __init__(self, requestQ=None, resultQ=None, **kwds):
  20. wx.EvtHandler.__init__(self)
  21. self.terminate = False
  22. threading.Thread.__init__(self, **kwds)
  23. if requestQ is None:
  24. self.requestQ = Queue.Queue()
  25. else:
  26. self.requestQ = requestQ
  27. if resultQ is None:
  28. self.resultQ = Queue.Queue()
  29. else:
  30. self.resultQ = resultQ
  31. self.setDaemon(True)
  32. self.Bind(EVT_CMD_DONE, self.OnDone)
  33. self.start()
  34. def Run(self, *args, **kwds):
  35. """Run command in queue
  36. :param args: unnamed command arguments
  37. :param kwds: named command arguments, keyword 'callable'
  38. represents function to be run, keyword 'ondone'
  39. represents function to be called after the
  40. callable is done
  41. :return: request id in queue
  42. """
  43. gThread.requestId += 1
  44. self.requestQ.put((gThread.requestId, args, kwds))
  45. return gThread.requestId
  46. def GetId(self):
  47. """Get id for next command"""
  48. return gThread.requestId + 1
  49. def SetId(self, id):
  50. """Set starting id"""
  51. gThread.requestId = id
  52. def run(self):
  53. while True:
  54. requestId, args, kwds = self.requestQ.get()
  55. for key in ('callable', 'ondone', 'userdata'):
  56. if key in kwds:
  57. vars()[key] = kwds[key]
  58. del kwds[key]
  59. else:
  60. vars()[key] = None
  61. requestTime = time.time()
  62. ret = None
  63. exception = None
  64. time.sleep(.01)
  65. if self.terminate:
  66. return
  67. ret = vars()['callable'](*args, **kwds)
  68. if self.terminate:
  69. return
  70. #except Exception as e:
  71. # exception = e;
  72. self.resultQ.put((requestId, ret))
  73. event = wxCmdDone(ondone=vars()['ondone'],
  74. kwds=kwds,
  75. args=args, #TODO expand args to kwds
  76. ret=ret,
  77. exception=exception,
  78. userdata=vars()['userdata'],
  79. pid=requestId)
  80. # send event
  81. wx.PostEvent(self, event)
  82. def OnDone(self, event):
  83. if event.ondone:
  84. event.ondone(event)
  85. def Terminate(self):
  86. """Abort command(s)"""
  87. self.terminate = True