Asynchronous IPC: Initial implementation

This commit adds a mixin which sets up a modal operator which:
* Starts a subprocess
* Polls for messages from that subprocesses
This commit is contained in:
gandalf3
2017-06-29 17:46:08 -07:00
parent 2268925733
commit 9dfd58671e
4 changed files with 86 additions and 17 deletions

View File

@@ -1,21 +1,72 @@
import bpy
from multiprocessing import Process
import logging
from multiprocessing import Process, Pipe
from . import blenderpack
class PACKAGE_OT_fetch_lists(bpy.types.Operator):
bl_idname = "package.fetch_lists"
bl_label = "Update package list(s)"
class SubprocessOperatorMixin:
timer = None
# run once in invoke
def setup(self):
pass
# run on receipt of data from subprocess
def handle_response(self, resp):
pass
def __init__(self):
self.pipe = Pipe()
self.subprocess = None
def execute(self, context):
return self.invoke(context, None)
def invoke(self, context, event):
self.subprocess.start()
# we have to explicitly close the end of the pipe we are NOT using,
# otherwise no exception will be generated when the other process closes its end.
self.pipe[1].close()
wm = context.window_manager
wm.modal_handler_add(self)
self.timer = wm.event_timer_add(.01, context.window)
self.setup()
return {'RUNNING_MODAL'}
def modal(self, context, event):
print("polling")
try:
if self.pipe[0].poll():
newdata = self.pipe[0].recv()
else:
newdata = None
except EOFError:
return {'FINISHED'}
if newdata is not None:
self.handle_response(newdata)
return {'PASS_THROUGH'}
class PACKAGE_OT_fetch(SubprocessOperatorMixin, bpy.types.Operator):
bl_idname = "package.fetch"
bl_label = "Update package list(s)"
def __init__(self):
SubprocessOperatorMixin.__init__(self)
settings = bpy.context.window_manager.package_manager_settings
self.subprocess = Process(target=blenderpack.fetch, args=(settings.url, self.pipe))
def handle_response(self, resp):
print("your response:", resp)
def execute(self, context):
settings = context.window_manager.PackageManagerSettings
proc = Process(target=lambda: blenderpack.fetch(settings.url))
proc.start()
return {'FINISHED'}
def register():
bpy.utils.register_class(PACKAGE_OT_fetch_lists)
bpy.utils.register_class(PACKAGE_OT_fetch)
def unregister():
bpy.utils.unregister_class(PACKAGE_OT_fetch_lists)
bpy.utils.unregister_class(PACKAGE_OT_fetch)