[RFC] locking decorators and iterators

Andrew Bennetts andrew at canonical.com
Tue Feb 13 03:44:43 GMT 2007


Robert Collins wrote:
[...]
> 
> After a conversation with Andrew about this, I have several things to
> suggest. I think our needs_*_lock decorators should check, and complain,
> if the function they are decorating is a generator. This can be done at
> load time, and should be very fast. The reason is that these decorators
> are ineffective on generators.

"f.func_code.co_code & 0x20" is the test for this (unfortunately there's no
python definition of the CO_GENERATOR constant in inspect.py).

Here's a quick & dirty patch, complete with the warnings it produces just from
running bzr diff to generate it!  So there's already some bugs lurking due to
this.

$ ./bzr diff
/home/andrew/code/bzr/bzrlib/decorators.py:127: UserWarning: <function unknowns at 0xb7b30f7c> is a generator
  import warnings; warnings.warn("%r is a generator" % unbound)
/home/andrew/code/bzr/bzrlib/decorators.py:127: UserWarning: <function get_deltas_for_revisions at 0xb7343a3c> is a generator
  import warnings; warnings.warn("%r is a generator" % unbound)
/home/andrew/code/bzr/bzrlib/decorators.py:127: UserWarning: <function revision_trees at 0xb726810c> is a generator
  import warnings; warnings.warn("%r is a generator" % unbound)
Subversion version too old for working tree support.
=== modified file 'bzrlib/decorators.py'
--- bzrlib/decorators.py        2007-01-25 15:54:29 +0000
+++ bzrlib/decorators.py        2007-02-13 03:41:44 +0000
@@ -76,6 +76,8 @@
         def branch_method(self, ...):
             stuff
     """
+    if unbound.func_code.co_flags & 0x20:
+        import warnings; warnings.warn("%r is a generator" % unbound)
     # This compiles a function with a similar name, but wrapped with
     # lock_read/unlock calls. We use dynamic creation, because we need the
     # internal name of the function to be modified so that --lsprof will see
@@ -121,6 +123,8 @@
         def branch_method(self, ...):
             stuff
     """
+    if unbound.func_code.co_flags & 0x20:
+        import warnings; warnings.warn("%r is a generator" % unbound)
     def read_locked(self, *args, **kwargs):
         self.lock_read()
         try:
@@ -143,6 +147,8 @@
         self.unlock()
 write_locked = %(name)s_write_locked
 """
+    if unbound.func_code.co_flags & 0x20:
+        import warnings; warnings.warn("%r is a generator" % unbound)
     params, passed_params = _get_parameters(unbound)
     variables = {'name':unbound.__name__,
                  'params':params,
@@ -159,6 +165,8 @@
 
 def _fast_needs_write_lock(unbound):
     """Decorate unbound to take out and release a write lock."""
+    if unbound.func_code.co_flags & 0x20:
+        import warnings; warnings.warn("%r is a generator" % unbound)
     def write_locked(self, *args, **kwargs):
         self.lock_write()
         try:


-Andrew.




More information about the bazaar mailing list