13. SubTask
subtaskオブジェクトは、既存の動作スクリプト(メインスクリプト
)とは別のメモリ空間上で新たな動作スクリプト(サブスクリプト
)を実行する機能を提供する組み込みオブジェクトです。
メインスクリプト上の処理をサブスクリプトに分散することで、メインスクリプトの簡素化、メインスクリプト上の使用メモリの低減が可能となります。
機能概要:
- メインスクリプトとは別のメモリ空間上でサブスクリプトを実行する機能を提供します。
- メインスクリプトとサブスクリプト間でデータを送受信する機能を提供します。
制限事項:
- サブスクリプト上では拡張オブジェクトを使用することはできません。
サブスクリプト上で使用可能なグローバルスコープ関数についてはこちらを参照してください。 - 同時実行可能なサブスクリプト数は
8
です。 - 本機能はNEQTO Engine for Linux専用の拡張オプションです。
サブスクリプト上で使用可能なメモリサイズ設定、サブスクリプト数に応じて、システムメモリ(RAM)を消費します。
subtask Global Object
Methods()/Properties | Summary | Version | Note |
---|---|---|---|
subtask.run() | サブスクリプトを実行します。 | 00.02.00+ |
subtask.run(script[,callback][,heapSize])
サブスクリプトを実行します。
尚、生成されたインスタンスはサブスクリプト終了とともに解放されます。
Name | Type | M/O | Summary | Note |
---|---|---|---|---|
script | string, function | mandatory | 実行するスクリプトコードを文字列で指定します。 分割されたスクリプトコードを結合順に返却するコールバック関数を指定します。コールバックの戻り値には、スクリプトコードを文字列で返却し、終了時にnullを返却します。本メソッドは、nullが指定されるまでスクリプトコード文字列の連結を行います。 | |
callback (str, num) | function | optional | サブスクリプトから任意文字列および任意数値を受け取った際にコールバック処理を実行します。 str: {string} num: {number} このコールバックの戻り値には、サブスクリプト側に通知する数値型の任意リターンコードを指定することができます。指定がない場合は、0が通知されます。 又、サブスクリプトが終了する際にコールバック処理を実行します。 str: undefined num: undefined | |
heapSize | number | optional | サブスクリプト上で使用可能なメモリサイズ[Byte]を指定します。 設定範囲: 1024~524288 省略した場合はメインスクリプトと同じメモリサイズが割り当てられます。 | 範囲外の場合は、最も近い有効値に丸められます。 |
return | {Eval} | - | {Eval} : 生成された{Eval} |
{Eval}
Methods()/Properties | Summary | Version | Note |
---|---|---|---|
.write() ⁽¹⁾ | 実行中のサブスクリプトに任意文字列および任意数値を送信します。 | ||
.write() ⁽²⁾ | 実行中のサブスクリプトにコールバックを介して任意文字列および任意数値を送信します。 | ||
.writeSync() | 実行中のサブスクリプトに任意文字列および任意数値を送信し、サブスクリプト側の読み出し完了を待ちます。 | ||
.abort() | 実行中のサブスクリプトを強制的に終了します。 |
Details
.write(str[,num])
実行中のサブスクリプトに任意文字列および任意数値を送信します。
Name | Type | M/O | Summary | Note |
---|---|---|---|---|
str | string | mandatory | 任意文字列 | |
num | number | optional | 任意数値 デフォルト値は0となります。 | |
return | boolean | - | true : 成功 false : 失敗 | サブスクリプト側が前回送信した任意文字列および任意数値をまだ読み出していない場合、falseが返却されます。 異常が発生した時は、例外となります。 |
.write(callback)
実行中のサブスクリプトにコールバックを介して任意文字列および任意数値を送信します。
Name | Type | M/O | Summary | Note |
---|---|---|---|---|
callback() | function | mandatory | サブスクリプト側が任意文字列および任意数値を受け取り可能な状態である時、定期的にコールバック処理を実行します。 サブスクリプトに送信する任意文字列および任意数値がある場合、コールバックの戻り値で{Element}を返却し、何もない場合は、nullを返却します。{Element}が指定された場合、サブスクリプトがそれを読み出すまで、次のコールバックは発生しません。 | |
return | undefined | - | - | 異常が発生した時は、例外となります。 |
{Element}
Name | Type | M/O | Summary | Note |
---|---|---|---|---|
.str | string | mandatory | 任意文字列 | |
.num | number | optional | 任意数値 デフォルト値は0となります。 |
.writeSync(str[,num[,timeout]])
実行中のサブスクリプトに任意文字列および任意数値を送信し、サブスクリプト側の読み出し完了を待ちます。
このメソッドはブロッキングで処理されます。
Name | Type | M/O | Summary | Note |
---|---|---|---|---|
str | string | mandatory | 任意文字列 | |
num | number | optional | 任意数値 デフォルト値は0となります。 | |
timeout | number | optional | タイムアウト値[ms]を指定します。 設定範囲: 0~3600000 0の場合、タイムアウト無効となります。 デフォルト値は0となります。 | 範囲外の場合は、最も近い有効値に丸められます。 |
return | boolean | - | true : 成功 false : 失敗 | タイムアウトが発生した場合、falseが返却されます。 異常が発生した時は、例外となります。 |
.abort()
実行中のサブスクリプトを強制的に終了します。
同時に、インスタンスが解放されます。
Name | Type | M/O | Summary | Note |
---|---|---|---|---|
return | undefined | - | - |
サブスクリプト上で使用可能なグローバルスコープ関数
Functions | Summary | Version | Note |
---|---|---|---|
read() | メインスクリプトから送信された任意文字列および任意数値を読み出します。 | 00.02.00+ | |
callback() | メインスクリプトに任意文字列および任意数値を送信します。 | 00.02.00+ | |
wait() | ウェイト(遅延)を挿入します。 | 00.02.00+ | |
print() | ログを出力します。 | 00.02.00+ | |
heap() | サブスクリプト上のメモリ使用量を取得します。 | 00.02.00+ |
Details
read()
メインスクリプトから送信された任意文字列および任意数値を読み出します。
Name | Type | M/O | Summary | Note |
---|---|---|---|---|
return | {Element}, null | - | {Element}: 読み出された要素 null : 読み出し要素なし |
{Element}
Name | Type | Summary | Note |
---|---|---|---|
.str | string | 任意文字列 | |
.num | number | 任意数値 |
callback(str[,num])
メインスクリプトに任意文字列および任意数値を送信します。
この関数を実行すると、メインスクリプト側ではsubtask.run()で指定したコールバック関数が呼び出されます。
Name | Type | M/O | Summary | Note |
---|---|---|---|---|
str | string | mandatory | 任意文字列 | |
num | number | optional | 任意数値 デフォルト値は0となります。 | |
return | number, undefined | - | メインスクリプト側のコールバック関数から通知された任意リターンコード | メインスクリプト側のコールバック関数が未設定の場合、undefinedが返却されます。 異常が発生した時は、例外となります。 |
wait(time)
ウェイト(遅延)を挿入します。
サブスクリプト処理を一時的に待ちとして、メインスクリプト側の処理を優先させることができます。
Name | Type | M/O | Summary | Note |
---|---|---|---|---|
time | number | mandatory | 待機時間[ms]を指定します。 設定範囲: 1~4,294,967,295 | 待機時間は1msから設定可能ですが、内部処理遅延によるタイムラグが発生する場合があることに注意してください。 |
return | undefined | - | - | パラメータ異常の場合は例外となります。 |
print(logMsg)
ログを出力します。
メインスクリプトのprint()
同様に使用可能です。
Name | Type | M/O | Summary | Note |
---|---|---|---|---|
logMsg | string | mandatory | 出力するログメッセージ | |
return | undefined | - | - | 異常が発生した時は、例外となります。 |
heap()
サブスクリプト上の使用メモリ情報を取得します。
Name | Type | M/O | Summary | Note |
---|---|---|---|---|
return | {HeapInfo} | - | {HeapInfo} : サブスクリプト上の使用メモリ情報 |
{HeapInfo}
Name | Type | Summary | Note |
---|---|---|---|
.total | number | 使用可能なメモリサイズ[Byte] | |
.current | number | 現時点の使用メモリサイズ[Byte] | |
.peak | number | 現時点での最大使用メモリサイズ[Byte] |
オブジェクトの使用例
Sample 1
サブスクリプトを実行し、結果を受け取るサンプルです。
var subEnd = false;
var subScr = `
var str = "abc";
var num = 123;
callback(str, num);
`;
var subInst = subtask.run(subScr, function(str, num) {
if((str === undefined) && (num === undefined)) {
print("subscript exit");
subEnd = true;
} else {
print(`str: ${str}, num: ${num}`);
}
});
while(!subEnd);
Sample 2
常駐型のサブスクリプトを実行し、結果を受け取るサンプルです。
var subEnd = false;
var subScr = `
var str = "abc";
var num = 123;
callback(str, num);
while(1);
`;
var subInst = subtask.run(subScr, function(str, num) {
if((str === undefined) && (num === undefined)) {
print("subscript exit");
} else {
print(`str: ${str}, num: ${num}`);
subEnd = true;
}
});
while(!subEnd);
subInst.abort();
Sample 3
常駐型のサブスクリプトを実行し、メインスクリプトから任意文字列を送信するサンプルです。
.writeSync()メソッドは、サブスクリプトが読み出し完了するまでの間、ブロッキングします。
var subEnd = false;
var subScr = `
while(1) {
var obj = read();
if(obj) {
print("cmd:", obj.str);
if(obj.str === "exit") break;
}
}
`;
var subInst = subtask.run(subScr, function(str, num) {
if((str === undefined) && (num === undefined)) {
print("subscript exit");
subEnd = true;
}
});
subInst.writeSync("abc");
subInst.writeSync("abcd");
subInst.writeSync("exit");
while(!subEnd);
Sample 4
常駐型のサブスクリプトを実行し、メインスクリプトから任意文字列を送信するサンプルです。
サブスクリプトが読み出し完了すると、.write()メソッドの戻り値がtrueとなります。
var subEnd = false;
var subScr = `
while(1) {
var obj = read();
if(obj) {
print("cmd:", obj.str);
if(obj.str === "exit") break;
}
wait(500);
}
`;
var subInst = subtask.run(subScr, function(str, num) {
if((str === undefined) && (num === undefined)) {
print("subscript exit");
subEnd = true;
}
});
var cmds = ["abc", "abcd", "exit"];
var index = 0;
while(!subEnd) {
if(cmds[index]) var ret = subInst.write(cmds[index]);
if(ret) index++;
}
Sample 5
常駐型のサブスクリプトを実行し、メインスクリプトから任意文字列を送信するサンプルです。
サブスクリプトが読み出し完了すると、.write()メソッドに指定したコールバック関数が定期的に呼ばれます。
var subEnd = false;
var subScr = `
while(1) {
var obj = read();
if(obj) {
print("cmd:", obj.str);
if(obj.str === "exit") break;
}
}
`;
var subInst = subtask.run(subScr, function(str, num) {
if((str === undefined) && (num === undefined)) {
print("subscript exit");
subEnd = true;
}
});
var index = 0;
var cmds = ["abc", "abcd", null, "exit"];
subInst.write(function() {
return {str:cmds[index++]};
});
while(!subEnd);
Sample 6
分割されたサブスクリプトコードを組み替えて活用するサンプルです。
var scrMain = `
while(1) {
var obj = read();
if(obj) {
var data = JSON.parse(obj.str);
var ret = calc(data.a, data.b);
print("result:", ret);
break;
}
}
`;
var scrCalcA = `var calc = function(a, b) { return a + b; };`;
var scrCalcB = `var calc = function(a, b) { return a - b; };`;
var callback = function(str, num) {
if((str === undefined) && (num === undefined)) {
print("subscript exit");
subEnd = true;
}
};
var subEnd = false;
var lineNum = 0;
var subInst = subtask.run(function() {
var scr = [scrCalcA, scrMain, null];
return scr[lineNum++];
}, callback);
subInst.write('{"a":3, "b":2}');
while(!subEnd);
subEnd = false;
lineNum = 0;
var subInst = subtask.run(function() {
var scr = [scrCalcB, scrMain, null];
return scr[lineNum++];
}, callback);
subInst.write('{"a":3, "b":2}');
while(!subEnd);
Sample 7
サブスクリプトを活用して、数値演算処理するサンプルです。
var subEnd = false;
var subScr = `
var sum = 0;
var end = false;
while(1) {
var obj = read();
if(obj) {
switch(obj.str) {
case "add":
sum = sum + obj.num;
break;
case "exit":
callback("", sum);
end = true;
break;
default:
break;
}
}
if(end) break;
}
`;
var subInst = subtask.run(subScr, function(str, num) {
if((str === undefined) && (num === undefined)) {
print("subTask exit");
subEnd = true;
} else {
print("sum: " + num);
}
});
for(var i=0; i<10;) {
var ret = subInst.write("add", i);
if(ret) i++;
}
subInst.writeSync("exit");
while(!subEnd);
Sample 8
メモリを多く消費する処理をサブスクリプトで実行するサンプルです。
サブスクリプトに処理を分散することで、メインスクリプトのメモリ消費量を削減します。
var subEnds = false;
var subScr = `
var size = 1024;
var buff = new Array(size);
var index = 0;
for(var i=0; i<size; i++) buff[i] = 0;
while(1) {
var obj = read();
if(obj) {
if(obj.str === "exit") {
var mem = heap();
print(\`total: \${mem.total}, current: \${mem.current}, peak: \${mem.peak}\`);
break;
}
buff[index++] = obj.num;
if(index >= size) index = 0;
var ave = 0;
for(var i=0; i<size; i++) ave = ave + buff[i];
ave = ave / size;
if(!(index % 512)) callback("value", ave);
}
}
`;
var subInst = subtask.run(subScr, function(str, num) {
if((str === undefined) && (num === undefined)) {
print("subTask exit");
subEnds = true;
} else {
print("ave:", num);
}
});
for(var i=0; i<2048; i++) {
subInst.writeSync("", 100 * Math.random());
}
subInst.writeSync("exit", 2);
while(!subEnds);
Sample 9
queueオブジェクトを活用して、メインスクリプトとサブスクリプト間をコマンドインタフェースするサンプルです。
var cmdQue = queue.create(4);
var rspQue = queue.create(4);
var subEnd = false;
var subScr = `
while(1) {
var obj = read();
if(obj) {
print("cmd:", obj.str, obj.num);
callback(obj.str + "2", obj.num + 10);
}
}
`;
var subInst = subtask.run(subScr, function(str, num) { rspQue.push(str, num); });
subInst.write(function() { return cmdQue.pop(); })
var index = 0;
var cmds = ["abc", "abcd", "abcde", "abcdef", "abcdefg"];
while(1) {
if(rspQue.getCount()) {
var obj = rspQue.pop();
print("rsp:", obj.str, obj.num);
}
if(index >= cmds.length) break;
cmdQue.push(cmds[index], index++);
setTimeout(1000).wait();
};
subInst.abort();
cmdQue.release();
rspQue.release();