This is my render_GET function in class inherited from resource.Resource in twisted HTTP server:
def render_GET(self, request):
file = request.args['file'][0]
altitude, azimuth, distance = request.args['position'][0].split(",")
self.update_render(file, altitude, azimuth, distance, request.args['clientID'][0])
# update_render() starts a thread that contacts this server again and POSTs data once done
self.add_client(request.args['clientID'][0])
while not self.client_data[request.args['clientID'][0]]:
# I GET STUCK HERE - the thread CANT send data to this dict since server is locked in this loop
time.sleep(0.5)
return "DONE"
What happens is that I need the twisted server to wait until function update_render does something (this function is asynchronous, so by calling self.update_render() I just start it, not sure when the actual data is written. The return data of update_render() is written in self.client_data dict.
I need to detect the content of this dict in a loop BUT I am stuck there – it seems the server is locked in this loop BUT I need it to respond to other clients (they asynchronously fill self.client_data)
You never want to write a while loop like that in a Twisted-using application.
Ideally, you want a better API than
update_render– one that returns a Deferred. A Deferred gives you a uniform, composable, convenient API for managing callbacks. Callbacks are fairly central to programming with Twisted.update_rendershould use theDeferred‘scallbackmethod once it gets the client data – instead of putting it intoself.client_data. By using theDeferred, it plays nicely in the event-driven system of Twisted. A callback you (the caller) attach to theDeferredcan send the result to the client.Twisted Web has a slight quirk in that you’ll need to return
twisted.web.server.NOT_DONE_YETfrom therender_GETmethod to let the server know that the response is forthcoming.Have a look at Twisted Web In 60 Seconds for some examples of asynchronously generating responses.