Skip to content
This repository has been archived by the owner on Jun 19, 2022. It is now read-only.

Commit

Permalink
Merge pull request #46 from bossjones/feature-threadmanager
Browse files Browse the repository at this point in the history
WIP: gitignore and initial commit to threadmanager etc
  • Loading branch information
bossjones authored Mar 26, 2017
2 parents 09a1ff7 + b76b928 commit 015af56
Show file tree
Hide file tree
Showing 10 changed files with 771 additions and 107 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -79,3 +79,4 @@ sphinxbase
.DS_Store
*.DS_Store
*.DS_Store*
listener.py.diff
6 changes: 6 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,9 @@ This package was created with Cookiecutter_ and the `audreyr/cookiecutter-pypack

.. _Cookiecutter: https://github.com/audreyr/cookiecutter
.. _`audreyr/cookiecutter-pypackage`: https://github.com/audreyr/cookiecutter-pypackage


INSTALL
--------

* Fill this out soon
98 changes: 71 additions & 27 deletions scarlett_os/listener.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@

from scarlett_os.utility.dbus_utils import DbusSignalHandler
from scarlett_os.utility.dbus_runner import DBusRunner
from scarlett_os.utility.threadmanager import SuspendableThread

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -126,31 +127,23 @@ def get_loop_thread():
_shared_loop_thread.start()
return _shared_loop_thread

# def stop_loop_thread():
# """Get the shared main-loop thread.
# """
# global _shared_loop_thread
# with _loop_thread_lock:
# if _shared_loop_thread:
# # Start a new thread.
# _shared_loop_thread = MainLoopThread()
# _shared_loop_thread.start()
# return _shared_loop_thread

# NOTE: doc updated via
# https://github.com/Faham/emophiz/blob/15612aaf13401201100d67a57dbe3ed9ace5589a/emotion_engine/dependencies/src/sensor_lib/SensorLib.Tobii/Software/tobiisdk-3.0.2-Win32/Win32/Python26/Modules/tobii/sdk/mainloop.py


class MainLoopThread(threading.Thread):
"""A daemon thread encapsulating a Gobject main loop.
A mainloop is used by all asynchronous objects to defer handlers and callbacks to. The function run() blocks until the function quit() has been called (and all queued handlers have been executed). The run() function will then execute all the handlers in order.
"""
A daemon thread encapsulating a Gobject main loop.
A mainloop is used by all asynchronous objects to defer
handlers and callbacks to. The function run() blocks until
the function quit() has been called
(and all queued handlers have been executed).
The run() function will then execute all the handlers in order.
"""

def __init__(self):
super(MainLoopThread, self).__init__()
self.__loop = GObject.MainLoop()
self.__daemon = True
self.daemon = True

def run(self):
try:
Expand All @@ -162,26 +155,77 @@ def run(self):
print('MainLoopThread finished ...')
return

@property
def loop(self, loop):
def get_loop(self):
return self.__loop

@loop.setter
def loop(self, loop):
def set_loop(self, loop):
self.__loop = loop

@property
def daemon(self, daemon):
return self.__daemon

@daemon.setter
def daemon(self, daemon):
self.__daemon = daemon
class SuspendableMainLoopThread(SuspendableThread):
"""A daemon thread encapsulating a Gobject main loop.
A mainloop is used by all asynchronous objects to defer handlers and callbacks to. The function run() blocks until the function quit() has been called (and all queued handlers have been executed). The run() function will then execute all the handlers in order.
"""

def __init__(self):
super(SuspendableMainLoopThread, self).__init__(name="SuspendableMainLoopThread")
self.daemon = True
self.__loop = GObject.MainLoop()
self.__active = False

def do_run(self):
"""
Start the :func:`GObject.MainLoop` to establish event loop.
"""
if self.__active:
return

self.__active = True

try:
self.__loop.run()
# Definition: GLib.MainLoop.get_context

# The GLib.MainContext with which the source is associated,
# or None if the context has not yet been added to a source.
# Return type: GLib.MainContext or None

# Gets the GLib.MainContext with which the source is associated.
# You can call this on a source that has been destroyed,
# provided that the GLib.MainContext it was attached to still
# exists (in which case it will return that GLib.MainContext).
# In particular, you can always call this function on the
# source returned from GLib.main_current_source().
# But calling this function on a source whose
# GLib.MainContext has been destroyed is an error.
context = self.__loop.get_context()
while self.__active:
context.iteration(False)
# Checks if any sources have pending events for the given context.
# Return True if events are pending.
if not context.pending():
time.sleep(.1)
self.emit('progress', -1, 'SuspendableMainLoopThread working interminably')
self.check_for_sleep()
except KeyboardInterrupt:
print('MainLoopThread recieved a Ctrl-C. Exiting gracefully...')
self.__active = False
self.__loop.quit()
print('MainLoopThread finished ...')
return

def get_loop(self):
return self.__loop

def set_loop(self, loop):
self.__loop = loop


class ScarlettListenerI(threading.Thread, _IdleObject):
"""
Attempt to take out all Gstreamer logic and put it in a class ouside the dbus server.
Attempt to take out all Gstreamer logic and put it in a
class ouside the dbus server.
Cancellable thread which uses gobject signals to return information
to the GUI.
"""
Expand Down
10 changes: 7 additions & 3 deletions scarlett_os/utility/gnome.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ def uri_is_valid(uri):
return bool(urlparse(uri)[0])


class DeferredSignal(object):
class DeferredSignal(object): # noqa
"""A wrapper for connecting functions to signals.
Some signals may fire hundreds of times, but only require processing
Expand Down Expand Up @@ -290,7 +290,7 @@ def is_main_thread():
return threading.current_thread().name == "MainThread"


class MainRunner(object):
class MainRunner(object): # noqa
"""Schedule a function call in the main loop from a
worker thread and wait for the result.
Expand Down Expand Up @@ -402,6 +402,8 @@ def re_escape(string, BAD="/.^$*+-?{,\\[]|()<>#=!:"):
return type(string)().join(map(needs_escape, string))


# _IdleObject etc. based on example John Stowers
# <john.stowers@gmail.com>
class _IdleObject(GObject.GObject):
"""
Override GObject.GObject to always emit signals in the main thread
Expand All @@ -412,6 +414,8 @@ def __init__(self):
GObject.GObject.__init__(self)

def emit(self, *args):
if args[0] != 'progress':
print('emit', args)
GObject.idle_add(GObject.GObject.emit, self, *args)


Expand Down Expand Up @@ -440,7 +444,7 @@ def wrapper(*args, **kwargs):
return wrapper


def trace(func):
def trace(func): # noqa
"""Tracing wrapper to log when function enter/exit happens.
:param func: Function to wrap
:type func: callable
Expand Down
Loading

0 comments on commit 015af56

Please sign in to comment.