added sync pausing...

Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
Alex A. Naanou 2020-12-02 21:02:38 +03:00
parent 33fc1d06d1
commit b440426bb6
2 changed files with 44 additions and 40 deletions

View File

@ -1,6 +1,6 @@
{
"name": "ig-types",
"version": "5.0.33",
"version": "5.0.34",
"description": "Generic JavaScript types and type extensions...",
"main": "main.js",
"scripts": {

View File

@ -65,12 +65,17 @@ object.Constructor('Queue', Array, {
}, events.EventMixin('flat', {
// config...
//
// Number of tasks to be running at the same time...
pool_size: 8,
// XXX revise defaults...
poling_delay: 50,
idle_poling_delay: 200,
// Number of tasks to run in a row before letting go of the exec
// frame...
pause_after_sync: 4,
// XXX revise defaults...
busy_timeout: 50,
poling_timeout: 200,
pause_timeout: 0,
auto_stop: false,
@ -184,6 +189,8 @@ object.Constructor('Queue', Array, {
// NOTE: we do not store the exec results...
// NOTE: not intended for direct use and will likely have no effect
// if called directly...
//
// XXX will this be collected by the GC if it is polling???
__running: null,
__run_tasks__: function(sync){
var that = this
@ -194,11 +201,26 @@ object.Constructor('Queue', Array, {
: !!sync
var run = function(){
// handle queue...
var c = 0
var pause = this.pause_after_sync
var running = this.__running || []
// run queue...
while(this.length > 0
&& this.state == 'running'
&& (this.__running || []).length < this.pool_size){
this.runTask(this.__run_tasks__.bind(this)) }
// do not exceed pool size...
&& running.length < this.pool_size
// do not run too many sync tasks without a break...
&& (pause == null
|| c < pause)){
var p = running.length
this.runTask(this.__run_tasks__.bind(this))
// NOTE: only count sync stuff that does not get added
// to the pool...
p == running.length
&& c++ }
// empty queue -> pole or stop...
//
@ -207,30 +229,32 @@ object.Constructor('Queue', Array, {
// - the queue is empty
// NOTE: we do not care about stopping the timer when changing
// state as .__run_tasks__() will stop itself...
//
// XXX will this be collected by the GC if it is polling???
if(this.state == 'running'){
var p
var timeout =
// idle -- empty queue...
this.length == 0 ?
this.poling_timeout
// busy poling -- pool full...
: c < pause ?
this.busy_timeout
// pause -- let other stuff run...
: (this.pause_timeout || 0)
;(this.length == 0 && this.auto_stop) ?
// auto-stop...
(this.idle_poling_delay ?
(timeout != null ?
// wait a bit then stop if still empty...
setTimeout(function(){
that.length > 0 ?
that.__run_tasks__()
: that.stop()
}, this.idle_poling_delay)
}, timeout)
// stop now...
: this.stop())
// pole...
// NOTE: there can be two poling states:
// - idle poling - when queue is empty
// - busy poling - when pool is full
: (p = this.length == 0 ?
this.idle_poling_delay
: this.poling_delay)
// pole / pause...
: timeout != null
&& setTimeout(
this.__run_tasks__.bind(this), p) } }.bind(this)
this.__run_tasks__.bind(this), timeout) } }.bind(this)
this.state == 'running'
&& (sync ?
@ -380,26 +404,6 @@ object.Constructor('Queue', Array, {
this.trigger('stop') } },
/*/ trigger .tasksAdded(..) when stuff is added to queue...
// XXX EXPERIMENTAL...
// XXX this messes up how devtools/node print this object...
// ...everything works as expected but looks ugly...
// XXX another potential issue here is the opposite of the overload
// approach, this is too strong and we will need to go around
// it if we need for instance to shift around around...
__new__: function(context, ...args){
return new Proxy(
Reflect.construct(Queue.__proto__, args, Queue),
{
set: function(queue, prop, value, receiver){
parseInt(prop) == prop
&& queue.trigger('tasksAdded', [value])
return Reflect.set(...arguments) },
}) },
//*/
// constructor argument handling...
//
// Queue()