Home / Class/ Watcher Class — netty Architecture

Watcher Class — netty Architecture

Architecture documentation for the Watcher class in ThreadDeathWatcher.java from the netty codebase.

Entity Profile

Dependency Diagram

graph TD
  5f6d0707_3005_8256_7c2d_19661826552d["Watcher"]
  e4597d51_0c3d_f1d3_89b7_46f963dc242f["ThreadDeathWatcher.java"]
  5f6d0707_3005_8256_7c2d_19661826552d -->|defined in| e4597d51_0c3d_f1d3_89b7_46f963dc242f
  2e12d8f3_2a76_c115_2e1f_27af3c853d54["run()"]
  5f6d0707_3005_8256_7c2d_19661826552d -->|method| 2e12d8f3_2a76_c115_2e1f_27af3c853d54
  d63c9c90_1e42_7586_aab0_7f19f87736ba["fetchWatchees()"]
  5f6d0707_3005_8256_7c2d_19661826552d -->|method| d63c9c90_1e42_7586_aab0_7f19f87736ba
  666cccad_fc12_bc19_59b3_051276b803c6["notifyWatchees()"]
  5f6d0707_3005_8256_7c2d_19661826552d -->|method| 666cccad_fc12_bc19_59b3_051276b803c6

Relationship Graph

Source Code

common/src/main/java/io/netty/util/ThreadDeathWatcher.java lines 146–228

    private static final class Watcher implements Runnable {

        private final List<Entry> watchees = new ArrayList<Entry>();

        @Override
        public void run() {
            for (;;) {
                fetchWatchees();
                notifyWatchees();

                // Try once again just in case notifyWatchees() triggered watch() or unwatch().
                fetchWatchees();
                notifyWatchees();

                try {
                    Thread.sleep(1000);
                } catch (InterruptedException ignore) {
                    // Ignore the interrupt; do not terminate until all tasks are run.
                }

                if (watchees.isEmpty() && pendingEntries.isEmpty()) {

                    // Mark the current worker thread as stopped.
                    // The following CAS must always success and must be uncontended,
                    // because only one watcher thread should be running at the same time.
                    boolean stopped = started.compareAndSet(true, false);
                    assert stopped;

                    // Check if there are pending entries added by watch() while we do CAS above.
                    if (pendingEntries.isEmpty()) {
                        // A) watch() was not invoked and thus there's nothing to handle
                        //    -> safe to terminate because there's nothing left to do
                        // B) a new watcher thread started and handled them all
                        //    -> safe to terminate the new watcher thread will take care the rest
                        break;
                    }

                    // There are pending entries again, added by watch()
                    if (!started.compareAndSet(false, true)) {
                        // watch() started a new watcher thread and set 'started' to true.
                        // -> terminate this thread so that the new watcher reads from pendingEntries exclusively.
                        break;
                    }

                    // watch() added an entry, but this worker was faster to set 'started' to true.
                    // i.e. a new watcher thread was not started
                    // -> keep this thread alive to handle the newly added entries.
                }
            }
        }

        private void fetchWatchees() {
            for (;;) {
                Entry e = pendingEntries.poll();
                if (e == null) {
                    break;
                }

                if (e.isWatch) {
                    watchees.add(e);
                } else {
                    watchees.remove(e);
                }
            }
        }

        private void notifyWatchees() {
            List<Entry> watchees = this.watchees;
            for (int i = 0; i < watchees.size();) {
                Entry e = watchees.get(i);
                if (!e.thread.isAlive()) {
                    watchees.remove(i);
                    try {
                        e.task.run();
                    } catch (Throwable t) {
                        logger.warn("Thread death watcher task raised an exception:", t);
                    }
                } else {
                    i ++;
                }
            }

Frequently Asked Questions

What is the Watcher class?
Watcher is a class in the netty codebase, defined in common/src/main/java/io/netty/util/ThreadDeathWatcher.java.
Where is Watcher defined?
Watcher is defined in common/src/main/java/io/netty/util/ThreadDeathWatcher.java at line 146.

Analyze Your Own Codebase

Get architecture documentation, dependency graphs, and domain analysis for your codebase in minutes.

Try Supermodel Free