diff --git a/src/Netscript/WorkerScript.ts b/src/Netscript/WorkerScript.ts index 6b99c43d5..726af7c84 100644 --- a/src/Netscript/WorkerScript.ts +++ b/src/Netscript/WorkerScript.ts @@ -80,6 +80,12 @@ export class WorkerScript { */ output: string = ""; + /** + * Process ID. Must be an integer. Used for efficient script + * killing and removal. + */ + pid: number; + /** * Script's Static RAM usage. Equivalent to underlying script's RAM usage */ @@ -100,10 +106,17 @@ export class WorkerScript { */ serverIp: string; - constructor(runningScriptObj: RunningScript, nsFuncsGenerator?: (ws: WorkerScript) => object) { + constructor(runningScriptObj: RunningScript, pid: number, nsFuncsGenerator?: (ws: WorkerScript) => object) { this.name = runningScriptObj.filename; this.serverIp = runningScriptObj.server; + const sanitizedPid = Math.round(pid); + if (typeof sanitizedPid !== "number" || isNaN(sanitizedPid)) { + throw new Error(`Invalid PID when constructing WorkerScript: ${pid}`); + } + this.pid = sanitizedPid; + runningScriptObj.pid = sanitizedPid; + // Get the underlying script's code const server = AllServers[this.serverIp]; if (server == null) { diff --git a/src/Netscript/WorkerScripts.ts b/src/Netscript/WorkerScripts.ts index 50515f413..58c184314 100644 --- a/src/Netscript/WorkerScripts.ts +++ b/src/Netscript/WorkerScripts.ts @@ -3,4 +3,4 @@ */ import { WorkerScript } from "./WorkerScript"; -export const workerScripts: WorkerScript[] = []; +export const workerScripts: Map = new Map(); diff --git a/src/NetscriptWorker.js b/src/NetscriptWorker.js index 095ba401d..cb8a355ae 100644 --- a/src/NetscriptWorker.js +++ b/src/NetscriptWorker.js @@ -407,6 +407,42 @@ function processNetscript1Imports(code, workerScript) { return res; } +/** + * + */ +let pidCounter = 1; +function generateNextPid() { + let tempCounter = pidCounter; + + // Cap the number of search iterations at some arbitrary value to avoid + // infinite loops. We'll assume that players wont have 1mil+ running scripts + let found = false; + for (let i = 0; i < 1e6;) { + if (!workerScripts.has(tempCounter + i)) { + found = true; + tempCounter = tempCounter + i; + break; + } + + if (i === Number.MAX_SAFE_INTEGER - 1) { + i = 1; + } else { + ++i; + } + } + + if (found) { + pidCounter = tempCounter + 1; + if (pidCounter >= Number.MAX_SAFE_INTEGER) { + pidCounter = 1; + } + + return tempCounter; + } else { + return -1; + } +} + /** * Start a script * @@ -438,8 +474,17 @@ export function addWorkerScript(runningScriptObj, server) { } server.ramUsed = roundToTwo(server.ramUsed + ramUsage); + // Get the pid + const pid = getNextPid(); + if (pid === -1) { + throw new Error( + `Failed to start script because could not find available PID. This is most ` + + `because you have too many scripts running.` + ); + } + // Create the WorkerScript - const s = new WorkerScript(runningScriptObj, NetscriptFunctions); + const s = new WorkerScript(runningScriptObj, pid, NetscriptFunctions); s.ramUsage = ramUsage; // Start the script's execution diff --git a/src/Script/RunningScript.ts b/src/Script/RunningScript.ts index 59bde86b2..f3f9b617c 100644 --- a/src/Script/RunningScript.ts +++ b/src/Script/RunningScript.ts @@ -56,6 +56,9 @@ export class RunningScript { // Number of seconds that this script has been running online onlineRunningTime: number = 0.01; + // Process ID. Must be an integer and equals the PID of corresponding WorkerScript + pid: number = -1; + // How much RAM this script uses for ONE thread ramUsage: number = 0;