##// END OF EJS Templates
Remove 5s wait on inactivity on GUI inputhook loops...
Jonah Graham -
Show More
@@ -1,175 +1,172 b''
1 # coding: utf-8
1 # coding: utf-8
2 """
2 """
3 GLUT Inputhook support functions
3 GLUT Inputhook support functions
4 """
4 """
5
5
6 #-----------------------------------------------------------------------------
6 #-----------------------------------------------------------------------------
7 # Copyright (C) 2008-2011 The IPython Development Team
7 # Copyright (C) 2008-2011 The IPython Development Team
8 #
8 #
9 # Distributed under the terms of the BSD License. The full license is in
9 # Distributed under the terms of the BSD License. The full license is in
10 # the file COPYING, distributed as part of this software.
10 # the file COPYING, distributed as part of this software.
11 #-----------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
12
12
13 # GLUT is quite an old library and it is difficult to ensure proper
13 # GLUT is quite an old library and it is difficult to ensure proper
14 # integration within IPython since original GLUT does not allow to handle
14 # integration within IPython since original GLUT does not allow to handle
15 # events one by one. Instead, it requires for the mainloop to be entered
15 # events one by one. Instead, it requires for the mainloop to be entered
16 # and never returned (there is not even a function to exit he
16 # and never returned (there is not even a function to exit he
17 # mainloop). Fortunately, there are alternatives such as freeglut
17 # mainloop). Fortunately, there are alternatives such as freeglut
18 # (available for linux and windows) and the OSX implementation gives
18 # (available for linux and windows) and the OSX implementation gives
19 # access to a glutCheckLoop() function that blocks itself until a new
19 # access to a glutCheckLoop() function that blocks itself until a new
20 # event is received. This means we have to setup the idle callback to
20 # event is received. This means we have to setup the idle callback to
21 # ensure we got at least one event that will unblock the function.
21 # ensure we got at least one event that will unblock the function.
22 #
22 #
23 # Furthermore, it is not possible to install these handlers without a window
23 # Furthermore, it is not possible to install these handlers without a window
24 # being first created. We choose to make this window invisible. This means that
24 # being first created. We choose to make this window invisible. This means that
25 # display mode options are set at this level and user won't be able to change
25 # display mode options are set at this level and user won't be able to change
26 # them later without modifying the code. This should probably be made available
26 # them later without modifying the code. This should probably be made available
27 # via IPython options system.
27 # via IPython options system.
28
28
29 #-----------------------------------------------------------------------------
29 #-----------------------------------------------------------------------------
30 # Imports
30 # Imports
31 #-----------------------------------------------------------------------------
31 #-----------------------------------------------------------------------------
32 import os
32 import os
33 import sys
33 import sys
34 import time
34 import time
35 import signal
35 import signal
36 import OpenGL.GLUT as glut
36 import OpenGL.GLUT as glut
37 import OpenGL.platform as platform
37 import OpenGL.platform as platform
38 from timeit import default_timer as clock
38 from timeit import default_timer as clock
39
39
40 #-----------------------------------------------------------------------------
40 #-----------------------------------------------------------------------------
41 # Constants
41 # Constants
42 #-----------------------------------------------------------------------------
42 #-----------------------------------------------------------------------------
43
43
44 # Frame per second : 60
44 # Frame per second : 60
45 # Should probably be an IPython option
45 # Should probably be an IPython option
46 glut_fps = 60
46 glut_fps = 60
47
47
48
48
49 # Display mode : double buffeed + rgba + depth
49 # Display mode : double buffeed + rgba + depth
50 # Should probably be an IPython option
50 # Should probably be an IPython option
51 glut_display_mode = (glut.GLUT_DOUBLE |
51 glut_display_mode = (glut.GLUT_DOUBLE |
52 glut.GLUT_RGBA |
52 glut.GLUT_RGBA |
53 glut.GLUT_DEPTH)
53 glut.GLUT_DEPTH)
54
54
55 glutMainLoopEvent = None
55 glutMainLoopEvent = None
56 if sys.platform == 'darwin':
56 if sys.platform == 'darwin':
57 try:
57 try:
58 glutCheckLoop = platform.createBaseFunction(
58 glutCheckLoop = platform.createBaseFunction(
59 'glutCheckLoop', dll=platform.GLUT, resultType=None,
59 'glutCheckLoop', dll=platform.GLUT, resultType=None,
60 argTypes=[],
60 argTypes=[],
61 doc='glutCheckLoop( ) -> None',
61 doc='glutCheckLoop( ) -> None',
62 argNames=(),
62 argNames=(),
63 )
63 )
64 except AttributeError:
64 except AttributeError:
65 raise RuntimeError(
65 raise RuntimeError(
66 '''Your glut implementation does not allow interactive sessions'''
66 '''Your glut implementation does not allow interactive sessions'''
67 '''Consider installing freeglut.''')
67 '''Consider installing freeglut.''')
68 glutMainLoopEvent = glutCheckLoop
68 glutMainLoopEvent = glutCheckLoop
69 elif glut.HAVE_FREEGLUT:
69 elif glut.HAVE_FREEGLUT:
70 glutMainLoopEvent = glut.glutMainLoopEvent
70 glutMainLoopEvent = glut.glutMainLoopEvent
71 else:
71 else:
72 raise RuntimeError(
72 raise RuntimeError(
73 '''Your glut implementation does not allow interactive sessions. '''
73 '''Your glut implementation does not allow interactive sessions. '''
74 '''Consider installing freeglut.''')
74 '''Consider installing freeglut.''')
75
75
76
76
77 #-----------------------------------------------------------------------------
77 #-----------------------------------------------------------------------------
78 # Platform-dependent imports and functions
78 # Platform-dependent imports and functions
79 #-----------------------------------------------------------------------------
79 #-----------------------------------------------------------------------------
80
80
81 if os.name == 'posix':
81 if os.name == 'posix':
82 import select
82 import select
83
83
84 def stdin_ready():
84 def stdin_ready():
85 infds, outfds, erfds = select.select([sys.stdin],[],[],0)
85 infds, outfds, erfds = select.select([sys.stdin],[],[],0)
86 if infds:
86 if infds:
87 return True
87 return True
88 else:
88 else:
89 return False
89 return False
90
90
91 elif sys.platform == 'win32':
91 elif sys.platform == 'win32':
92 import msvcrt
92 import msvcrt
93
93
94 def stdin_ready():
94 def stdin_ready():
95 return msvcrt.kbhit()
95 return msvcrt.kbhit()
96
96
97 #-----------------------------------------------------------------------------
97 #-----------------------------------------------------------------------------
98 # Callback functions
98 # Callback functions
99 #-----------------------------------------------------------------------------
99 #-----------------------------------------------------------------------------
100
100
101 def glut_display():
101 def glut_display():
102 # Dummy display function
102 # Dummy display function
103 pass
103 pass
104
104
105 def glut_idle():
105 def glut_idle():
106 # Dummy idle function
106 # Dummy idle function
107 pass
107 pass
108
108
109 def glut_close():
109 def glut_close():
110 # Close function only hides the current window
110 # Close function only hides the current window
111 glut.glutHideWindow()
111 glut.glutHideWindow()
112 glutMainLoopEvent()
112 glutMainLoopEvent()
113
113
114 def glut_int_handler(signum, frame):
114 def glut_int_handler(signum, frame):
115 # Catch sigint and print the defautl message
115 # Catch sigint and print the defautl message
116 signal.signal(signal.SIGINT, signal.default_int_handler)
116 signal.signal(signal.SIGINT, signal.default_int_handler)
117 print '\nKeyboardInterrupt'
117 print '\nKeyboardInterrupt'
118 # Need to reprint the prompt at this stage
118 # Need to reprint the prompt at this stage
119
119
120
120
121
121
122 #-----------------------------------------------------------------------------
122 #-----------------------------------------------------------------------------
123 # Code
123 # Code
124 #-----------------------------------------------------------------------------
124 #-----------------------------------------------------------------------------
125 def inputhook_glut():
125 def inputhook_glut():
126 """Run the pyglet event loop by processing pending events only.
126 """Run the pyglet event loop by processing pending events only.
127
127
128 This keeps processing pending events until stdin is ready. After
128 This keeps processing pending events until stdin is ready. After
129 processing all pending events, a call to time.sleep is inserted. This is
129 processing all pending events, a call to time.sleep is inserted. This is
130 needed, otherwise, CPU usage is at 100%. This sleep time should be tuned
130 needed, otherwise, CPU usage is at 100%. This sleep time should be tuned
131 though for best performance.
131 though for best performance.
132 """
132 """
133 # We need to protect against a user pressing Control-C when IPython is
133 # We need to protect against a user pressing Control-C when IPython is
134 # idle and this is running. We trap KeyboardInterrupt and pass.
134 # idle and this is running. We trap KeyboardInterrupt and pass.
135
135
136 signal.signal(signal.SIGINT, glut_int_handler)
136 signal.signal(signal.SIGINT, glut_int_handler)
137
137
138 try:
138 try:
139 t = clock()
139 t = clock()
140
140
141 # Make sure the default window is set after a window has been closed
141 # Make sure the default window is set after a window has been closed
142 if glut.glutGetWindow() == 0:
142 if glut.glutGetWindow() == 0:
143 glut.glutSetWindow( 1 )
143 glut.glutSetWindow( 1 )
144 glutMainLoopEvent()
144 glutMainLoopEvent()
145 return 0
145 return 0
146
146
147 while not stdin_ready():
147 while not stdin_ready():
148 glutMainLoopEvent()
148 glutMainLoopEvent()
149 # We need to sleep at this point to keep the idle CPU load
149 # We need to sleep at this point to keep the idle CPU load
150 # low. However, if sleep to long, GUI response is poor. As
150 # low. However, if sleep to long, GUI response is poor. As
151 # a compromise, we watch how often GUI events are being processed
151 # a compromise, we watch how often GUI events are being processed
152 # and switch between a short and long sleep time. Here are some
152 # and switch between a short and long sleep time. Here are some
153 # stats useful in helping to tune this.
153 # stats useful in helping to tune this.
154 # time CPU load
154 # time CPU load
155 # 0.001 13%
155 # 0.001 13%
156 # 0.005 3%
156 # 0.005 3%
157 # 0.01 1.5%
157 # 0.01 1.5%
158 # 0.05 0.5%
158 # 0.05 0.5%
159 used_time = clock() - t
159 used_time = clock() - t
160 if used_time > 5*60.0:
160 if used_time > 10.0:
161 # print 'Sleep for 5 s' # dbg
162 time.sleep(5.0)
163 elif used_time > 10.0:
164 # print 'Sleep for 1 s' # dbg
161 # print 'Sleep for 1 s' # dbg
165 time.sleep(1.0)
162 time.sleep(1.0)
166 elif used_time > 0.1:
163 elif used_time > 0.1:
167 # Few GUI events coming in, so we can sleep longer
164 # Few GUI events coming in, so we can sleep longer
168 # print 'Sleep for 0.05 s' # dbg
165 # print 'Sleep for 0.05 s' # dbg
169 time.sleep(0.05)
166 time.sleep(0.05)
170 else:
167 else:
171 # Many GUI events coming in, so sleep only very little
168 # Many GUI events coming in, so sleep only very little
172 time.sleep(0.001)
169 time.sleep(0.001)
173 except KeyboardInterrupt:
170 except KeyboardInterrupt:
174 pass
171 pass
175 return 0
172 return 0
@@ -1,114 +1,111 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """
2 """
3 Enable pyglet to be used interacive by setting PyOS_InputHook.
3 Enable pyglet to be used interacive by setting PyOS_InputHook.
4
4
5 Authors
5 Authors
6 -------
6 -------
7
7
8 * Nicolas P. Rougier
8 * Nicolas P. Rougier
9 * Fernando Perez
9 * Fernando Perez
10 """
10 """
11
11
12 #-----------------------------------------------------------------------------
12 #-----------------------------------------------------------------------------
13 # Copyright (C) 2008-2011 The IPython Development Team
13 # Copyright (C) 2008-2011 The IPython Development Team
14 #
14 #
15 # Distributed under the terms of the BSD License. The full license is in
15 # Distributed under the terms of the BSD License. The full license is in
16 # the file COPYING, distributed as part of this software.
16 # the file COPYING, distributed as part of this software.
17 #-----------------------------------------------------------------------------
17 #-----------------------------------------------------------------------------
18
18
19 #-----------------------------------------------------------------------------
19 #-----------------------------------------------------------------------------
20 # Imports
20 # Imports
21 #-----------------------------------------------------------------------------
21 #-----------------------------------------------------------------------------
22
22
23 import os
23 import os
24 import sys
24 import sys
25 import time
25 import time
26 from timeit import default_timer as clock
26 from timeit import default_timer as clock
27 import pyglet
27 import pyglet
28
28
29 #-----------------------------------------------------------------------------
29 #-----------------------------------------------------------------------------
30 # Platform-dependent imports and functions
30 # Platform-dependent imports and functions
31 #-----------------------------------------------------------------------------
31 #-----------------------------------------------------------------------------
32
32
33 if os.name == 'posix':
33 if os.name == 'posix':
34 import select
34 import select
35
35
36 def stdin_ready():
36 def stdin_ready():
37 infds, outfds, erfds = select.select([sys.stdin],[],[],0)
37 infds, outfds, erfds = select.select([sys.stdin],[],[],0)
38 if infds:
38 if infds:
39 return True
39 return True
40 else:
40 else:
41 return False
41 return False
42
42
43 elif sys.platform == 'win32':
43 elif sys.platform == 'win32':
44 import msvcrt
44 import msvcrt
45
45
46 def stdin_ready():
46 def stdin_ready():
47 return msvcrt.kbhit()
47 return msvcrt.kbhit()
48
48
49
49
50 # On linux only, window.flip() has a bug that causes an AttributeError on
50 # On linux only, window.flip() has a bug that causes an AttributeError on
51 # window close. For details, see:
51 # window close. For details, see:
52 # http://groups.google.com/group/pyglet-users/browse_thread/thread/47c1aab9aa4a3d23/c22f9e819826799e?#c22f9e819826799e
52 # http://groups.google.com/group/pyglet-users/browse_thread/thread/47c1aab9aa4a3d23/c22f9e819826799e?#c22f9e819826799e
53
53
54 if sys.platform.startswith('linux'):
54 if sys.platform.startswith('linux'):
55 def flip(window):
55 def flip(window):
56 try:
56 try:
57 window.flip()
57 window.flip()
58 except AttributeError:
58 except AttributeError:
59 pass
59 pass
60 else:
60 else:
61 def flip(window):
61 def flip(window):
62 window.flip()
62 window.flip()
63
63
64 #-----------------------------------------------------------------------------
64 #-----------------------------------------------------------------------------
65 # Code
65 # Code
66 #-----------------------------------------------------------------------------
66 #-----------------------------------------------------------------------------
67
67
68 def inputhook_pyglet():
68 def inputhook_pyglet():
69 """Run the pyglet event loop by processing pending events only.
69 """Run the pyglet event loop by processing pending events only.
70
70
71 This keeps processing pending events until stdin is ready. After
71 This keeps processing pending events until stdin is ready. After
72 processing all pending events, a call to time.sleep is inserted. This is
72 processing all pending events, a call to time.sleep is inserted. This is
73 needed, otherwise, CPU usage is at 100%. This sleep time should be tuned
73 needed, otherwise, CPU usage is at 100%. This sleep time should be tuned
74 though for best performance.
74 though for best performance.
75 """
75 """
76 # We need to protect against a user pressing Control-C when IPython is
76 # We need to protect against a user pressing Control-C when IPython is
77 # idle and this is running. We trap KeyboardInterrupt and pass.
77 # idle and this is running. We trap KeyboardInterrupt and pass.
78 try:
78 try:
79 t = clock()
79 t = clock()
80 while not stdin_ready():
80 while not stdin_ready():
81 pyglet.clock.tick()
81 pyglet.clock.tick()
82 for window in pyglet.app.windows:
82 for window in pyglet.app.windows:
83 window.switch_to()
83 window.switch_to()
84 window.dispatch_events()
84 window.dispatch_events()
85 window.dispatch_event('on_draw')
85 window.dispatch_event('on_draw')
86 flip(window)
86 flip(window)
87
87
88 # We need to sleep at this point to keep the idle CPU load
88 # We need to sleep at this point to keep the idle CPU load
89 # low. However, if sleep to long, GUI response is poor. As
89 # low. However, if sleep to long, GUI response is poor. As
90 # a compromise, we watch how often GUI events are being processed
90 # a compromise, we watch how often GUI events are being processed
91 # and switch between a short and long sleep time. Here are some
91 # and switch between a short and long sleep time. Here are some
92 # stats useful in helping to tune this.
92 # stats useful in helping to tune this.
93 # time CPU load
93 # time CPU load
94 # 0.001 13%
94 # 0.001 13%
95 # 0.005 3%
95 # 0.005 3%
96 # 0.01 1.5%
96 # 0.01 1.5%
97 # 0.05 0.5%
97 # 0.05 0.5%
98 used_time = clock() - t
98 used_time = clock() - t
99 if used_time > 5*60.0:
99 if used_time > 10.0:
100 # print 'Sleep for 5 s' # dbg
101 time.sleep(5.0)
102 elif used_time > 10.0:
103 # print 'Sleep for 1 s' # dbg
100 # print 'Sleep for 1 s' # dbg
104 time.sleep(1.0)
101 time.sleep(1.0)
105 elif used_time > 0.1:
102 elif used_time > 0.1:
106 # Few GUI events coming in, so we can sleep longer
103 # Few GUI events coming in, so we can sleep longer
107 # print 'Sleep for 0.05 s' # dbg
104 # print 'Sleep for 0.05 s' # dbg
108 time.sleep(0.05)
105 time.sleep(0.05)
109 else:
106 else:
110 # Many GUI events coming in, so sleep only very little
107 # Many GUI events coming in, so sleep only very little
111 time.sleep(0.001)
108 time.sleep(0.001)
112 except KeyboardInterrupt:
109 except KeyboardInterrupt:
113 pass
110 pass
114 return 0
111 return 0
@@ -1,170 +1,167 b''
1 # encoding: utf-8
1 # encoding: utf-8
2
2
3 """
3 """
4 Enable wxPython to be used interacive by setting PyOS_InputHook.
4 Enable wxPython to be used interacive by setting PyOS_InputHook.
5
5
6 Authors: Robin Dunn, Brian Granger, Ondrej Certik
6 Authors: Robin Dunn, Brian Granger, Ondrej Certik
7 """
7 """
8
8
9 #-----------------------------------------------------------------------------
9 #-----------------------------------------------------------------------------
10 # Copyright (C) 2008-2011 The IPython Development Team
10 # Copyright (C) 2008-2011 The IPython Development Team
11 #
11 #
12 # Distributed under the terms of the BSD License. The full license is in
12 # Distributed under the terms of the BSD License. The full license is in
13 # the file COPYING, distributed as part of this software.
13 # the file COPYING, distributed as part of this software.
14 #-----------------------------------------------------------------------------
14 #-----------------------------------------------------------------------------
15
15
16 #-----------------------------------------------------------------------------
16 #-----------------------------------------------------------------------------
17 # Imports
17 # Imports
18 #-----------------------------------------------------------------------------
18 #-----------------------------------------------------------------------------
19
19
20 import sys
20 import sys
21 import signal
21 import signal
22 import time
22 import time
23 from timeit import default_timer as clock
23 from timeit import default_timer as clock
24 import wx
24 import wx
25
25
26 from IPython.lib.inputhook import stdin_ready
26 from IPython.lib.inputhook import stdin_ready
27
27
28
28
29 #-----------------------------------------------------------------------------
29 #-----------------------------------------------------------------------------
30 # Code
30 # Code
31 #-----------------------------------------------------------------------------
31 #-----------------------------------------------------------------------------
32
32
33 def inputhook_wx1():
33 def inputhook_wx1():
34 """Run the wx event loop by processing pending events only.
34 """Run the wx event loop by processing pending events only.
35
35
36 This approach seems to work, but its performance is not great as it
36 This approach seems to work, but its performance is not great as it
37 relies on having PyOS_InputHook called regularly.
37 relies on having PyOS_InputHook called regularly.
38 """
38 """
39 try:
39 try:
40 app = wx.GetApp()
40 app = wx.GetApp()
41 if app is not None:
41 if app is not None:
42 assert wx.Thread_IsMain()
42 assert wx.Thread_IsMain()
43
43
44 # Make a temporary event loop and process system events until
44 # Make a temporary event loop and process system events until
45 # there are no more waiting, then allow idle events (which
45 # there are no more waiting, then allow idle events (which
46 # will also deal with pending or posted wx events.)
46 # will also deal with pending or posted wx events.)
47 evtloop = wx.EventLoop()
47 evtloop = wx.EventLoop()
48 ea = wx.EventLoopActivator(evtloop)
48 ea = wx.EventLoopActivator(evtloop)
49 while evtloop.Pending():
49 while evtloop.Pending():
50 evtloop.Dispatch()
50 evtloop.Dispatch()
51 app.ProcessIdle()
51 app.ProcessIdle()
52 del ea
52 del ea
53 except KeyboardInterrupt:
53 except KeyboardInterrupt:
54 pass
54 pass
55 return 0
55 return 0
56
56
57 class EventLoopTimer(wx.Timer):
57 class EventLoopTimer(wx.Timer):
58
58
59 def __init__(self, func):
59 def __init__(self, func):
60 self.func = func
60 self.func = func
61 wx.Timer.__init__(self)
61 wx.Timer.__init__(self)
62
62
63 def Notify(self):
63 def Notify(self):
64 self.func()
64 self.func()
65
65
66 class EventLoopRunner(object):
66 class EventLoopRunner(object):
67
67
68 def Run(self, time):
68 def Run(self, time):
69 self.evtloop = wx.EventLoop()
69 self.evtloop = wx.EventLoop()
70 self.timer = EventLoopTimer(self.check_stdin)
70 self.timer = EventLoopTimer(self.check_stdin)
71 self.timer.Start(time)
71 self.timer.Start(time)
72 self.evtloop.Run()
72 self.evtloop.Run()
73
73
74 def check_stdin(self):
74 def check_stdin(self):
75 if stdin_ready():
75 if stdin_ready():
76 self.timer.Stop()
76 self.timer.Stop()
77 self.evtloop.Exit()
77 self.evtloop.Exit()
78
78
79 def inputhook_wx2():
79 def inputhook_wx2():
80 """Run the wx event loop, polling for stdin.
80 """Run the wx event loop, polling for stdin.
81
81
82 This version runs the wx eventloop for an undetermined amount of time,
82 This version runs the wx eventloop for an undetermined amount of time,
83 during which it periodically checks to see if anything is ready on
83 during which it periodically checks to see if anything is ready on
84 stdin. If anything is ready on stdin, the event loop exits.
84 stdin. If anything is ready on stdin, the event loop exits.
85
85
86 The argument to elr.Run controls how often the event loop looks at stdin.
86 The argument to elr.Run controls how often the event loop looks at stdin.
87 This determines the responsiveness at the keyboard. A setting of 1000
87 This determines the responsiveness at the keyboard. A setting of 1000
88 enables a user to type at most 1 char per second. I have found that a
88 enables a user to type at most 1 char per second. I have found that a
89 setting of 10 gives good keyboard response. We can shorten it further,
89 setting of 10 gives good keyboard response. We can shorten it further,
90 but eventually performance would suffer from calling select/kbhit too
90 but eventually performance would suffer from calling select/kbhit too
91 often.
91 often.
92 """
92 """
93 try:
93 try:
94 app = wx.GetApp()
94 app = wx.GetApp()
95 if app is not None:
95 if app is not None:
96 assert wx.Thread_IsMain()
96 assert wx.Thread_IsMain()
97 elr = EventLoopRunner()
97 elr = EventLoopRunner()
98 # As this time is made shorter, keyboard response improves, but idle
98 # As this time is made shorter, keyboard response improves, but idle
99 # CPU load goes up. 10 ms seems like a good compromise.
99 # CPU load goes up. 10 ms seems like a good compromise.
100 elr.Run(time=10) # CHANGE time here to control polling interval
100 elr.Run(time=10) # CHANGE time here to control polling interval
101 except KeyboardInterrupt:
101 except KeyboardInterrupt:
102 pass
102 pass
103 return 0
103 return 0
104
104
105 def inputhook_wx3():
105 def inputhook_wx3():
106 """Run the wx event loop by processing pending events only.
106 """Run the wx event loop by processing pending events only.
107
107
108 This is like inputhook_wx1, but it keeps processing pending events
108 This is like inputhook_wx1, but it keeps processing pending events
109 until stdin is ready. After processing all pending events, a call to
109 until stdin is ready. After processing all pending events, a call to
110 time.sleep is inserted. This is needed, otherwise, CPU usage is at 100%.
110 time.sleep is inserted. This is needed, otherwise, CPU usage is at 100%.
111 This sleep time should be tuned though for best performance.
111 This sleep time should be tuned though for best performance.
112 """
112 """
113 # We need to protect against a user pressing Control-C when IPython is
113 # We need to protect against a user pressing Control-C when IPython is
114 # idle and this is running. We trap KeyboardInterrupt and pass.
114 # idle and this is running. We trap KeyboardInterrupt and pass.
115 try:
115 try:
116 app = wx.GetApp()
116 app = wx.GetApp()
117 if app is not None:
117 if app is not None:
118 assert wx.Thread_IsMain()
118 assert wx.Thread_IsMain()
119
119
120 # The import of wx on Linux sets the handler for signal.SIGINT
120 # The import of wx on Linux sets the handler for signal.SIGINT
121 # to 0. This is a bug in wx or gtk. We fix by just setting it
121 # to 0. This is a bug in wx or gtk. We fix by just setting it
122 # back to the Python default.
122 # back to the Python default.
123 if not callable(signal.getsignal(signal.SIGINT)):
123 if not callable(signal.getsignal(signal.SIGINT)):
124 signal.signal(signal.SIGINT, signal.default_int_handler)
124 signal.signal(signal.SIGINT, signal.default_int_handler)
125
125
126 evtloop = wx.EventLoop()
126 evtloop = wx.EventLoop()
127 ea = wx.EventLoopActivator(evtloop)
127 ea = wx.EventLoopActivator(evtloop)
128 t = clock()
128 t = clock()
129 while not stdin_ready():
129 while not stdin_ready():
130 while evtloop.Pending():
130 while evtloop.Pending():
131 t = clock()
131 t = clock()
132 evtloop.Dispatch()
132 evtloop.Dispatch()
133 app.ProcessIdle()
133 app.ProcessIdle()
134 # We need to sleep at this point to keep the idle CPU load
134 # We need to sleep at this point to keep the idle CPU load
135 # low. However, if sleep to long, GUI response is poor. As
135 # low. However, if sleep to long, GUI response is poor. As
136 # a compromise, we watch how often GUI events are being processed
136 # a compromise, we watch how often GUI events are being processed
137 # and switch between a short and long sleep time. Here are some
137 # and switch between a short and long sleep time. Here are some
138 # stats useful in helping to tune this.
138 # stats useful in helping to tune this.
139 # time CPU load
139 # time CPU load
140 # 0.001 13%
140 # 0.001 13%
141 # 0.005 3%
141 # 0.005 3%
142 # 0.01 1.5%
142 # 0.01 1.5%
143 # 0.05 0.5%
143 # 0.05 0.5%
144 used_time = clock() - t
144 used_time = clock() - t
145 if used_time > 5*60.0:
145 if used_time > 10.0:
146 # print 'Sleep for 5 s' # dbg
147 time.sleep(5.0)
148 elif used_time > 10.0:
149 # print 'Sleep for 1 s' # dbg
146 # print 'Sleep for 1 s' # dbg
150 time.sleep(1.0)
147 time.sleep(1.0)
151 elif used_time > 0.1:
148 elif used_time > 0.1:
152 # Few GUI events coming in, so we can sleep longer
149 # Few GUI events coming in, so we can sleep longer
153 # print 'Sleep for 0.05 s' # dbg
150 # print 'Sleep for 0.05 s' # dbg
154 time.sleep(0.05)
151 time.sleep(0.05)
155 else:
152 else:
156 # Many GUI events coming in, so sleep only very little
153 # Many GUI events coming in, so sleep only very little
157 time.sleep(0.001)
154 time.sleep(0.001)
158 del ea
155 del ea
159 except KeyboardInterrupt:
156 except KeyboardInterrupt:
160 pass
157 pass
161 return 0
158 return 0
162
159
163 if sys.platform == 'darwin':
160 if sys.platform == 'darwin':
164 # On OSX, evtloop.Pending() always returns True, regardless of there being
161 # On OSX, evtloop.Pending() always returns True, regardless of there being
165 # any events pending. As such we can't use implementations 1 or 3 of the
162 # any events pending. As such we can't use implementations 1 or 3 of the
166 # inputhook as those depend on a pending/dispatch loop.
163 # inputhook as those depend on a pending/dispatch loop.
167 inputhook_wx = inputhook_wx2
164 inputhook_wx = inputhook_wx2
168 else:
165 else:
169 # This is our default implementation
166 # This is our default implementation
170 inputhook_wx = inputhook_wx3
167 inputhook_wx = inputhook_wx3
General Comments 0
You need to be logged in to leave comments. Login now