hydrus/include/HydrusThreading.py

304 lines
7.5 KiB
Python
Raw Normal View History

2015-04-29 19:20:35 +00:00
import HydrusExceptions
2014-05-21 21:37:35 +00:00
import Queue
import threading
import time
import traceback
2015-03-25 22:04:19 +00:00
import HydrusData
import HydrusGlobals
2015-09-16 18:11:00 +00:00
import os
2014-05-21 21:37:35 +00:00
2015-09-16 18:11:00 +00:00
THREADS_TO_THREAD_INFO = {}
THREAD_INFO_LOCK = threading.Lock()
def GetThreadInfo( thread = None ):
if thread is None:
thread = threading.current_thread()
with THREAD_INFO_LOCK:
if thread not in THREADS_TO_THREAD_INFO:
thread_info = {}
thread_info[ 'shutting_down' ] = False
THREADS_TO_THREAD_INFO[ thread ] = thread_info
return THREADS_TO_THREAD_INFO[ thread ]
def IsThreadShuttingDown():
if HydrusGlobals.view_shutdown:
return True
thread_info = GetThreadInfo()
return thread_info[ 'shutting_down' ]
def ShutdownThread( thread ):
thread_info = GetThreadInfo( thread )
thread_info[ 'shutting_down' ] = True
2014-05-21 21:37:35 +00:00
class DAEMON( threading.Thread ):
2015-08-26 21:18:39 +00:00
def __init__( self, controller, name, period = 1200 ):
2014-05-21 21:37:35 +00:00
threading.Thread.__init__( self, name = name )
2015-08-26 21:18:39 +00:00
self._controller = controller
2014-05-21 21:37:35 +00:00
self._name = name
self._event = threading.Event()
2015-08-26 21:18:39 +00:00
self._controller.sub( self, 'wake', 'wake_daemons' )
2015-09-16 18:11:00 +00:00
self._controller.sub( self, 'shutdown', 'shutdown' )
def shutdown( self ):
ShutdownThread( self )
self.wake()
2014-05-21 21:37:35 +00:00
2015-08-26 21:18:39 +00:00
def wake( self ):
self._event.set()
2014-05-21 21:37:35 +00:00
class DAEMONQueue( DAEMON ):
2015-08-26 21:18:39 +00:00
def __init__( self, controller, name, callable, queue_topic, period = 10 ):
2014-05-21 21:37:35 +00:00
2015-08-26 21:18:39 +00:00
DAEMON.__init__( self, controller, name )
2014-05-21 21:37:35 +00:00
self._callable = callable
self._queue = Queue.Queue()
self._queue_topic = queue_topic
self._period = period
2015-08-26 21:18:39 +00:00
self._controller.sub( self, 'put', queue_topic )
2014-05-21 21:37:35 +00:00
self.start()
def put( self, data ): self._queue.put( data )
def run( self ):
time.sleep( 3 )
while True:
while self._queue.empty():
2015-09-16 18:11:00 +00:00
if IsThreadShuttingDown(): return
2014-05-21 21:37:35 +00:00
self._event.wait( self._period )
self._event.clear()
items = []
while not self._queue.empty(): items.append( self._queue.get() )
2015-03-04 22:44:32 +00:00
try:
2015-11-04 22:30:28 +00:00
self._callable( self._controller, items )
2015-03-04 22:44:32 +00:00
2015-04-29 19:20:35 +00:00
except HydrusExceptions.ShutdownException:
return
2015-03-04 22:44:32 +00:00
except Exception as e:
2015-03-25 22:04:19 +00:00
HydrusData.ShowException( e )
2015-03-04 22:44:32 +00:00
2014-05-21 21:37:35 +00:00
class DAEMONWorker( DAEMON ):
2016-11-30 20:24:17 +00:00
def __init__( self, controller, name, callable, topics = None, period = 3600, init_wait = 3 ):
2016-02-17 22:06:47 +00:00
if topics is None: topics = []
DAEMON.__init__( self, controller, name )
self._callable = callable
self._topics = topics
self._period = period
2016-11-30 20:24:17 +00:00
self._init_wait = init_wait
2016-02-17 22:06:47 +00:00
for topic in topics: self._controller.sub( self, 'set', topic )
self.start()
def run( self ):
2016-11-30 20:24:17 +00:00
self._event.wait( self._init_wait )
2016-02-17 22:06:47 +00:00
while True:
if IsThreadShuttingDown(): return
try:
self._callable( self._controller )
except HydrusExceptions.ShutdownException:
return
except Exception as e:
HydrusData.ShowText( 'Daemon ' + self._name + ' encountered an exception:' )
HydrusData.ShowException( e )
if IsThreadShuttingDown(): return
self._event.wait( self._period )
self._event.clear()
def set( self, *args, **kwargs ): self._event.set()
class DAEMONBigJobWorker( DAEMON ):
2015-12-30 23:44:09 +00:00
def __init__( self, controller, name, callable, topics = None, period = 3600, init_wait = 3, pre_callable_wait = 3 ):
2015-03-25 22:04:19 +00:00
if topics is None: topics = []
2014-05-21 21:37:35 +00:00
2015-08-26 21:18:39 +00:00
DAEMON.__init__( self, controller, name )
2014-05-21 21:37:35 +00:00
self._callable = callable
self._topics = topics
self._period = period
self._init_wait = init_wait
2014-07-23 21:21:37 +00:00
self._pre_callable_wait = pre_callable_wait
2014-05-21 21:37:35 +00:00
2015-08-26 21:18:39 +00:00
for topic in topics: self._controller.sub( self, 'set', topic )
2014-05-21 21:37:35 +00:00
self.start()
def run( self ):
self._event.wait( self._init_wait )
while True:
2015-09-16 18:11:00 +00:00
if IsThreadShuttingDown(): return
2014-07-23 21:21:37 +00:00
2015-09-16 18:11:00 +00:00
time_to_go = ( HydrusData.GetNow() - 1 ) + self._pre_callable_wait
2015-06-17 20:01:41 +00:00
2015-09-16 18:11:00 +00:00
while not ( HydrusData.TimeHasPassed( time_to_go ) and self._controller.GoodTimeToDoBackgroundWork() ):
2014-10-29 21:39:01 +00:00
2015-09-16 18:11:00 +00:00
time.sleep( 1 )
2014-10-29 21:39:01 +00:00
2015-09-16 18:11:00 +00:00
if IsThreadShuttingDown(): return
2014-10-29 21:39:01 +00:00
2015-04-29 19:20:35 +00:00
try:
2015-11-04 22:30:28 +00:00
self._callable( self._controller )
2015-04-29 19:20:35 +00:00
except HydrusExceptions.ShutdownException:
return
2014-07-23 21:21:37 +00:00
except Exception as e:
2015-03-25 22:04:19 +00:00
HydrusData.ShowText( 'Daemon ' + self._name + ' encountered an exception:' )
2014-09-24 21:50:07 +00:00
2015-03-25 22:04:19 +00:00
HydrusData.ShowException( e )
2014-07-23 21:21:37 +00:00
2014-05-21 21:37:35 +00:00
2015-09-16 18:11:00 +00:00
if IsThreadShuttingDown(): return
2014-05-21 21:37:35 +00:00
self._event.wait( self._period )
self._event.clear()
def set( self, *args, **kwargs ): self._event.set()
2015-12-23 22:51:04 +00:00
class THREADCallToThread( DAEMON ):
2014-05-21 21:37:35 +00:00
2015-08-26 21:18:39 +00:00
def __init__( self, controller ):
2014-05-21 21:37:35 +00:00
2015-08-26 21:18:39 +00:00
DAEMON.__init__( self, controller, 'CallToThread' )
2014-05-21 21:37:35 +00:00
self._queue = Queue.Queue()
2016-07-20 19:57:10 +00:00
self._currently_working = False
def CurrentlyWorking( self ):
return self._currently_working
2014-05-21 21:37:35 +00:00
def put( self, callable, *args, **kwargs ):
self._queue.put( ( callable, args, kwargs ) )
self._event.set()
def run( self ):
while True:
while self._queue.empty():
2015-11-04 22:30:28 +00:00
if self._controller.ModelIsShutdown(): return
2014-05-21 21:37:35 +00:00
self._event.wait( 1200 )
self._event.clear()
2014-05-28 21:03:24 +00:00
try:
( callable, args, kwargs ) = self._queue.get()
2016-07-20 19:57:10 +00:00
self._currently_working = True
2014-05-28 21:03:24 +00:00
callable( *args, **kwargs )
2014-06-18 21:53:48 +00:00
del callable
2015-04-29 19:20:35 +00:00
except HydrusExceptions.ShutdownException:
return
2015-03-04 22:44:32 +00:00
except Exception as e:
2015-03-25 22:04:19 +00:00
HydrusData.ShowException( e )
2015-03-04 22:44:32 +00:00
2016-07-20 19:57:10 +00:00
finally:
self._currently_working = False
2014-05-21 21:37:35 +00:00
2014-05-28 21:03:24 +00:00
time.sleep( 0.00001 )
2014-05-21 21:37:35 +00:00