<commit_before>package org.rubyforge.debugcommons.model;

import java.io.File;
import org.rubyforge.debugcommons.RubyDebuggerException;
import org.rubyforge.debugcommons.RubyDebuggerProxy;
import org.rubyforge.debugcommons.Util;
import org.rubyforge.debugcommons.model.RubyEntity;
import org.rubyforge.debugcommons.model.RubyThread;

public final class RubyDebugTarget extends RubyEntity {
    
    private final Process process;
    private final int port;
    private final String debuggedFile;
    private final File baseDir;
    
    private boolean terminated;
    private RubyThread[] threads;
    
    public RubyDebugTarget(RubyDebuggerProxy proxy, Process process, int port,
            String debuggedFile, File baseDir) {
        super(proxy);
        this.process = process;
        this.port = port;
        this.debuggedFile = new File(debuggedFile).getName();
        this.baseDir = baseDir;
        this.threads = new RubyThread[0];
    }
    
    public Process getProcess() {
        return process;
    }
    
    public int getPort() {
        return port;
    }
    
    public String getDebuggedFile() {
        return debuggedFile;
    }
    
    public File getBaseDir() {
        return baseDir;
    }
    
    public void updateThreads() throws RubyDebuggerException {
        // preconditions:
        // 1) both threadInfos and updatedThreads are sorted by their id attribute
        // 2) once a thread has died its id is never reused for new threads again.
        //    Instead each new thread gets an id which is the currently highest id + 1.
        
        Util.fine("udpating threads");
        RubyThreadInfo[] threadInfos = getProxy().readThreadInfo();
        RubyThread[] updatedThreads = new RubyThread[threadInfos.length];
        int threadIndex = 0;
        for (int i = 0; i < threadInfos.length; i++) {
            while (threadIndex < threads.length && threadInfos[i].getId() != threads[threadIndex].getId()) {
                // step over dead threads, which do not occur in threadInfos anymore
                threadIndex += 1;
            }
            if (threadIndex == threads.length) {
                updatedThreads[i] = new RubyThread(this, threadInfos[i].getId());
            } else {
                updatedThreads[i] = threads[threadIndex];
            }
        }
        threads = updatedThreads;
    }
    
    public void suspensionOccurred(SuspensionPoint suspensionPoint) {
        try {
            updateThreads();
        } catch (RubyDebuggerException e) {
            throw new RuntimeException("Cannot update threads", e);
        }
        RubyThread thread = getThreadById(suspensionPoint.getThreadId());
        if (thread == null) {
            Util.warning("Thread with id " + suspensionPoint.getThreadId() + " was not found");
            return;
        }
        thread.suspend(suspensionPoint);
    }
    
    public RubyThread getThreadById(int id) {
        for (RubyThread thread : threads) {
            if (thread.getId() == id) {
                return thread;
            }
        }
        return null;
    }
    
    public boolean isRunning() {
        try {
            process.exitValue();
            return false;
        } catch (IllegalThreadStateException ex) {
            // not yet finished, normal behaviour why does java.lang.Process
            // does not have a function like isRunning()?
            return true;
        }
    }
    
}
<commit_msg>Just documenting fact the getThreadById might return null<commit_after>package org.rubyforge.debugcommons.model;

import java.io.File;
import org.rubyforge.debugcommons.RubyDebuggerException;
import org.rubyforge.debugcommons.RubyDebuggerProxy;
import org.rubyforge.debugcommons.Util;
import org.rubyforge.debugcommons.model.RubyEntity;
import org.rubyforge.debugcommons.model.RubyThread;

public final class RubyDebugTarget extends RubyEntity {
    
    private final Process process;
    private final int port;
    private final String debuggedFile;
    private final File baseDir;
    
    private boolean terminated;
    private RubyThread[] threads;
    
    public RubyDebugTarget(RubyDebuggerProxy proxy, Process process, int port,
            String debuggedFile, File baseDir) {
        super(proxy);
        this.process = process;
        this.port = port;
        this.debuggedFile = new File(debuggedFile).getName();
        this.baseDir = baseDir;
        this.threads = new RubyThread[0];
    }
    
    public Process getProcess() {
        return process;
    }
    
    public int getPort() {
        return port;
    }
    
    public String getDebuggedFile() {
        return debuggedFile;
    }
    
    public File getBaseDir() {
        return baseDir;
    }
    
    public void updateThreads() throws RubyDebuggerException {
        // preconditions:
        // 1) both threadInfos and updatedThreads are sorted by their id attribute
        // 2) once a thread has died its id is never reused for new threads again.
        //    Instead each new thread gets an id which is the currently highest id + 1.
        
        Util.fine("udpating threads");
        RubyThreadInfo[] threadInfos = getProxy().readThreadInfo();
        RubyThread[] updatedThreads = new RubyThread[threadInfos.length];
        int threadIndex = 0;
        for (int i = 0; i < threadInfos.length; i++) {
            while (threadIndex < threads.length && threadInfos[i].getId() != threads[threadIndex].getId()) {
                // step over dead threads, which do not occur in threadInfos anymore
                threadIndex += 1;
            }
            if (threadIndex == threads.length) {
                updatedThreads[i] = new RubyThread(this, threadInfos[i].getId());
            } else {
                updatedThreads[i] = threads[threadIndex];
            }
        }
        threads = updatedThreads;
    }
    
    public void suspensionOccurred(SuspensionPoint suspensionPoint) {
        try {
            updateThreads();
        } catch (RubyDebuggerException e) {
            throw new RuntimeException("Cannot update threads", e);
        }
        RubyThread thread = getThreadById(suspensionPoint.getThreadId());
        if (thread == null) {
            Util.warning("Thread with id " + suspensionPoint.getThreadId() + " was not found");
            return;
        }
        thread.suspend(suspensionPoint);
    }
    
    /**
     * Look up Ruby thread corresponding to the given id.
     *
     * @return {@link RubyThread} instance or <code>null</code> if no thread if
     *          found.
     */
    public RubyThread getThreadById(int id) {
        for (RubyThread thread : threads) {
            if (thread.getId() == id) {
                return thread;
            }
        }
        return null;
    }
    
    public boolean isRunning() {
        try {
            process.exitValue();
            return false;
        } catch (IllegalThreadStateException ex) {
            // not yet finished, normal behaviour why does java.lang.Process
            // does not have a function like isRunning()?
            return true;
        }
    }
    
}

{'fraction_non_alphanumeric': 0.0865546218487395, 'fraction_numerical': 0.00196078431372549, 'mean_word_length': 2.0926808142052837, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1214949', 'n_tokens_mistral': 1920, 'n_tokens_neox': 1848, 'n_words': 533}