reSTify PEP 319 (#350)
This commit is contained in:
parent
cc56b43dcb
commit
86a462a7b4
270
pep-0319.txt
270
pep-0319.txt
|
@ -5,25 +5,27 @@ Last-Modified: $Date$
|
|||
Author: Michel Pelletier <michel@users.sourceforge.net>
|
||||
Status: Rejected
|
||||
Type: Standards Track
|
||||
Content-Type: text/x-rst
|
||||
Created: 24-Feb-2003
|
||||
Python-Version: 2.4?
|
||||
Post-History:
|
||||
|
||||
|
||||
Abstract
|
||||
========
|
||||
|
||||
This PEP proposes adding two new keywords to Python, `synchronize'
|
||||
and 'asynchronize'.
|
||||
This PEP proposes adding two new keywords to Python, 'synchronize'
|
||||
and 'asynchronize'.
|
||||
|
||||
Pronouncement
|
||||
=============
|
||||
|
||||
This PEP is rejected in favor of PEP 343.
|
||||
|
||||
The `synchronize' Keyword
|
||||
This PEP is rejected in favor of PEP 343.
|
||||
|
||||
The 'synchronize' Keyword
|
||||
The concept of code synchronization in Python is too low-level.
|
||||
To synchronize code a programmer must be aware of the details of
|
||||
the following pseudo-code pattern:
|
||||
the following pseudo-code pattern::
|
||||
|
||||
initialize_lock()
|
||||
|
||||
|
@ -37,7 +39,7 @@ The `synchronize' Keyword
|
|||
|
||||
This synchronized block pattern is not the only pattern (more
|
||||
discussed below) but it is very common. This PEP proposes
|
||||
replacing the above code with the following equivalent:
|
||||
replacing the above code with the following equivalent::
|
||||
|
||||
synchronize:
|
||||
change_shared_data()
|
||||
|
@ -49,13 +51,12 @@ The `synchronize' Keyword
|
|||
thread locking issues.
|
||||
|
||||
|
||||
The `asynchronize' Keyword
|
||||
|
||||
While executing a `synchronize' block of code a programmer may
|
||||
The 'asynchronize' Keyword
|
||||
While executing a 'synchronize' block of code a programmer may
|
||||
want to "drop back" to running asynchronously momentarily to run
|
||||
blocking input/output routines or something else that might take a
|
||||
indeterminate amount of time and does not require synchronization.
|
||||
This code usually follows the pattern:
|
||||
This code usually follows the pattern::
|
||||
|
||||
initialize_lock()
|
||||
|
||||
|
@ -75,7 +76,7 @@ The `asynchronize' Keyword
|
|||
The asynchronous section of the code is not very obvious visually,
|
||||
so it is marked up with comments. Using the proposed
|
||||
'asynchronize' keyword this code becomes much cleaner, easier to
|
||||
understand, and less prone to error:
|
||||
understand, and less prone to error::
|
||||
|
||||
synchronize:
|
||||
change_shared_data()
|
||||
|
@ -85,10 +86,10 @@ The `asynchronize' Keyword
|
|||
|
||||
change_shared_data2()
|
||||
|
||||
Encountering an `asynchronize' keyword inside a non-synchronized
|
||||
Encountering an 'asynchronize' keyword inside a non-synchronized
|
||||
block can raise either an error or issue a warning (as all code
|
||||
blocks are implicitly asynchronous anyway). It is important to
|
||||
note that the above example is *not* the same as:
|
||||
note that the above example is **not** the same as::
|
||||
|
||||
synchronize:
|
||||
change_shared_data()
|
||||
|
@ -99,7 +100,7 @@ The `asynchronize' Keyword
|
|||
change_shared_data2()
|
||||
|
||||
Because both synchronized blocks of code may be running inside the
|
||||
same iteration of a loop, Consider:
|
||||
same iteration of a loop, Consider::
|
||||
|
||||
while in_main_loop():
|
||||
synchronize:
|
||||
|
@ -118,15 +119,16 @@ The `asynchronize' Keyword
|
|||
|
||||
|
||||
Synchronization Targets
|
||||
=======================
|
||||
|
||||
As proposed the `synchronize' and `asynchronize' keywords
|
||||
synchronize a block of code. However programmers may want to
|
||||
specify a target object that threads synchronize on. Any object
|
||||
can be a synchronization target.
|
||||
As proposed the 'synchronize' and 'asynchronize' keywords
|
||||
synchronize a block of code. However programmers may want to
|
||||
specify a target object that threads synchronize on. Any object
|
||||
can be a synchronization target.
|
||||
|
||||
Consider a two-way queue object: two different objects are used by
|
||||
the same `synchronize' code block to synchronize both queues
|
||||
separately in the 'get' method:
|
||||
Consider a two-way queue object: two different objects are used by
|
||||
the same 'synchronize' code block to synchronize both queues
|
||||
separately in the 'get' method::
|
||||
|
||||
class TwoWayQueue:
|
||||
def __init__(self):
|
||||
|
@ -157,8 +159,8 @@ Synchronization Targets
|
|||
del queue[0]
|
||||
return item
|
||||
|
||||
Here is the equivalent code in Python as it is now without a
|
||||
`synchronize' keyword:
|
||||
Here is the equivalent code in Python as it is now without a
|
||||
'synchronize' keyword::
|
||||
|
||||
import thread
|
||||
|
||||
|
@ -203,24 +205,25 @@ Synchronization Targets
|
|||
finally:
|
||||
queue.lock.release()
|
||||
|
||||
The last example had to define an extra class to associate a lock
|
||||
with the queue where the first example the `synchronize' keyword
|
||||
does this association internally and transparently.
|
||||
The last example had to define an extra class to associate a lock
|
||||
with the queue where the first example the 'synchronize' keyword
|
||||
does this association internally and transparently.
|
||||
|
||||
|
||||
Other Patterns that Synchronize
|
||||
===============================
|
||||
|
||||
There are some situations where the `synchronize' and
|
||||
`asynchronize' keywords cannot entirely replace the use of lock
|
||||
methods like `acquire' and `release'. Some examples are if the
|
||||
programmer wants to provide arguments for `acquire' or if a lock
|
||||
is acquired in one code block but released in another, as shown
|
||||
below.
|
||||
There are some situations where the 'synchronize' and
|
||||
'asynchronize' keywords cannot entirely replace the use of lock
|
||||
methods like ``acquire`` and ``release``. Some examples are if the
|
||||
programmer wants to provide arguments for ``acquire`` or if a lock
|
||||
is acquired in one code block but released in another, as shown
|
||||
below.
|
||||
|
||||
Here is a class from Zope modified to use both the `synchronize'
|
||||
and `asynchronize' keywords and also uses a pool of explicit locks
|
||||
that are acquired and released in different code blocks and thus
|
||||
don't use `synchronize':
|
||||
Here is a class from Zope modified to use both the 'synchronize'
|
||||
and 'asynchronize' keywords and also uses a pool of explicit locks
|
||||
that are acquired and released in different code blocks and thus
|
||||
don't use 'synchronize'::
|
||||
|
||||
import thread
|
||||
from ZServerPublisher import ZServerPublisher
|
||||
|
@ -266,9 +269,9 @@ Other Patterns that Synchronize
|
|||
del ready[-1]
|
||||
l.release()
|
||||
|
||||
Here is the original class as found in the
|
||||
'Zope/ZServer/PubCore/ZRendevous.py' module. The "convenience" of
|
||||
the '_a' and '_r' shortcut names obscure the code:
|
||||
Here is the original class as found in the
|
||||
'Zope/ZServer/PubCore/ZRendevous.py' module. The "convenience" of
|
||||
the '_a' and '_r' shortcut names obscure the code::
|
||||
|
||||
import thread
|
||||
from ZServerPublisher import ZServerPublisher
|
||||
|
@ -321,95 +324,99 @@ Other Patterns that Synchronize
|
|||
l.release()
|
||||
finally: self._r()
|
||||
|
||||
In particular the asynchronize section of the `accept' method is
|
||||
not very obvious. To beginner programmers, `synchronize' and
|
||||
`asynchronize' remove many of the problems encountered when
|
||||
juggling multiple `acquire' and `release' methods on different
|
||||
locks in different `try/finally' blocks.
|
||||
In particular the asynchronize section of the ``accept`` method is
|
||||
not very obvious. To beginner programmers, 'synchronize' and
|
||||
'asynchronize' remove many of the problems encountered when
|
||||
juggling multiple ``acquire`` and ``release`` methods on different
|
||||
locks in different ``try/finally`` blocks.
|
||||
|
||||
|
||||
Formal Syntax
|
||||
=============
|
||||
|
||||
Python syntax is defined in a modified BNF grammar notation
|
||||
described in the Python Language Reference [1]. This section
|
||||
describes the proposed synchronization syntax using this grammar:
|
||||
Python syntax is defined in a modified BNF grammar notation
|
||||
described in the Python Language Reference [1]_. This section
|
||||
describes the proposed synchronization syntax using this grammar::
|
||||
|
||||
synchronize_stmt: 'synchronize' [test] ':' suite
|
||||
asynchronize_stmt: 'asynchronize' [test] ':' suite
|
||||
compound_stmt: ... | synchronized_stmt | asynchronize_stmt
|
||||
|
||||
(The '...' indicates other compound statements elided).
|
||||
(The '...' indicates other compound statements elided).
|
||||
|
||||
|
||||
Proposed Implementation
|
||||
=======================
|
||||
|
||||
The author of this PEP has not explored an implementation yet.
|
||||
There are several implementation issues that must be resolved.
|
||||
The main implementation issue is what exactly gets locked and
|
||||
unlocked during a synchronized block.
|
||||
The author of this PEP has not explored an implementation yet.
|
||||
There are several implementation issues that must be resolved.
|
||||
The main implementation issue is what exactly gets locked and
|
||||
unlocked during a synchronized block.
|
||||
|
||||
During an unqualified synchronized block (the use of the
|
||||
`synchronize' keyword without a target argument) a lock could be
|
||||
created and associated with the synchronized code block object.
|
||||
Any threads that are to execute the block must first acquire the
|
||||
code block lock.
|
||||
During an unqualified synchronized block (the use of the
|
||||
'synchronize' keyword without a target argument) a lock could be
|
||||
created and associated with the synchronized code block object.
|
||||
Any threads that are to execute the block must first acquire the
|
||||
code block lock.
|
||||
|
||||
When an `asynchronize' keyword is encountered in a `synchronize'
|
||||
block the code block lock is unlocked before the inner block is
|
||||
executed and re-locked when the inner block terminates.
|
||||
When an 'asynchronize' keyword is encountered in a 'synchronize'
|
||||
block the code block lock is unlocked before the inner block is
|
||||
executed and re-locked when the inner block terminates.
|
||||
|
||||
When a synchronized block target is specified the object is
|
||||
associated with a lock. How this is implemented cleanly is
|
||||
probably the highest risk of this proposal. Java Virtual Machines
|
||||
typically associate a special hidden lock object with target
|
||||
object and use it to synchronized the block around the target
|
||||
only.
|
||||
When a synchronized block target is specified the object is
|
||||
associated with a lock. How this is implemented cleanly is
|
||||
probably the highest risk of this proposal. Java Virtual Machines
|
||||
typically associate a special hidden lock object with target
|
||||
object and use it to synchronized the block around the target
|
||||
only.
|
||||
|
||||
|
||||
Backward Compatibility
|
||||
======================
|
||||
|
||||
Backward compatibility is solved with the new `from __future__'
|
||||
Python syntax [2], and the new warning framework [3] to evolve the
|
||||
Python language into phasing out any conflicting names that use
|
||||
the new keywords `synchronize' and `asynchronize'. To use the
|
||||
syntax now, a developer could use the statement:
|
||||
Backward compatibility is solved with the new ``from __future__``
|
||||
Python syntax [2]_, and the new warning framework [3]_ to evolve the
|
||||
Python language into phasing out any conflicting names that use
|
||||
the new keywords 'synchronize' and 'asynchronize'. To use the
|
||||
syntax now, a developer could use the statement::
|
||||
|
||||
from __future__ import threadsync # or whatever
|
||||
|
||||
In addition, any code that uses the keyword `synchronize' or
|
||||
`asynchronize' as an identifier will be issued a warning from
|
||||
Python. After the appropriate period of time, the syntax would
|
||||
become standard, the above import statement would do nothing, and
|
||||
any identifiers named `synchronize' or `asynchronize' would raise
|
||||
an exception.
|
||||
In addition, any code that uses the keyword 'synchronize' or
|
||||
'asynchronize' as an identifier will be issued a warning from
|
||||
Python. After the appropriate period of time, the syntax would
|
||||
become standard, the above import statement would do nothing, and
|
||||
any identifiers named 'synchronize' or 'asynchronize' would raise
|
||||
an exception.
|
||||
|
||||
|
||||
PEP 310 Reliable Acquisition/Release Pairs
|
||||
==========================================
|
||||
|
||||
PEP 310 [4] proposes the 'with' keyword that can serve the same
|
||||
function as 'synchronize' (but no facility for 'asynchronize').
|
||||
The pattern:
|
||||
PEP 310 [4]_ proposes the 'with' keyword that can serve the same
|
||||
function as 'synchronize' (but no facility for 'asynchronize').
|
||||
The pattern::
|
||||
|
||||
initialize_lock()
|
||||
|
||||
with the_lock:
|
||||
change_shared_data()
|
||||
|
||||
is equivalent to the proposed:
|
||||
is equivalent to the proposed::
|
||||
|
||||
synchronize the_lock:
|
||||
change_shared_data()
|
||||
|
||||
PEP 310 must synchronize on an exsiting lock, while this PEP
|
||||
proposes that unqualified 'synchronize' statements synchronize on
|
||||
a global, internal, transparent lock in addition to qualifiled
|
||||
'synchronize' statements. The 'with' statement also requires lock
|
||||
initialization, while the 'synchronize' statement can synchronize
|
||||
on any target object *including* locks.
|
||||
PEP 310 must synchronize on an exsiting lock, while this PEP
|
||||
proposes that unqualified 'synchronize' statements synchronize on
|
||||
a global, internal, transparent lock in addition to qualifiled
|
||||
'synchronize' statements. The 'with' statement also requires lock
|
||||
initialization, while the 'synchronize' statement can synchronize
|
||||
on any target object **including** locks.
|
||||
|
||||
While limited in this fashion, the 'with' statement is more
|
||||
abstract and serves more purposes than synchronization. For
|
||||
example, transactions could be used with the 'with' keyword:
|
||||
While limited in this fashion, the 'with' statement is more
|
||||
abstract and serves more purposes than synchronization. For
|
||||
example, transactions could be used with the 'with' keyword::
|
||||
|
||||
initialize_transaction()
|
||||
|
||||
|
@ -418,83 +425,90 @@ PEP 310 Reliable Acquisition/Release Pairs
|
|||
|
||||
# when the block terminates, the transaction is committed.
|
||||
|
||||
The 'synchronize' and 'asynchronize' keywords cannot serve this or
|
||||
any other general acquire/release pattern other than thread
|
||||
synchronization.
|
||||
The 'synchronize' and 'asynchronize' keywords cannot serve this or
|
||||
any other general acquire/release pattern other than thread
|
||||
synchronization.
|
||||
|
||||
|
||||
How Java Does It
|
||||
================
|
||||
|
||||
Java defines a 'synchronized' keyword (note the grammatical tense
|
||||
different between the Java keyword and this PEP's 'synchronize')
|
||||
which must be qualified on any object. The syntax is:
|
||||
Java defines a 'synchronized' keyword (note the grammatical tense
|
||||
different between the Java keyword and this PEP's 'synchronize')
|
||||
which must be qualified on any object. The syntax is::
|
||||
|
||||
synchronized (Expression) Block
|
||||
|
||||
Expression must yield a valid object (null raises an error and
|
||||
exceptions during 'Expression' terminate the 'synchronized' block
|
||||
for the same reason) upon which 'Block' is synchronized.
|
||||
Expression must yield a valid object (null raises an error and
|
||||
exceptions during 'Expression' terminate the 'synchronized' block
|
||||
for the same reason) upon which 'Block' is synchronized.
|
||||
|
||||
|
||||
How Jython Does It
|
||||
==================
|
||||
|
||||
Jython uses a 'synchronize' class with the static method
|
||||
'make_synchronized' that accepts one callable argument and returns
|
||||
a newly created, synchronized, callable "wrapper" around the
|
||||
argument.
|
||||
Jython uses a 'synchronize' class with the static method
|
||||
'make_synchronized' that accepts one callable argument and returns
|
||||
a newly created, synchronized, callable "wrapper" around the
|
||||
argument.
|
||||
|
||||
|
||||
Summary of Proposed Changes to Python
|
||||
=====================================
|
||||
|
||||
Adding new `synchronize' and `asynchronize' keywords to the
|
||||
language.
|
||||
Adding new 'synchronize' and 'asynchronize' keywords to the
|
||||
language.
|
||||
|
||||
|
||||
Risks
|
||||
=====
|
||||
|
||||
This PEP proposes adding two keywords to the Python language. This
|
||||
may break code.
|
||||
This PEP proposes adding two keywords to the Python language. This
|
||||
may break code.
|
||||
|
||||
There is no implementation to test.
|
||||
There is no implementation to test.
|
||||
|
||||
It's not the most important problem facing Python programmers
|
||||
today (although it is a fairly notorious one).
|
||||
It's not the most important problem facing Python programmers
|
||||
today (although it is a fairly notorious one).
|
||||
|
||||
The equivalent Java keyword is the past participle 'synchronized'.
|
||||
This PEP proposes the present tense, 'synchronize' as being more
|
||||
in spirit with Python (there being less distinction between
|
||||
compile-time and run-time in Python than Java).
|
||||
The equivalent Java keyword is the past participle 'synchronized'.
|
||||
This PEP proposes the present tense, 'synchronize' as being more
|
||||
in spirit with Python (there being less distinction between
|
||||
compile-time and run-time in Python than Java).
|
||||
|
||||
|
||||
Dissenting Opinion
|
||||
==================
|
||||
|
||||
This PEP has not been discussed on python-dev.
|
||||
This PEP has not been discussed on python-dev.
|
||||
|
||||
|
||||
References
|
||||
==========
|
||||
|
||||
[1] The Python Language Reference
|
||||
.. [1] The Python Language Reference
|
||||
http://docs.python.org/reference/
|
||||
|
||||
[2] PEP 236, Back to the __future__, Peters
|
||||
.. [2] PEP 236, Back to the __future__, Peters
|
||||
http://www.python.org/dev/peps/pep-0236/
|
||||
|
||||
[3] PEP 230, Warning Framework, van Rossum
|
||||
.. [3] PEP 230, Warning Framework, van Rossum
|
||||
http://www.python.org/dev/peps/pep-0230/
|
||||
|
||||
[4] PEP 310, Reliable Acquisition/Release Pairs, Hudson, Moore
|
||||
.. [4] PEP 310, Reliable Acquisition/Release Pairs, Hudson, Moore
|
||||
http://www.python.org/dev/peps/pep-0310/
|
||||
|
||||
|
||||
Copyright
|
||||
=========
|
||||
|
||||
This document has been placed in the public domain.
|
||||
This document has been placed in the public domain.
|
||||
|
||||
|
||||
|
||||
Local Variables:
|
||||
mode: indented-text
|
||||
indent-tabs-mode: nil
|
||||
sentence-end-double-space: t
|
||||
fill-column: 70
|
||||
End:
|
||||
..
|
||||
Local Variables:
|
||||
mode: indented-text
|
||||
indent-tabs-mode: nil
|
||||
sentence-end-double-space: t
|
||||
fill-column: 70
|
||||
End:
|
||||
|
|
Loading…
Reference in New Issue