threaded_completer.py 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. #!/usr/bin/env python
  2. #
  3. # Copyright (C) 2011, 2012 Strahinja Val Markovic <val@markovic.io>
  4. #
  5. # This file is part of YouCompleteMe.
  6. #
  7. # YouCompleteMe is free software: you can redistribute it and/or modify
  8. # it under the terms of the GNU General Public License as published by
  9. # the Free Software Foundation, either version 3 of the License, or
  10. # (at your option) any later version.
  11. #
  12. # YouCompleteMe is distributed in the hope that it will be useful,
  13. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. # GNU General Public License for more details.
  16. #
  17. # You should have received a copy of the GNU General Public License
  18. # along with YouCompleteMe. If not, see <http://www.gnu.org/licenses/>.
  19. import abc
  20. from threading import Thread, Event
  21. from ycm.completers.completer import Completer
  22. class ThreadedCompleter( Completer ):
  23. def __init__( self ):
  24. super( ThreadedCompleter, self ).__init__()
  25. self._query_ready = Event()
  26. self._candidates_ready = Event()
  27. self._candidates = None
  28. self._start_completion_thread()
  29. def _start_completion_thread( self ):
  30. self._completion_thread = Thread( target=self.SetCandidates )
  31. self._completion_thread.daemon = True
  32. self._completion_thread.start()
  33. def CandidatesForQueryAsyncInner( self, query, start_column ):
  34. self._candidates = None
  35. self._candidates_ready.clear()
  36. self._query = query
  37. self._start_column = start_column
  38. self._query_ready.set()
  39. def AsyncCandidateRequestReadyInner( self ):
  40. return WaitAndClearIfSet( self._candidates_ready, timeout=0.005 )
  41. def CandidatesFromStoredRequestInner( self ):
  42. return self._candidates or []
  43. @abc.abstractmethod
  44. def ComputeCandidates( self, query, start_column ):
  45. pass
  46. def SetCandidates( self ):
  47. while True:
  48. try:
  49. WaitAndClearIfSet( self._query_ready )
  50. self._candidates = self.ComputeCandidates( self._query,
  51. self._start_column )
  52. except:
  53. self._query_ready.clear()
  54. self._candidates = []
  55. self._candidates_ready.set()
  56. def WaitAndClearIfSet( event, timeout=None ):
  57. """Given an |event| and a |timeout|, waits for the event a maximum of timeout
  58. seconds. After waiting, clears the event if it's set and returns the state of
  59. the event before it was cleared."""
  60. # We can't just do flag_is_set = event.wait( timeout ) because that breaks on
  61. # Python 2.6
  62. event.wait( timeout )
  63. flag_is_set = event.is_set()
  64. if flag_is_set:
  65. event.clear()
  66. return flag_is_set