@@ -8,8 +8,8 @@ Debugging tools, like those used for tracing, are implemented through
8
8
calls to the :func: `sys.settrace ` function. Now, in |CPY |, when
9
9
this has been called any code that runs within the operating system thread
10
10
is covered by it. In Stackless however, this function only covers the
11
- current tasklet. Stackless provides the tasklet attributes
12
- :attr: `~tasklet.trace_function ` and :attr: `~tasklet.profile_function ` to
11
+ current tasklet. Stackless provides the tasklet attributes
12
+ :attr: `~tasklet.trace_function ` and :attr: `~tasklet.profile_function ` to
13
13
get and set the trace/profile function of a particular tasklet.
14
14
15
15
The debugging related modules, whether :doc: `in the standard library
@@ -19,8 +19,8 @@ In an ideal world, |SLP| might include modified versions of these
19
19
modules, and patches adding them would be most welcome.
20
20
21
21
If you want working debugging for |SLP |, at this time your best
22
- option is to use the `WingWare Python IDE <http://wingware.com >`_
23
- or the `Eclipse IDE with the PyDev-Plugin <http://pydev.org >`_.
22
+ option is to use the `WingWare Python IDE <http://wingware.com >`_
23
+ or the `Eclipse IDE with the PyDev-Plugin <http://pydev.org >`_.
24
24
Both have gone out of their way to add and support |SLP | development.
25
25
26
26
.. note ::
@@ -36,39 +36,39 @@ Tracing tasklets
36
36
37
37
In order to get debugging support working on a per-tasklet basis, you need to
38
38
ensure you enable tracing for all tasklets. This can be archived by the
39
- schedule callback. This callback sees every task switch. Here is
39
+ schedule callback. This callback sees every task switch. Here is
40
40
a complete example::
41
41
42
42
from __future__ import absolute_import, print_function
43
-
43
+
44
44
import sys
45
45
import stackless
46
46
import traceback
47
-
48
-
47
+
48
+
49
49
class NamedTasklet(stackless.tasklet):
50
50
__slots__ = ("name",)
51
-
51
+
52
52
def __init__(self, func, name=None):
53
53
stackless.tasklet.__init__(self, func)
54
54
if name is None:
55
55
name = "at %08x" % (id(self))
56
56
self.name = name
57
-
57
+
58
58
def __repr__(self):
59
59
return "<tasklet %s>" % (self.name)
60
-
61
-
60
+
61
+
62
62
class Mutex(object):
63
-
63
+
64
64
def __init__(self, capacity=1):
65
65
self.queue = stackless.channel()
66
66
self.capacity = capacity
67
-
67
+
68
68
def isLocked(self):
69
69
'''return non-zero if locked'''
70
70
return self.capacity == 0
71
-
71
+
72
72
def lock(self):
73
73
'''acquire the lock'''
74
74
currentTasklet = stackless.getcurrent()
@@ -80,7 +80,7 @@ a complete example::
80
80
self.queue.receive()
81
81
finally:
82
82
currentTasklet.set_atomic(atomic)
83
-
83
+
84
84
def unlock(self):
85
85
'''release the lock'''
86
86
currentTasklet = stackless.getcurrent()
@@ -92,10 +92,10 @@ a complete example::
92
92
self.capacity += 1
93
93
finally:
94
94
currentTasklet.set_atomic(atomic)
95
-
95
+
96
96
m = Mutex()
97
-
98
-
97
+
98
+
99
99
def task():
100
100
name = stackless.getcurrent().name
101
101
print(name, "acquiring")
@@ -104,8 +104,8 @@ a complete example::
104
104
stackless.schedule()
105
105
print(name, "releasing")
106
106
m.unlock()
107
-
108
-
107
+
108
+
109
109
def trace_function(frame, event, arg):
110
110
if frame.f_code.co_name in ('schedule_cb', 'channel_cb'):
111
111
return None
@@ -114,8 +114,8 @@ a complete example::
114
114
if event in ('call', 'line', 'exception'):
115
115
return trace_function
116
116
return None
117
-
118
-
117
+
118
+
119
119
def channel_cb(channel, tasklet, sending, willblock):
120
120
tf = tasklet.trace_function
121
121
try:
@@ -124,8 +124,8 @@ a complete example::
124
124
(tasklet, ("recv", "send")[sending], ("", " will block")[willblock]))
125
125
finally:
126
126
tasklet.trace_function = tf
127
-
128
-
127
+
128
+
129
129
def schedule_cb(prev, next):
130
130
# During a tasklet switch (during the execution of this function) the
131
131
# the result of stackless.getcurrent() is implementation defined.
@@ -140,20 +140,20 @@ a complete example::
140
140
f_back = current_frame.f_back
141
141
if f_back is not None:
142
142
current_tf = f_back.f_trace
143
-
143
+
144
144
current_info = "Schedule CB "
145
145
if not prev:
146
146
print("%sstarting %r" % (current_info, next))
147
147
elif not next:
148
148
print("%sending %r" % (current_info, prev))
149
149
else:
150
150
print("%sjumping from %s to %s" % (current_info, prev, next))
151
-
151
+
152
152
# Inform about the installed trace functions
153
153
prev_tf = current_tf if prev.frame is current_frame else prev.trace_function
154
154
next_tf = current_tf if next.frame is current_frame else next.trace_function
155
155
print(" Current trace functions: prev: %r, next: %r" % (prev_tf, next_tf))
156
-
156
+
157
157
# Eventually set a trace function
158
158
if next is not None:
159
159
if not next.is_main:
@@ -175,20 +175,20 @@ a complete example::
175
175
traceback.print_exc()
176
176
finally:
177
177
sys.settrace(current_tf)
178
-
178
+
179
179
if __name__ == "__main__":
180
180
if len(sys.argv) > 1 and sys.argv[1] == 'hard':
181
181
stackless.enable_softswitch(False)
182
-
182
+
183
183
stackless.set_channel_callback(channel_cb)
184
184
stackless.set_schedule_callback(schedule_cb)
185
-
185
+
186
186
NamedTasklet(task, "tick")()
187
187
NamedTasklet(task, "trick")()
188
188
NamedTasklet(task, "track")()
189
-
189
+
190
190
stackless.run()
191
-
191
+
192
192
stackless.set_channel_callback(None)
193
193
stackless.set_schedule_callback(None)
194
194
@@ -199,13 +199,13 @@ a complete example::
199
199
200
200
.. note ::
201
201
202
- This section is out dated and only of historical interest. Since the
203
- implementation of :attr: `~tasklet.trace_function ` and
202
+ This section is out dated and only of historical interest. Since the
203
+ implementation of :attr: `~tasklet.trace_function ` and
204
204
:attr: `~tasklet.profile_function ` a debugger can enable tracing or profiling
205
205
within the schedule callback without monkey patching.
206
-
206
+
207
207
In order to get debugging support working on a per-tasklet basis, you need to
208
- ensure you call :func: `sys.settrace ` for all tasklets. Vilhelm Saevarsson
208
+ ensure you call :func: `sys.settrace ` for all tasklets. Vilhelm Saevarsson
209
209
`has an email
210
210
<http://www.stackless.com/pipermail/stackless/2007-October/003074.html> `_
211
211
giving code and a description of the steps required including potentially
@@ -215,7 +215,7 @@ Vilhelm's code::
215
215
216
216
import sys
217
217
import stackless
218
-
218
+
219
219
def contextDispatch( prev, next ):
220
220
if not prev: #Creating next
221
221
# I never see this print out
@@ -232,7 +232,7 @@ Vilhelm's code::
232
232
if not next.frame.f_trace:
233
233
# We might already be tracing so ...
234
234
sys.call_tracing(next.settrace, (traceDispatch, ))
235
-
235
+
236
236
stackless.set_schedule_callback(contextDispatch)
237
237
238
238
def __call__(self, *args, **kwargs):
@@ -243,11 +243,11 @@ Vilhelm's code::
243
243
sys.settrace(None)
244
244
self.tempval = new_f
245
245
stackless.tasklet.setup(self, f, args, kwargs)
246
-
246
+
247
247
def settrace( self, tb ):
248
248
self.frame.f_trace = tb
249
249
sys.settrace(tb)
250
-
250
+
251
251
stackless.tasklet.__call__ = __call__
252
252
stackless.tasklet.settrace = settrace
253
253
0 commit comments