@staticmethod
def instance():
- """Returns a global `IOLoop` instance.
-
- Most applications have a single, global `IOLoop` running on the
- main thread. Use this method to get this instance from
- another thread. In most other cases, it is better to use `current()`
- to get the current thread's `IOLoop`.
+ """Deprecated alias for `IOLoop.current()`.
+
+ .. versionchanged:: 5.0
+
+ Previously, this method returned a global singleton
+ `IOLoop`, in contrast with the per-thread `IOLoop` returned
+ by `current()`. In nearly all cases the two were the same
+ (when they differed, it was generally used from non-Tornado
+ threads to communicate back to the main thread's `IOLoop`).
+ This distinction is not present in `asyncio`, so in order
+ to facilitate integration with that package `instance()`
+ was changed to be an alias to `current()`. Applications
+ using the cross-thread communications aspect of
+ `instance()` should instead set their own global variable
+ to point to the `IOLoop` they want to use.
+
+ .. deprecated:: 5.0
"""
- if not hasattr(IOLoop, "_instance"):
- with IOLoop._instance_lock:
- if not hasattr(IOLoop, "_instance"):
- # New instance after double check
- IOLoop._instance = IOLoop()
- return IOLoop._instance
+ return IOLoop.current()
@staticmethod
def initialized():
- """Returns true if the singleton instance has been created."""
- return hasattr(IOLoop, "_instance")
+ """Returns true if there is a current IOLoop.
+
+ .. versionchanged:: 5.0
+
+ Redefined in terms of `current()` instead of `instance()`.
+
+ .. deprecated:: 5.0
+
+ This method only knows about `IOLoop` objects (and not, for
+ example, `asyncio` event loops), so it is of limited use.
+ """
+ return IOLoop.current(instance=False) is not None
def install(self):
- """Installs this `IOLoop` object as the singleton instance.
+ """Deprecated alias for `make_current()`.
+
+ .. versionchanged:: 5.0
- This is normally not necessary as `instance()` will create
- an `IOLoop` on demand, but you may want to call `install` to use
- a custom subclass of `IOLoop`.
+ Previously, this method would set this `IOLoop` as the
+ global singleton used by `IOLoop.instance()`. Now that
+ `instance()` is an alias for `current()`, `install()`
+ is an alias for `make_current()`.
- When using an `IOLoop` subclass, `install` must be called prior
- to creating any objects that implicitly create their own
- `IOLoop` (e.g., :class:`tornado.httpclient.AsyncHTTPClient`).
+ .. deprecated:: 5.0
"""
- assert not IOLoop.initialized()
- IOLoop._instance = self
+ self.make_current()
@staticmethod
def clear_instance():
- """Clear the global `IOLoop` instance.
+ """Deprecated alias for `clear_current()`.
+
+ .. versionchanged:: 5.0
+
+ Previously, this method would clear the `IOLoop` used as
+ the global singleton by `IOLoop.instance()`. Now that
+ `instance()` is an alias for `current()`,
+ `clear_instance()` is an alias for `clear_instance()`.
+
+ .. deprecated:: 5.0
- .. versionadded:: 4.0
"""
- if hasattr(IOLoop, "_instance"):
- del IOLoop._instance
+ IOLoop.clear_current()
@staticmethod
def current(instance=True):
If an `IOLoop` is currently running or has been marked as
current by `make_current`, returns that instance. If there is
- no current `IOLoop`, returns `IOLoop.instance()` (i.e. the
- main thread's `IOLoop`, creating one if necessary) if ``instance``
- is true.
-
- In general you should use `IOLoop.current` as the default when
- constructing an asynchronous object, and use `IOLoop.instance`
- when you mean to communicate to the main thread from a different
- one.
+ no current `IOLoop` and ``instance`` is true, creates one.
.. versionchanged:: 4.1
Added ``instance`` argument to control the fallback to
`IOLoop.instance()`.
+ .. versionchanged:: 5.0
+ The ``instance`` argument now controls whether an `IOLoop`
+ is created automatically when there is none, instead of
+ whether we fall back to `IOLoop.instance()` (which is now
+ an alias for this method)
"""
current = getattr(IOLoop._current, "instance", None)
if current is None and instance:
- return IOLoop.instance()
+ current = IOLoop()
+ if IOLoop._current.instance is not current:
+ raise RuntimeError("new IOLoop did not become current")
return current
def make_current(self):
@staticmethod
def clear_current():
+ """Clears the `IOLoop` for the current thread.
+
+ Intended primarily for use by test frameworks in between tests.
+ """
IOLoop._current.instance = None
@classmethod
# Clean up Subprocess, so it can be used again with a new ioloop.
Subprocess.uninitialize()
self.io_loop.clear_current()
- if (not IOLoop.initialized() or
- self.io_loop is not IOLoop.instance()):
- # Try to clean up any file descriptors left open in the ioloop.
- # This avoids leaks, especially when tests are run repeatedly
- # in the same process with autoreload (because curl does not
- # set FD_CLOEXEC on its file descriptors)
- self.io_loop.close(all_fds=True)
+ # Try to clean up any file descriptors left open in the ioloop.
+ # This avoids leaks, especially when tests are run repeatedly
+ # in the same process with autoreload (because curl does not
+ # set FD_CLOEXEC on its file descriptors)
+ self.io_loop.close(all_fds=True)
super(AsyncTestCase, self).tearDown()
# In case an exception escaped or the StackContext caught an exception
# when there wasn't a wait() to re-raise it, do so here.
self.http_server.stop()
self.io_loop.run_sync(self.http_server.close_all_connections,
timeout=get_async_test_timeout())
- if (not IOLoop.initialized() or
- self.http_client.io_loop is not IOLoop.instance()):
- self.http_client.close()
+ self.http_client.close()
super(AsyncHTTPTestCase, self).tearDown()