All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.olivergondza.dumpling.model.ProcessRuntime Maven / Gradle / Ivy

/*
 * The MIT License
 *
 * Copyright (c) 2014 Red Hat, Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
package com.github.olivergondza.dumpling.model;

import java.io.PrintStream;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.Set;

import javax.annotation.Nonnull;

import com.github.olivergondza.dumpling.factory.IllegalRuntimeStateException;
import com.github.olivergondza.dumpling.query.SingleThreadSetQuery;

/**
 * Snapshot of threads in JVM at given time.
 *
 * @author ogondza
 */
public abstract class ProcessRuntime<
        RuntimeType extends ProcessRuntime,
        SetType extends ThreadSet,
        ThreadType extends ProcessThread
> extends ModelObject {

    private final @Nonnull SetType threads;
    private final @Nonnull SetType emptySet;

    public ProcessRuntime(@Nonnull Set> builders) {
        this.threads = createThreads(builders);
        this.emptySet = createSet(Collections.emptySet());
        checkSanity();
    }

    private @Nonnull SetType createThreads(@Nonnull Set> builders) {
        Set threads = new LinkedHashSet(builders.size());
        for (ProcessThread.Builder builder: builders) {
            threads.add(createThread(builder));
        }

        int buildersSize = builders.size();
        int threadsSize = threads.size();
        if (buildersSize != threadsSize) throw new IllegalRuntimeStateException(
                "%d builders produced %d threads", buildersSize, threadsSize
        );

        return createSet(Collections.unmodifiableSet(threads));
    }

    private void checkSanity() {
        // At most one thread should own the monitor/synchronizer
        HashMap monitors = new HashMap();
        HashMap synchronizers = new HashMap();
        for (ThreadType t: threads) {
            for (ThreadLock lock: t.getAcquiredMonitors()) {
                ThreadType existing = monitors.put(lock, t);
                if (existing != null) {
                    throw new IllegalRuntimeStateException(
                            "Multiple threads own the same monitor '%s':%n%s%n%nAND%n%n%s%n",
                            lock, existing, t
                    );
                }
            }

            for (ThreadLock lock: t.getAcquiredSynchronizers()) {
                ThreadType existing = synchronizers.put(lock, t);
                if (existing != null) {
                    throw new IllegalRuntimeStateException(
                            "Multiple threads own the same synchronizer '%s':%n%s%n%nAND%n%n%s%n",
                            lock, existing, t
                    );
                }
            }
        }
    }

    protected abstract @Nonnull SetType createSet(@Nonnull Set threads);

    protected abstract @Nonnull ThreadType createThread(@Nonnull ProcessThread.Builder builder);

    /**
     * All threads in current runtime.
     */
    public @Nonnull SetType getThreads() {
        return threads;
    }

    public @Nonnull SetType getEmptyThreadSet() {
        return emptySet;
    }

    /**
     * Instantiate {@link ThreadSet} scoped to this runtime.
     */
    public @Nonnull SetType getThreadSet(@Nonnull Collection threads) {
        if (threads.isEmpty()) return emptySet;

        Set threadSet = threads instanceof Set
                ? (Set) threads
                : new LinkedHashSet(threads)
        ;
        return createSet(threadSet);
    }

    /**
     * Run query against all threads in the runtime.
     *
     * @see ThreadSet#query(SingleThreadSetQuery)
     */
    public > T query(SingleThreadSetQuery query) {
        return threads.query(query);
    }

    @Override
    public void toString(PrintStream stream, Mode mode) {
        threads.toString(stream, mode);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy