diff --git a/usim/_core/loop.py b/usim/_core/loop.py
index 733de51..90e8752 100644
--- a/usim/_core/loop.py
+++ b/usim/_core/loop.py
@@ -74,15 +74,37 @@ __LOOP_STATE__.LOOP = MissingLoop()  # type: Union[MissingLoop, Loop]
 
 # Commands
 class Hibernate(object):
-    r"""Pause current execution indefinitely"""
+    r"""
+    Pause current execution indefinitely
+
+    When yielding this event to :py:class:`~.Loop`,
+    the current activity is suspended.
+    It can be used both in asynchronous functions
+    and synchronous generators;
+    the latter is intended for ``__await__`` methods.
+
+    This class is stateless and effectively works like a singleton.
+    Use :py:attr:`~.__HIBERNATE__` to avoid creating new instances.
+
+    .. code:: python3
+
+        async def sleep():
+            await __HIBERNATE__
+
+        class Sleep:
+            def __await__():
+                yield from __HIBERNATE__
+    """
     __slots__ = ()
 
     def __await__(self) -> 'Generator[Hibernate, None, None]':
         yield self
 
+    __iter__ = __await__
+
 
 #: reusable instance of :py:class:`Hibernate`
-HIBERNATE = Hibernate
+__HIBERNATE__ = Hibernate()
 
 
 class Loop:
diff --git a/usim/_primitives/condition.py b/usim/_primitives/condition.py
index 5edc095..6e880b8 100644
--- a/usim/_primitives/condition.py
+++ b/usim/_primitives/condition.py
@@ -67,9 +67,13 @@ class Condition(Notification):
         return True  # noqa: B901
 
     def __and__(self, other) -> 'Condition':
+        if isinstance(other, All):
+            return All(self, *other._children)
         return All(self, other)
 
     def __or__(self, other) -> 'Condition':
+        if isinstance(other, Any):
+            return Any(self, *other._children)
         return Any(self, other)
 
     def __invert__(self) -> 'Condition':
diff --git a/usim/_primitives/flag.py b/usim/_primitives/flag.py
index 4fac82d..11572de 100644
--- a/usim/_primitives/flag.py
+++ b/usim/_primitives/flag.py
@@ -11,10 +11,10 @@ class Flag(Condition):
         self._value = False
         self._inverse = InverseFlag(self)
 
-    def __bool__(self):
+    def __bool__(self) -> bool:
         return self._value
 
-    def __invert__(self):
+    def __invert__(self) -> 'InverseFlag':
         return self._inverse
 
     async def set(self, to: bool = True):
@@ -35,10 +35,10 @@ class InverseFlag(Condition):
         super().__init__()
         self._event = flag
 
-    def __bool__(self):
+    def __bool__(self) -> bool:
         return not self._event
 
-    def __invert__(self):
+    def __invert__(self) -> 'Flag':
         return self._event
 
     async def set(self, to: bool = True):
diff --git a/usim/_primitives/notification.py b/usim/_primitives/notification.py
index d6e1aa1..3fd43cd 100644
--- a/usim/_primitives/notification.py
+++ b/usim/_primitives/notification.py
@@ -1,7 +1,7 @@
 from typing import List, Tuple, Coroutine
 from contextlib import contextmanager
 
-from .._core.loop import Hibernate, Interrupt, __LOOP_STATE__
+from .._core.loop import Interrupt, __LOOP_STATE__, __HIBERNATE__
 
 
 # TODO: add protocol for destroying a notification
@@ -22,7 +22,7 @@ async def postpone():
     wake_up = Interrupt('postpone', task)
     __LOOP_STATE__.LOOP.schedule(task, signal=wake_up)
     try:
-        await Hibernate()
+        await __HIBERNATE__
     except Interrupt as err:
         if err is not wake_up:
             assert (
@@ -33,23 +33,6 @@ async def postpone():
         wake_up.revoke()
 
 
-@contextmanager
-def subscribe(notification: 'Notification'):
-    task = __LOOP_STATE__.LOOP.activity
-    wake_up = Interrupt(notification, task)
-    notification.__subscribe__(task, wake_up)
-    try:
-        yield
-    except Interrupt as err:
-        if err is not wake_up:
-            assert (
-                task is __LOOP_STATE__.LOOP.activity
-            ), 'Break points cannot be passed to other coroutines'
-            raise
-    finally:
-        notification.__unsubscribe__(task, wake_up)
-
-
 class Notification:
     """
     Synchronisation point to which activities can subscribe
@@ -67,19 +50,8 @@ class Notification:
         self._waiting = []  # type: List[Tuple[Coroutine, Interrupt]]
 
     def __await__(self):
-        yield from self.__await_notification__().__await__()
-
-    async def __await_notification__(self, interrupt: Interrupt = None):
-        activity = __LOOP_STATE__.LOOP.activity
-        interrupt = interrupt if interrupt is not None else Interrupt(self, activity)
-        self.__subscribe__(activity, interrupt)
-        try:
-            await Hibernate()  # break point - we are resumed when the event is set
-        except Interrupt as err:
-            if err is not interrupt:  # resumed prematurely
-                raise
-        finally:
-            self.__unsubscribe__(activity, interrupt)
+        with self.__subscription__():
+            yield from __HIBERNATE__
 
     def __awake_next__(self) -> Tuple[Coroutine, Interrupt]:
         """Awake the oldest waiter"""
@@ -127,13 +99,14 @@ class Notification:
         finally:
             self.__unsubscribe__(task, wake_up)
 
-    def __del__(self):
-        if self._waiting:
-            raise RuntimeError(
-                '%r collected without releasing %d waiting tasks:\n  %s' % (
-                    self, len(self._waiting), self._waiting
+    if __debug__:
+        def __del__(self):
+            if self._waiting:
+                raise RuntimeError(
+                    '%r collected without releasing %d waiting tasks:\n  %s' % (
+                        self, len(self._waiting), self._waiting
+                    )
                 )
-            )
 
     def __repr__(self):
         return '<%s, waiters=%d>' % (self.__class__.__name__, len(self._waiting))
diff --git a/usim/_primitives/timing.py b/usim/_primitives/timing.py
index a98ebd5..3d7b93a 100644
--- a/usim/_primitives/timing.py
+++ b/usim/_primitives/timing.py
@@ -14,7 +14,7 @@ time can represent more than 285 million years of time accurately.
 """
 from typing import Coroutine, Union, Generator, Any
 
-from .._core.loop import __LOOP_STATE__, Hibernate, Interrupt as CoreInterrupt
+from .._core.loop import __LOOP_STATE__, __HIBERNATE__, Interrupt as CoreInterrupt
 from .notification import postpone, Notification
 from .condition import Condition
 
@@ -107,7 +107,7 @@ class Before(Condition):
         if self:
             yield from postpone().__await__()
         else:
-            yield from Hibernate().__await__()
+            yield from __HIBERNATE__
         return True  # noqa: B901
 
     def __repr__(self):
@@ -157,7 +157,7 @@ class Moment(Condition):
         elif not self._transition:
             yield from self._transition.__await__()
         else:
-            yield from Hibernate().__await__()
+            yield from __HIBERNATE__
         return True  # noqa: B901
 
     def __subscribe__(self, waiter: Coroutine, interrupt: CoreInterrupt):
@@ -192,7 +192,7 @@ class Eternity(Condition):
         return Instant()
 
     def __await__(self) -> Generator[Any, None, bool]:
-        yield from Hibernate().__await__()
+        yield from __HIBERNATE__
         return True  # noqa: B901
 
 

Streamline internal notification API
The internal subscribe/unsubscribe API of notifications is partially refactored. ``Notification.__await_notification__`` has a useless parameter and the ``subscribe`` context is not used yet. Probably some more unused/incomplete code.
diff --git a/usim_pytest/test_types/test_condition.py b/usim_pytest/test_types/test_condition.py
index 8d0b819..a9f4651 100644
--- a/usim_pytest/test_types/test_condition.py
+++ b/usim_pytest/test_types/test_condition.py
@@ -1,4 +1,4 @@
-from usim import Flag
+from usim import Flag, until, instant
 
 from ..utility import via_usim
 
@@ -65,3 +65,59 @@ class TestChainedCondition:
         assert chain
         assert not ~chain
         assert await chain
+
+    @via_usim
+    async def test_flatten_and(self):
+        a, b, c, d, e, f = Flag(), Flag(), Flag(), Flag(), Flag(), Flag()
+        lexical_chain = a & b & c & d & e & f
+        parenthesised_chain = a & (b & (c & (d & (e & f))))
+        pairwise_chain = (a & b) & (c & d) & (e & f)
+        assert lexical_chain._children == parenthesised_chain._children
+        assert lexical_chain._children == pairwise_chain._children
+
+    @via_usim
+    async def test_flatten_or(self):
+        a, b, c, d, e, f = Flag(), Flag(), Flag(), Flag(), Flag(), Flag()
+        lexical_chain = a | b | c | d | e | f
+        parenthesised_chain = a | (b | (c | (d | (e | f))))
+        pairwise_chain = (a | b) | (c | d) | (e | f)
+        assert lexical_chain._children == parenthesised_chain._children
+        assert lexical_chain._children == pairwise_chain._children
+
+
+class TestContextCondition:
+    @via_usim
+    async def test_release_self(self):
+        """Condition is set synchronously"""
+        flag = Flag()
+        entered, exited = False, False
+        async with until(flag):
+            entered = True
+            await flag.set()  # get interrupted immediately
+            exited = True
+        assert entered and not exited
+
+    @via_usim
+    async def test_release_concurrent(self):
+        """Condition is set concurrently"""
+        flag = Flag()
+        entered, exited = False, False
+        async with until(flag) as scope:
+            scope.do(flag.set())
+            await instant  # start task
+            entered = True
+            await instant
+            exited = True
+        assert entered and not exited
+
+    @via_usim
+    async def test_release_early(self):
+        """Condition is set before entering interrupt scope"""
+        flag = Flag()
+        await flag.set()
+        entered, exited = False, False
+        async with until(flag):
+            entered = True
+            await instant
+            exited = True
+        assert entered and not exited
diff --git a/usim_pytest/test_types/test_flag.py b/usim_pytest/test_types/test_flag.py
new file mode 100644
index 0000000..ed48e59
--- /dev/null
+++ b/usim_pytest/test_types/test_flag.py
@@ -0,0 +1,30 @@
+from usim import Flag
+
+from ..utility import via_usim
+
+
+class TestFlag:
+    @via_usim
+    async def test_set(self):
+        flag = Flag()
+        assert not flag
+        await flag.set()
+        assert flag
+        await flag.set()
+        assert flag
+        await flag.set(to=False)
+        assert not flag
+        await flag.set(to=False)
+        assert not flag
+
+    @via_usim
+    async def test_invert(self):
+        flag = Flag()
+        i_flag = ~flag
+        assert not flag and i_flag
+        assert ~flag is i_flag
+        assert flag is ~i_flag
+        await i_flag.set(to=False)
+        assert flag and not i_flag
+        assert ~flag is i_flag
+        assert flag is ~i_flag

pip install -e .[contrib]
parse_log_pytest
requirements.txt
pytest pytest-timeout
apt-get update apt-get install -y gcc
3.6
requirements/base.txt
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
attrs==22.2.0
certifi==2021.5.30
flake8==5.0.4
flake8-bugbear==22.9.23
importlib-metadata==4.2.0
iniconfig==1.1.1
mccabe==0.7.0
packaging==21.3
pluggy==1.0.0
py==1.11.0
pycodestyle==2.9.1
pyflakes==2.5.0
pyparsing==3.1.4
pytest==7.0.1
pytest-timeout==2.1.0
sortedcontainers==2.4.0
tomli==1.2.3
typing_extensions==4.1.1
-e git+https://github.com/MaineKuehn/usim.git@079d39e201e5f48d505c22c0cff582d530fb4a41#egg=usim
zipp==3.6.0

name: usim
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - certifi=2021.5.30=py36h06a4308_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.3=he6710b0_2
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=1.1.1w=h7f8727e_0
  - pip=21.2.2=py36h06a4308_0
  - python=3.6.13=h12debd9_1
  - readline=8.2=h5eee18b_0
  - setuptools=58.0.4=py36h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - wheel=0.37.1=pyhd3eb1b0_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - attrs==22.2.0
      - flake8==5.0.4
      - flake8-bugbear==22.9.23
      - importlib-metadata==4.2.0
      - iniconfig==1.1.1
      - mccabe==0.7.0
      - packaging==21.3
      - pluggy==1.0.0
      - py==1.11.0
      - pycodestyle==2.9.1
      - pyflakes==2.5.0
      - pyparsing==3.1.4
      - pytest==7.0.1
      - pytest-timeout==2.1.0
      - sortedcontainers==2.4.0
      - tomli==1.2.3
      - typing-extensions==4.1.1
      - zipp==3.6.0
prefix: /opt/conda/envs/usim

usim_pytest/test_types/test_condition.py::TestChainedCondition::test_flatten_and usim_pytest/test_types/test_condition.py::TestChainedCondition::test_flatten_or
usim_pytest/test_types/test_condition.py::TestChainedCondition::test_chain_and usim_pytest/test_types/test_condition.py::TestChainedCondition::test_chain_or usim_pytest/test_types/test_condition.py::TestChainedCondition::test_chain_long usim_pytest/test_types/test_condition.py::TestContextCondition::test_release_self usim_pytest/test_types/test_condition.py::TestContextCondition::test_release_concurrent usim_pytest/test_types/test_condition.py::TestContextCondition::test_release_early usim_pytest/test_types/test_flag.py::TestFlag::test_set usim_pytest/test_types/test_flag.py::TestFlag::test_invert
usim/_primitives/notification.py usim/_primitives/timing.py usim/_primitives/flag.py usim/_core/loop.py usim/_primitives/condition.py
usim/_primitives/notification.py usim/_primitives/timing.py usim/_primitives/flag.py usim/_core/loop.py usim/_primitives/condition.py