@@ -1400,6 +1400,104 @@ error state. The distinction between the two cases is made using the ``source``
14001400property on the raised exception.
14011401
14021402
1403+ Advisory Locks
1404+ ==============
1405+
1406+ `Explicit Locking in PostgreSQL <http://www.postgresql.org/docs/current/static/explicit-locking.html#ADVISORY-LOCKS>`_.
1407+
1408+ PostgreSQL's advisory locks offer a cooperative synchronization primitive.
1409+ These are used in cases where an application needs access to a resource, but
1410+ using table locks may cause interference with other operations that can be
1411+ safely performed alongside the application-level, exclusive operation.
1412+
1413+ Advisory locks can be used by directly executing the stored procedures in the
1414+ database or by using the :class:`postgresql.alock.ALock` subclasses, which
1415+ provides a context manager that uses those stored procedures.
1416+
1417+ Currently, only two subclasses exist. Each represents the lock mode
1418+ supported by PostgreSQL's advisory locks:
1419+
1420+ * :class:`postgresql.alock.ShareLock`
1421+ * :class:`postgresql.alock.ExclusiveLock`
1422+
1423+
1424+ Acquiring ALocks
1425+ ----------------
1426+
1427+ An ALock instance represents a sequence of advisory locks. A single ALock can
1428+ acquire and release multiple advisory locks by creating the instance with
1429+ multiple lock identifiers::
1430+
1431+ >>> from postgresql import alock
1432+ >>> table1_oid = 192842
1433+ >>> table2_oid = 192849
1434+ >>> l = alock.ExclusiveLock(db, (table1_oid, 0), (table2_oid, 0))
1435+ >>> l.acquire()
1436+ >>> ...
1437+ >>> l.release()
1438+
1439+ :class:`postgresql.alock.ALock` is similar to :class:`threading.RLock`; in
1440+ order for an ALock to be released, it must be released the number of times it
1441+ has been acquired. ALocks are associated with and survived by their session.
1442+ Much like how RLocks are associated with the thread they are acquired in:
1443+ acquiring an ALock again will merely increment its count.
1444+
1445+ PostgreSQL allows advisory locks to be identified using a pair of `int4` or a
1446+ single `int8`. ALock instances represent a *sequence* of those identifiers::
1447+
1448+ >>> from postgresql import alock
1449+ >>> ids = [(0,0), 0, 1]
1450+ >>> with alock.ShareLock(db, *ids):
1451+ ... ...
1452+
1453+ Both types of identifiers may be used within the same ALock, and, regardless of
1454+ their type, will be aquired in the order that they were given to the class'
1455+ constructor. In the above example, ``(0,0)`` is acquired first, then ``0``, and
1456+ lastly ``1``.
1457+
1458+ `postgresql.alock.ALock` subclasses:
1459+
1460+ ``postgresql.alock.ExclusiveLock(database, *identifiers)``
1461+ Instantiate an ALock object representing the `identifiers` for use with the
1462+ `database`. Exclusive locks will conflict with other exclusive locks and share
1463+ locks.
1464+
1465+ ``postgresql.alock.ShareLock(database, *identifiers)``
1466+ Instantiate an ALock object representing the `identifiers` for use with the
1467+ `database`. Share locks can be acquired when a share lock with the same
1468+ identifier has been acquired by another backend. However, an exclusive lock
1469+ with the same identifier will conflict.
1470+
1471+
1472+ Advisory Lock Interface Points
1473+ ------------------------------
1474+
1475+ Methods and properties available on :class:`postgresql.alock.ALock` instances:
1476+
1477+ ``alock.acquire(blocking = True)``
1478+ Acquire the advisory locks represented by the ``alock`` object. If blocking is
1479+ `True`, the default, the method will block until locks on *all* the
1480+ identifiers have been acquired.
1481+
1482+ If blocking is `False`, acquisition may not block, and success will be
1483+ indicated by the returned object: `True` if *all* lock identifiers were
1484+ acquired and `False` if any of the lock identifiers could not be acquired.
1485+
1486+ ``alock.release()``
1487+ Release the advisory locks represented by the ``alock`` object. If the lock
1488+ has not been acquired, a `RuntimeError` will be raised.
1489+
1490+ ``alock.locked()``
1491+ Returns a boolean describing whether the locks are held or not. This will
1492+ return `False` if the lock connection has been closed.
1493+
1494+ ``alock.__enter__()``
1495+ Alias to ``acquire``; context manager protocol. Always blocking.
1496+
1497+ ``alock.__exit__(typ, val, tb)``
1498+ Alias to ``release``; context manager protocol.
1499+
1500+
14031501Settings
14041502========
14051503
@@ -1920,101 +2018,3 @@ Summary of Characteristics
19202018 * A notification triple is a tuple consisting of ``(channel, payload, pid)``.
19212019 * Connections may be added and removed from the ``nm.connections`` set at
19222020 any time.
1923-
1924-
1925- Advisory Locks
1926- ==============
1927-
1928- `Explicit Locking in PostgreSQL <http://www.postgresql.org/docs/current/static/explicit-locking.html#ADVISORY-LOCKS>`_.
1929-
1930- PostgreSQL's advisory locks offer a cooperative synchronization primitive.
1931- These are used in cases where an application needs access to a resource, but
1932- using table locks may cause interference with other operations that can be
1933- safely performed alongside the application-level, exclusive operation.
1934-
1935- Advisory locks can be used by directly executing the stored procedures in the
1936- database or by using the :class:`postgresql.alock.ALock` subclasses, which
1937- provides a context manager that uses those stored procedures.
1938-
1939- Currently, only two subclasses exist. Each represents the lock mode
1940- supported by PostgreSQL's advisory locks:
1941-
1942- * :class:`postgresql.alock.ShareLock`
1943- * :class:`postgresql.alock.ExclusiveLock`
1944-
1945-
1946- Acquiring ALocks
1947- ----------------
1948-
1949- An ALock instance represents a sequence of advisory locks. A single ALock can
1950- acquire and release multiple advisory locks by creating the instance with
1951- multiple lock identifiers::
1952-
1953- >>> from postgresql import alock
1954- >>> table1_oid = 192842
1955- >>> table2_oid = 192849
1956- >>> l = alock.ExclusiveLock(db, (table1_oid, 0), (table2_oid, 0))
1957- >>> l.acquire()
1958- >>> ...
1959- >>> l.release()
1960-
1961- :class:`postgresql.alock.ALock` is similar to :class:`threading.RLock`; in
1962- order for an ALock to be released, it must be released the number of times it
1963- has been acquired. ALocks are associated with and survived by their session.
1964- Much like how RLocks are associated with the thread they are acquired in:
1965- acquiring an ALock again will merely increment its count.
1966-
1967- PostgreSQL allows advisory locks to be identified using a pair of `int4` or a
1968- single `int8`. ALock instances represent a *sequence* of those identifiers::
1969-
1970- >>> from postgresql import alock
1971- >>> ids = [(0,0), 0, 1]
1972- >>> with alock.ShareLock(db, *ids):
1973- ... ...
1974-
1975- Both types of identifiers may be used within the same ALock, and, regardless of
1976- their type, will be aquired in the order that they were given to the class'
1977- constructor. In the above example, ``(0,0)`` is acquired first, then ``0``, and
1978- lastly ``1``.
1979-
1980- `postgresql.alock.ALock` subclasses:
1981-
1982- ``postgresql.alock.ExclusiveLock(database, *identifiers)``
1983- Instantiate an ALock object representing the `identifiers` for use with the
1984- `database`. Exclusive locks will conflict with other exclusive locks and share
1985- locks.
1986-
1987- ``postgresql.alock.ShareLock(database, *identifiers)``
1988- Instantiate an ALock object representing the `identifiers` for use with the
1989- `database`. Share locks can be acquired when a share lock with the same
1990- identifier has been acquired by another backend. However, an exclusive lock
1991- with the same identifier will conflict.
1992-
1993-
1994- Advisory Lock Interface Points
1995- ------------------------------
1996-
1997- Methods and properties available on :class:`postgresql.alock.ALock` instances:
1998-
1999- ``alock.acquire(blocking = True)``
2000- Acquire the advisory locks represented by the ``alock`` object. If blocking is
2001- `True`, the default, the method will block until locks on *all* the
2002- identifiers have been acquired.
2003-
2004- If blocking is `False`, acquisition may not block, and success will be
2005- indicated by the returned object: `True` if *all* lock identifiers were
2006- acquired and `False` if any of the lock identifiers could not be acquired.
2007-
2008- ``alock.release()``
2009- Release the advisory locks represented by the ``alock`` object. If the lock
2010- has not been acquired, a `RuntimeError` will be raised.
2011-
2012- ``alock.locked()``
2013- Returns a boolean describing whether the locks are held or not. This will
2014- return `False` if the lock connection has been closed.
2015-
2016- ``alock.__enter__()``
2017- Alias to ``acquire``; context manager protocol. Always blocking.
2018-
2019- ``alock.__exit__(typ, val, tb)``
2020- Alias to ``release``; context manager protocol.
0 commit comments