gthread.py 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  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. from core.gcmd import DecodeString
  17. class gThread(threading.Thread, wx.EvtHandler):
  18. """Thread for various backends"""
  19. requestId = 0
  20. def __init__(self, requestQ=None, resultQ=None, **kwds):
  21. wx.EvtHandler.__init__(self)
  22. self.terminate = False
  23. threading.Thread.__init__(self, **kwds)
  24. if requestQ is None:
  25. self.requestQ = Queue.Queue()
  26. else:
  27. self.requestQ = requestQ
  28. if resultQ is None:
  29. self.resultQ = Queue.Queue()
  30. else:
  31. self.resultQ = resultQ
  32. self.setDaemon(True)
  33. self.Bind(EVT_CMD_DONE, self.OnDone)
  34. self.start()
  35. def Run(self, *args, **kwds):
  36. """Run command in queue
  37. :param args: unnamed command arguments
  38. :param kwds: named command arguments, keyword 'callable'
  39. represents function to be run, keyword 'ondone'
  40. represents function to be called after the
  41. callable is done
  42. :return: request id in queue
  43. """
  44. gThread.requestId += 1
  45. self.requestQ.put((gThread.requestId, args, kwds))
  46. return gThread.requestId
  47. def GetId(self):
  48. """Get id for next command"""
  49. return gThread.requestId + 1
  50. def SetId(self, id):
  51. """Set starting id"""
  52. gThread.requestId = id
  53. def run(self):
  54. while True:
  55. requestId, args, kwds = self.requestQ.get()
  56. for key in ('callable', 'ondone', 'userdata'):
  57. if key in kwds:
  58. vars()[key] = kwds[key]
  59. del kwds[key]
  60. else:
  61. vars()[key] = None
  62. requestTime = time.time()
  63. ret = None
  64. exception = None
  65. time.sleep(.01)
  66. if self.terminate:
  67. return
  68. ret = vars()['callable'](*args, **kwds)
  69. if self.terminate:
  70. return
  71. # except Exception as e:
  72. # exception = e;
  73. self.resultQ.put((requestId, ret))
  74. event = wxCmdDone(ondone=vars()['ondone'],
  75. kwds=kwds,
  76. args=args, # TODO expand args to kwds
  77. ret=ret,
  78. exception=exception,
  79. userdata=vars()['userdata'],
  80. pid=requestId)
  81. # send event
  82. wx.PostEvent(self, event)
  83. def OnDone(self, event):
  84. if event.ondone:
  85. event.ondone(event)
  86. def Terminate(self, terminate=True):
  87. """Abort command(s)"""
  88. self.terminate = terminate