13. SubTask
The subtask object is a built-in object that provides the ability to execute a new operation script (sub script
) in a separate memory space from the existing operation script (main script
).
By distributing the processing on the main script to the sub script, it is possible to simplify the main script and reduce the memory usage on the main script.
Functional overview:
- Provides a function to execute the sub script in a separate memory space from the main script.
- Provides a function for sending and receiving data between the main script and the sub script.
Limitations:
- It is not possible to use extension objects on the sub script.
For information about the global scope functions usable on the sub script, refer to here. - The number of sub scripts that can be executed simultaneously is
8
. - This feature is an extension option exclusively for the NEQTO Engine for Linux.
Depending on the memory size setting available for use on the sub script and the number of sub scripts, system memory (RAM) will be consumed.
subtask Global Object
Methods()/Properties | Summary | Version | Note |
---|---|---|---|
subtask.run() | Executes the sub script. | 00.02.00+ |
subtask.run(script[,callback][,heapSize])
Executes the sub script.
A generated instance is released when the sub script ends.
Name | Type | M/O | Summary | Note |
---|---|---|---|---|
script | string, function | mandatory | Specify the script code to be executed in string. Specify a callback function that returns the separated script code in the order to be combined. For the return value of the callback, return the script code in string, and then return null at the end. This method concatenates script code strings until null is specified. | |
callback (str, num) | function | optional | Executes callback processing when an arbitrary string and an arbitrary number are received from the sub script. str: {string} num: {number} In the return value of this callback, it is possible to specify an arbitrary return code of the numeric type that will be notified to the sub script side. If not specified, 0 will be notified. In addition, executes the callback processing when the sub script ends. str: undefined num: undefined | |
heapSize | number | optional | Specify the memory size [Byte] available for use on the sub script. Range: 1024 - 524288 If omitted, the same memory size as the main script will be allocated. | If out of range, it will be rounded to the nearest valid value. |
return | {Eval} | - | {Eval} : Generated {Eval} |
{Eval}
Methods()/Properties | Summary | Version | Note |
---|---|---|---|
.write() ⁽¹⁾ | Sends an arbitrary string and an arbitrary number to the running sub script. | ||
.write() ⁽²⁾ | Sends an arbitrary string and an arbitrary number to the running sub script via callback. | ||
.writeSync() | Sends an arbitrary string and an arbitrary number to the running sub script, and then waits for the sub script side to complete reading. | ||
.abort() | Aborts the running sub script. |
Details
.write(str[,num])
Sends an arbitrary string and an arbitrary number to the running sub script.
Name | Type | M/O | Summary | Note |
---|---|---|---|---|
str | string | mandatory | Arbitrary string | |
num | number | optional | Arbitrary number The default value is 0. | |
return | boolean | - | true : Success false : Failure | If the sub script side has not yet read the arbitrary string and arbitrary number sent last time, false will be returned. When an error occurs, an exception is raised. |
.write(callback)
Sends an arbitrary string and an arbitrary number to the running sub script via callback.
Name | Type | M/O | Summary | Note |
---|---|---|---|---|
callback() | function | mandatory | Periodically executes callback processing when the sub script is in a state ready to accept an arbitrary string and an arbitrary number. If there is an arbitrary string or an arbitrary number to be sent to the sub script, returns {Element} to the return value of the callback, and if there is nothing, returns null. If {Element} is specified, the next callback will not occur until the sub script reads it. | |
return | undefined | - | - | When an error occurs, an exception is raised. |
{Element}
Name | Type | M/O | Summary | Note |
---|---|---|---|---|
.str | string | mandatory | Arbitrary string | |
.num | number | optional | Arbitrary number The default value is 0. |
.writeSync(str[,num[,timeout]])
Sends an arbitrary string and an arbitrary number to the running sub script, and then waits for the sub script side to complete reading.
This method is executed by blocking.
Name | Type | M/O | Summary | Note |
---|---|---|---|---|
str | string | mandatory | Arbitrary string | |
num | number | optional | Arbitrary number The default value is 0. | |
timeout | number | optional | Specify the timeout value [ms]. Range: 0 - 3600000 If 0, timeout is disabled. The default value is 0. | If out of range, it will be rounded to the nearest valid value. |
return | boolean | - | true : Success false : Failure | If a timeout occurs, false is returned. When an error occurs, an exception is raised. |
.abort()
Aborts the running sub script.
At the same time, the instance is released.
Name | Type | M/O | Summary | Note |
---|---|---|---|---|
return | undefined | - | - |
Global scope functions usable on the sub script
Functions | Summary | Version | Note |
---|---|---|---|
read() | Reads an arbitrary string and an arbitrary number sent from the main script. | 00.02.00+ | |
callback() | Sends an arbitrary string and an arbitrary number to the main script. | 00.02.00+ | |
wait() | Inserts a wait (delay). | 00.02.00+ | |
print() | Prints the log message. | 00.02.00+ | |
heap() | Gets the memory usage information on the sub script. | 00.02.00+ |
Details
read()
Reads an arbitrary string and an arbitrary number sent from the main script.
Name | Type | M/O | Summary | Note |
---|---|---|---|---|
return | {Element}, null | - | {Element}: Read element null : No read element |
{Element}
Name | Type | Summary | Note |
---|---|---|---|
.str | string | Arbitrary string | |
.num | number | Arbitrary number |
callback(str[,num])
Sends an arbitrary string and an arbitrary number to the main script.
When this function is executed, the callback function specified in subtask.run() will be called on the main script side.
Name | Type | M/O | Summary | Note |
---|---|---|---|---|
str | string | mandatory | Arbitrary string | |
num | number | optional | Arbitrary number The default value is 0. | |
return | number, undefined | - | Arbitrary return code notified from the callback function on the main script side | If the callback function on the main script side is not set, undefined will be returned. When an error occurs, an exception is raised. |
wait(time)
Inserts a wait (delay).
It is possible to temporarily wait for the sub script processing and give priority to the main script side processing.
Name | Type | M/O | Summary | Note |
---|---|---|---|---|
time | number | mandatory | Specify the waiting time [ms]. Range: 1 - 4,294,967,295 | The waiting time can be set from 1ms, but note that there may be a time lag due to internal processing delays. |
return | undefined | - | - | If the parameter is abnormal, an exception occurs. |
print(logMsg)
Prints the log message.
It can be used in the same way as print()
in the main script.
Name | Type | M/O | Summary | Note |
---|---|---|---|---|
logMsg | string | mandatory | Message to output as log. | |
return | undefined | - | - | When an error occurs, an exception is raised. |
heap()
Gets the memory usage information on the sub script.
Name | Type | M/O | Summary | Note |
---|---|---|---|---|
return | {HeapInfo} | - | {HeapInfo} : Memory usage information on the sub script |
{HeapInfo}
Name | Type | Summary | Note |
---|---|---|---|
.total | number | Available memory size [Byte] | |
.current | number | Current usage memory size [Byte] | |
.peak | number | Maximum memory usage size to date [Byte] |
Object Usage Examples
Sample 1
This is a sample that executes the sub script and receives the result.
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
This is a sample that executes the resident sub script and receives the result.
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
This is a sample that executes the resident sub script and sends an arbitrary string from the main script.
The .writeSync() method blocks until the sub script reads it.
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
This is a sample that executes the resident sub script and sends an arbitrary string from the main script.
When reading is completed in the sub script, the return value of the .write() method will be 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
This is a sample that executes the resident sub script and sends an arbitrary string from the main script.
When reading is completed in the sub script, the callback function specified in the .write() method will be called periodically.
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
This is a sample that rearranges and utilizes the separated sub script code.
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
This is a sample that utilizes the sub script to perform numerical calculations.
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
This is a sample that executes a process that consumes a lot of memory using the sub script.
By distributing the processing to the sub script, the memory consumption of the main script is reduced.
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
This is a sample that utilizes the queue object to interface commands between the main script and the sub script.
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();