collect-your-stuff 1.3.2 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/collections/arrayable/Arrayable.d.ts +2 -2
- package/dist/collections/arrayable/Arrayable.js +10 -0
- package/dist/collections/arrayable/Arrayable.min.js +1 -1
- package/dist/collections/doubly-linked-list/DoublyLinkedList.d.ts +14 -8
- package/dist/collections/doubly-linked-list/DoublyLinkedList.js +91 -56
- package/dist/collections/doubly-linked-list/DoublyLinkedList.min.js +1 -1
- package/dist/collections/linked-list/LinkedList.d.ts +14 -3
- package/dist/collections/linked-list/LinkedList.js +76 -32
- package/dist/collections/linked-list/LinkedList.min.js +1 -1
- package/dist/collections/linked-tree-list/LinkedTreeList.d.ts +9 -3
- package/dist/collections/linked-tree-list/LinkedTreeList.js +19 -21
- package/dist/collections/linked-tree-list/LinkedTreeList.min.js +1 -1
- package/dist/collections/queue/Queue.d.ts +35 -42
- package/dist/collections/queue/Queue.js +64 -80
- package/dist/collections/queue/Queue.min.js +1 -1
- package/dist/collections/queue/TaskQueue.d.ts +68 -0
- package/dist/collections/queue/TaskQueue.js +137 -0
- package/dist/collections/queue/TaskQueue.min.js +1 -0
- package/dist/collections/stack/Stack.d.ts +40 -40
- package/dist/collections/stack/Stack.js +73 -52
- package/dist/collections/stack/Stack.min.js +1 -1
- package/dist/collections/stack/TaskStack.d.ts +65 -0
- package/dist/collections/stack/TaskStack.js +107 -0
- package/dist/collections/stack/TaskStack.min.js +1 -0
- package/dist/main.d.ts +7 -1
- package/dist/main.js +16 -0
- package/dist/main.min.js +1 -1
- package/dist/recipes/IsQueue.d.ts +37 -0
- package/dist/recipes/IsQueue.js +5 -0
- package/dist/recipes/IsQueue.min.js +1 -0
- package/dist/recipes/IsStack.d.ts +36 -0
- package/dist/recipes/IsStack.js +5 -0
- package/dist/recipes/IsStack.min.js +1 -0
- package/package.json +1 -1
|
@@ -14,6 +14,13 @@ var _DoublyLinkedList = require('../doubly-linked-list/DoublyLinkedList')
|
|
|
14
14
|
* @memberOf module:collect-your-stuff
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
|
+
/**
|
|
18
|
+
* Use one of the accessors of DoublyLinkedList (which keeps track of the head, tail and length) for a LinkedTreeList.
|
|
19
|
+
* @param {string} name The accessor to use
|
|
20
|
+
* @param {LinkedTreeList} list The list to use it on
|
|
21
|
+
* @returns {*}
|
|
22
|
+
*/
|
|
23
|
+
const borrowedGetter = (name, list) => Object.getOwnPropertyDescriptor(_DoublyLinkedList.DoublyLinkedList.prototype, name).get.call(list)
|
|
17
24
|
/**
|
|
18
25
|
* LinkedTreeList represents a collection stored with a root and spreading in branching (tree) formation.
|
|
19
26
|
* @extends DoublyLinkedList
|
|
@@ -30,6 +37,10 @@ class LinkedTreeList {
|
|
|
30
37
|
this.innerList = null
|
|
31
38
|
/** Whether the inner list has been initialized (it can only be initialized once). */
|
|
32
39
|
this.initialized = false
|
|
40
|
+
/** The last linker, remembered so that adding to the end does not need to walk the whole list (null when not known yet). */
|
|
41
|
+
this.tailCache = null
|
|
42
|
+
/** The number of linkers, kept up to date by the list's own methods so that the length does not need to walk the whole list (null when not known yet). */
|
|
43
|
+
this.countCache = null
|
|
33
44
|
this.linkerClass = linkerClass
|
|
34
45
|
}
|
|
35
46
|
|
|
@@ -61,38 +72,24 @@ class LinkedTreeList {
|
|
|
61
72
|
* @returns {TreeLinker}
|
|
62
73
|
*/
|
|
63
74
|
get first () {
|
|
64
|
-
return this
|
|
75
|
+
return borrowedGetter('first', this)
|
|
65
76
|
}
|
|
66
77
|
|
|
67
78
|
/**
|
|
68
|
-
* Retrieve the last TreeLinker in the list.
|
|
79
|
+
* Retrieve the last TreeLinker in the list. The end is remembered, so this does not walk the list.
|
|
69
80
|
* @returns {TreeLinker}
|
|
70
81
|
*/
|
|
71
82
|
get last () {
|
|
72
|
-
|
|
73
|
-
if (tail === null) {
|
|
74
|
-
return null
|
|
75
|
-
}
|
|
76
|
-
let next = tail.next
|
|
77
|
-
while (next !== null) {
|
|
78
|
-
tail = next
|
|
79
|
-
next = tail.next
|
|
80
|
-
}
|
|
81
|
-
return tail
|
|
83
|
+
return borrowedGetter('last', this)
|
|
82
84
|
}
|
|
83
85
|
|
|
84
86
|
/**
|
|
85
|
-
* Return the length of the list.
|
|
87
|
+
* Return the length of the list. It is kept up to date by the list's own methods, so this does not walk the list
|
|
88
|
+
* (call reset() after linkers were changed directly).
|
|
86
89
|
* @returns {number}
|
|
87
90
|
*/
|
|
88
91
|
get length () {
|
|
89
|
-
|
|
90
|
-
let length = 0
|
|
91
|
-
while (current !== null) {
|
|
92
|
-
++length
|
|
93
|
-
current = current.next
|
|
94
|
-
}
|
|
95
|
-
return length
|
|
92
|
+
return borrowedGetter('length', this)
|
|
96
93
|
}
|
|
97
94
|
|
|
98
95
|
/**
|
|
@@ -201,7 +198,8 @@ class LinkedTreeList {
|
|
|
201
198
|
}
|
|
202
199
|
|
|
203
200
|
/**
|
|
204
|
-
* Refresh all references and return head
|
|
201
|
+
* Refresh all references (the head, the end and the length) by walking the list once, and return the head. The
|
|
202
|
+
* list's own methods keep these up to date, so this is only needed after linkers were changed directly.
|
|
205
203
|
* @return {TreeLinker}
|
|
206
204
|
*/
|
|
207
205
|
reset () {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.LinkedTreeList=void 0;var _TreeLinker=require("./TreeLinker"),_TreeLinkerIterator=require("../../recipes/TreeLinkerIterator"),_DoublyLinkedList=require("../doubly-linked-list/DoublyLinkedList");class LinkedTreeList{constructor(e=_TreeLinker.TreeLinker){this.classType=LinkedTreeList,this.innerList=null,this.initialized=!1,this.linkerClass=e}initialize(e){return this.initialized?(console.warn("Attempt to initialize LinkedTreeList which is not empty."),this):(this.initialized=!0,this.innerList=e,this)}get list(){return this.innerList}get first(){return this
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.LinkedTreeList=void 0;var _TreeLinker=require("./TreeLinker"),_TreeLinkerIterator=require("../../recipes/TreeLinkerIterator"),_DoublyLinkedList=require("../doubly-linked-list/DoublyLinkedList");const borrowedGetter=(e,t)=>Object.getOwnPropertyDescriptor(_DoublyLinkedList.DoublyLinkedList.prototype,e).get.call(t);class LinkedTreeList{constructor(e=_TreeLinker.TreeLinker){this.classType=LinkedTreeList,this.innerList=null,this.initialized=!1,this.tailCache=null,this.countCache=null,this.linkerClass=e}initialize(e){return this.initialized?(console.warn("Attempt to initialize LinkedTreeList which is not empty."),this):(this.initialized=!0,this.innerList=e,this)}get list(){return this.innerList}get first(){return borrowedGetter("first",this)}get last(){return borrowedGetter("last",this)}get length(){return borrowedGetter("length",this)}get parent(){return null===this.first?null:this.first.parent}set parent(e){let t=this.first;for(;null!==t;)t.parent=e,t=t.next;e&&(e.children=this)}get rootParent(){let e=this.first;if(!e)return null;let t=this.first.parent;for(;null!==t;)e=t,t=e.parent;return e}setChildren(e,t=null){Array.from(this).indexOf(e)<0&&console.error("item is not a child of this"),t.parent=e}insertAfter(e,t){return _DoublyLinkedList.DoublyLinkedList.prototype.insertAfter.call(this,e,t)}insertBefore(e,t){return _DoublyLinkedList.DoublyLinkedList.prototype.insertBefore.call(this,e,t)}append(e,t=this.last){return _DoublyLinkedList.DoublyLinkedList.prototype.append.call(this,e,t)}prepend(e,t=this.first){return _DoublyLinkedList.DoublyLinkedList.prototype.prepend.call(this,e,t)}remove(e){return _DoublyLinkedList.DoublyLinkedList.prototype.remove.call(this,e)}reset(){return _DoublyLinkedList.DoublyLinkedList.prototype.reset.call(this)}item(e){return _DoublyLinkedList.DoublyLinkedList.prototype.item.call(this,e)}forEach(e,t=this){let r=0,i=t.first;for(;null!==i;)e(i,r,t),i=i.next,++r;return t}[Symbol.iterator](){let e=this.rootParent;return new _TreeLinkerIterator.TreeLinkerIterator(e)}}exports.LinkedTreeList=LinkedTreeList,LinkedTreeList.fromArray=(e=[],t=_TreeLinker.TreeLinker,r=LinkedTreeList)=>new r(t).initialize(t.fromArray(e).head);
|
|
@@ -1,66 +1,59 @@
|
|
|
1
|
-
|
|
2
|
-
* @file queue
|
|
3
|
-
* @author Joshua Heagle <joshuaheagle@gmail.com>
|
|
4
|
-
* @version 1.1.0
|
|
5
|
-
* @memberOf module:collect-your-stuff
|
|
6
|
-
*/
|
|
7
|
-
import { Queueable } from './Queueable';
|
|
1
|
+
import { Linker } from '../linked-list/Linker';
|
|
8
2
|
import { IsArrayable } from '../../recipes/IsArrayable';
|
|
9
|
-
import {
|
|
10
|
-
import { completeResponse } from '../../recipes/Runnable';
|
|
3
|
+
import { IsQueue } from '../../recipes/IsQueue';
|
|
11
4
|
/**
|
|
12
|
-
*
|
|
5
|
+
* A first-in-first-out collection: items are added to the back with enqueue and taken from the front with dequeue.
|
|
6
|
+
* Any value can be queued (it is stored as it is, whether it is a function, an object or null), and adding and taking
|
|
7
|
+
* are constant time. To queue tasks which are run as they are taken use TaskQueue.
|
|
13
8
|
*/
|
|
14
|
-
export declare class Queue {
|
|
15
|
-
/** The list which stores the
|
|
9
|
+
export declare class Queue<T = any> implements IsQueue<T>, Iterable<T> {
|
|
10
|
+
/** The list which stores the queued items, the first is next to be dequeued. */
|
|
16
11
|
queuedList: IsArrayable<any>;
|
|
17
|
-
private
|
|
18
|
-
private queueableClass;
|
|
12
|
+
private readonly linkerClass;
|
|
19
13
|
/**
|
|
20
|
-
* Instantiate the queue with
|
|
21
|
-
* @param {
|
|
22
|
-
* @param {IsArrayable} [listClass=LinkedList] The type of list to create when no queued list is given
|
|
23
|
-
* @param {
|
|
14
|
+
* Instantiate the queue, optionally with a list of items to start from.
|
|
15
|
+
* @param {IsArrayable|null} [queuedList=null] The list of linkers to start in this queue (the first is the front)
|
|
16
|
+
* @param {IsArrayable} [listClass=LinkedList] The type of list to create when no queued list is given
|
|
17
|
+
* @param {Linker} [linkerClass=Linker] The class used to hold each queued item
|
|
24
18
|
*/
|
|
25
|
-
constructor(queuedList?: IsArrayable<any
|
|
19
|
+
constructor(queuedList?: IsArrayable<any> | null, listClass?: any, linkerClass?: typeof Linker);
|
|
26
20
|
/**
|
|
27
|
-
* Take
|
|
28
|
-
*
|
|
29
|
-
* completed tasks are discarded.
|
|
30
|
-
* @return {completeResponse|*}
|
|
21
|
+
* Take the item from the front of the queue.
|
|
22
|
+
* @return {*|null} The item, or null when the queue is empty
|
|
31
23
|
*/
|
|
32
|
-
dequeue():
|
|
24
|
+
dequeue(): T | null;
|
|
33
25
|
/**
|
|
34
|
-
*
|
|
26
|
+
* Check whether the queue has no items.
|
|
35
27
|
* @return {boolean}
|
|
36
28
|
*/
|
|
37
29
|
empty(): boolean;
|
|
38
30
|
/**
|
|
39
|
-
* Add
|
|
40
|
-
* @param {
|
|
41
|
-
|
|
42
|
-
enqueue(queueable: Queueable): void;
|
|
43
|
-
/**
|
|
44
|
-
* Take a look at the next queued task
|
|
45
|
-
* @return {Queueable}
|
|
31
|
+
* Add an item to the back of the queue.
|
|
32
|
+
* @param {*} data The item to add
|
|
33
|
+
* @return {Queue} This queue, so that adding can be chained
|
|
46
34
|
*/
|
|
47
|
-
|
|
35
|
+
enqueue(data: T): this;
|
|
48
36
|
/**
|
|
49
|
-
*
|
|
50
|
-
* @return {
|
|
37
|
+
* Look at the item at the front of the queue, without removing it.
|
|
38
|
+
* @return {*|null} The item, or null when the queue is empty
|
|
51
39
|
*/
|
|
52
|
-
|
|
40
|
+
peek(): T | null;
|
|
53
41
|
/**
|
|
54
|
-
*
|
|
42
|
+
* Count the items in the queue.
|
|
55
43
|
* @return {number}
|
|
56
44
|
*/
|
|
57
45
|
size(): number;
|
|
58
46
|
/**
|
|
59
|
-
*
|
|
60
|
-
* @
|
|
61
|
-
|
|
62
|
-
|
|
47
|
+
* Iterate over the items from the front of the queue to the back, without removing them.
|
|
48
|
+
* @return {Iterator}
|
|
49
|
+
*/
|
|
50
|
+
[Symbol.iterator](): Iterator<T>;
|
|
51
|
+
/**
|
|
52
|
+
* Convert an array to a Queue, the first value is at the front.
|
|
53
|
+
* @param {Array} [values=[]] The items to queue
|
|
54
|
+
* @param {IsArrayable} [listClass=LinkedList] The type of list used to store the items
|
|
55
|
+
* @param {Linker} [linkerClass=Linker] The class used to hold each queued item
|
|
63
56
|
* @returns {Queue}
|
|
64
57
|
*/
|
|
65
|
-
static fromArray: (values?: Array<
|
|
58
|
+
static fromArray: <T_1 = any>(values?: Array<T_1>, listClass?: any, linkerClass?: typeof Linker) => Queue<T_1>;
|
|
66
59
|
}
|
|
@@ -4,81 +4,49 @@ Object.defineProperty(exports, '__esModule', {
|
|
|
4
4
|
value: true
|
|
5
5
|
})
|
|
6
6
|
exports.Queue = void 0
|
|
7
|
-
|
|
7
|
+
require('core-js/modules/esnext.iterator.constructor.js')
|
|
8
|
+
require('core-js/modules/esnext.iterator.for-each.js')
|
|
8
9
|
var _LinkedList = require('../linked-list/LinkedList')
|
|
10
|
+
var _Linker = require('../linked-list/Linker')
|
|
9
11
|
/**
|
|
10
12
|
* @file queue
|
|
11
13
|
* @author Joshua Heagle <joshuaheagle@gmail.com>
|
|
12
|
-
* @version
|
|
14
|
+
* @version 2.0.0
|
|
13
15
|
* @memberOf module:collect-your-stuff
|
|
14
16
|
*/
|
|
15
17
|
|
|
16
18
|
/**
|
|
17
|
-
*
|
|
19
|
+
* A first-in-first-out collection: items are added to the back with enqueue and taken from the front with dequeue.
|
|
20
|
+
* Any value can be queued (it is stored as it is, whether it is a function, an object or null), and adding and taking
|
|
21
|
+
* are constant time. To queue tasks which are run as they are taken use TaskQueue.
|
|
18
22
|
*/
|
|
19
23
|
class Queue {
|
|
20
24
|
/**
|
|
21
|
-
* Instantiate the queue with
|
|
22
|
-
* @param {
|
|
23
|
-
* @param {IsArrayable} [listClass=LinkedList] The type of list to create when no queued list is given
|
|
24
|
-
* @param {
|
|
25
|
+
* Instantiate the queue, optionally with a list of items to start from.
|
|
26
|
+
* @param {IsArrayable|null} [queuedList=null] The list of linkers to start in this queue (the first is the front)
|
|
27
|
+
* @param {IsArrayable} [listClass=LinkedList] The type of list to create when no queued list is given
|
|
28
|
+
* @param {Linker} [linkerClass=Linker] The class used to hold each queued item
|
|
25
29
|
*/
|
|
26
|
-
constructor (queuedList = null, listClass = _LinkedList.LinkedList,
|
|
27
|
-
this.
|
|
28
|
-
this.
|
|
29
|
-
if (queuedList === null) {
|
|
30
|
-
queuedList = new listClass(queueableClass)
|
|
31
|
-
}
|
|
32
|
-
this.queuedList = queuedList
|
|
30
|
+
constructor (queuedList = null, listClass = _LinkedList.LinkedList, linkerClass = _Linker.Linker) {
|
|
31
|
+
this.linkerClass = linkerClass
|
|
32
|
+
this.queuedList = queuedList === null ? new listClass(linkerClass) : queuedList
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
/**
|
|
36
|
-
* Take
|
|
37
|
-
*
|
|
38
|
-
* completed tasks are discarded.
|
|
39
|
-
* @return {completeResponse|*}
|
|
36
|
+
* Take the item from the front of the queue.
|
|
37
|
+
* @return {*|null} The item, or null when the queue is empty
|
|
40
38
|
*/
|
|
41
39
|
dequeue () {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
next = this.remove()
|
|
46
|
-
}
|
|
47
|
-
if (!next) {
|
|
48
|
-
return {
|
|
49
|
-
success: 'No more queueable tasks in the queue',
|
|
50
|
-
error: false,
|
|
51
|
-
context: this.queuedList
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
if (next.running) {
|
|
55
|
-
// The unfinished task reports back through its own complete callback, so it is not kept in the queue
|
|
56
|
-
return {
|
|
57
|
-
success: false,
|
|
58
|
-
error: 'The queue has been blocked by an unfinished task.',
|
|
59
|
-
context: next
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
if (!next.isReady) {
|
|
63
|
-
// Keep the task (at the back, so the next dequeue can try the other tasks) rather than losing it
|
|
64
|
-
this.enqueue(next)
|
|
65
|
-
// We could go check the next in queue here but if we end up in a state where nothing is ready it would infinite loop
|
|
66
|
-
// Also, we want the loop handled externally
|
|
67
|
-
return {
|
|
68
|
-
success: false,
|
|
69
|
-
error: 'Unable to find ready task.',
|
|
70
|
-
context: next
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
if (!this.empty()) {
|
|
74
|
-
// Place back in queue to be checked once again next time, only if the queue will not be empty
|
|
75
|
-
this.enqueue(next)
|
|
40
|
+
const front = this.queuedList.first
|
|
41
|
+
if (front === null || typeof front === 'undefined') {
|
|
42
|
+
return null
|
|
76
43
|
}
|
|
77
|
-
|
|
44
|
+
this.queuedList.remove(front)
|
|
45
|
+
return front.data
|
|
78
46
|
}
|
|
79
47
|
|
|
80
48
|
/**
|
|
81
|
-
*
|
|
49
|
+
* Check whether the queue has no items.
|
|
82
50
|
* @return {boolean}
|
|
83
51
|
*/
|
|
84
52
|
empty () {
|
|
@@ -86,50 +54,66 @@ class Queue {
|
|
|
86
54
|
}
|
|
87
55
|
|
|
88
56
|
/**
|
|
89
|
-
* Add
|
|
90
|
-
* @param {
|
|
57
|
+
* Add an item to the back of the queue.
|
|
58
|
+
* @param {*} data The item to add
|
|
59
|
+
* @return {Queue} This queue, so that adding can be chained
|
|
91
60
|
*/
|
|
92
|
-
enqueue (
|
|
93
|
-
|
|
61
|
+
enqueue (data) {
|
|
62
|
+
// The item is wrapped here rather than left to the list, since the list treats objects that look like a linker's
|
|
63
|
+
// settings (they have a data property) as such, and a queue must give back exactly what it was given
|
|
64
|
+
this.queuedList.append(new this.linkerClass({
|
|
65
|
+
data
|
|
66
|
+
}))
|
|
67
|
+
return this
|
|
94
68
|
}
|
|
95
69
|
|
|
96
70
|
/**
|
|
97
|
-
*
|
|
98
|
-
* @return {
|
|
71
|
+
* Look at the item at the front of the queue, without removing it.
|
|
72
|
+
* @return {*|null} The item, or null when the queue is empty
|
|
99
73
|
*/
|
|
100
74
|
peek () {
|
|
101
|
-
|
|
75
|
+
const front = this.queuedList.first
|
|
76
|
+
return front === null || typeof front === 'undefined' ? null : front.data
|
|
102
77
|
}
|
|
103
78
|
|
|
104
79
|
/**
|
|
105
|
-
*
|
|
106
|
-
* @return {
|
|
80
|
+
* Count the items in the queue.
|
|
81
|
+
* @return {number}
|
|
107
82
|
*/
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
return null
|
|
111
|
-
}
|
|
112
|
-
return this.queuedList.remove(this.queuedList.first)
|
|
83
|
+
size () {
|
|
84
|
+
return this.queuedList.length
|
|
113
85
|
}
|
|
114
86
|
|
|
115
87
|
/**
|
|
116
|
-
*
|
|
117
|
-
* @return {
|
|
88
|
+
* Iterate over the items from the front of the queue to the back, without removing them.
|
|
89
|
+
* @return {Iterator}
|
|
118
90
|
*/
|
|
119
|
-
|
|
120
|
-
|
|
91
|
+
[Symbol.iterator] () {
|
|
92
|
+
const linkers = this.queuedList[Symbol.iterator]()
|
|
93
|
+
return {
|
|
94
|
+
next: () => {
|
|
95
|
+
const result = linkers.next()
|
|
96
|
+
return result.done ? {
|
|
97
|
+
done: true,
|
|
98
|
+
value: undefined
|
|
99
|
+
} : {
|
|
100
|
+
done: false,
|
|
101
|
+
value: result.value.data
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
121
105
|
}
|
|
122
106
|
}
|
|
123
107
|
/**
|
|
124
|
-
* Convert an array to a Queue.
|
|
125
|
-
* @param {Array} values
|
|
126
|
-
* @param {
|
|
127
|
-
* @param {
|
|
108
|
+
* Convert an array to a Queue, the first value is at the front.
|
|
109
|
+
* @param {Array} [values=[]] The items to queue
|
|
110
|
+
* @param {IsArrayable} [listClass=LinkedList] The type of list used to store the items
|
|
111
|
+
* @param {Linker} [linkerClass=Linker] The class used to hold each queued item
|
|
128
112
|
* @returns {Queue}
|
|
129
113
|
*/
|
|
130
114
|
exports.Queue = Queue
|
|
131
|
-
Queue.fromArray = (values = [],
|
|
132
|
-
const
|
|
133
|
-
|
|
134
|
-
return
|
|
115
|
+
Queue.fromArray = (values = [], listClass = _LinkedList.LinkedList, linkerClass = _Linker.Linker) => {
|
|
116
|
+
const queue = new Queue(null, listClass, linkerClass)
|
|
117
|
+
values.forEach(value => queue.enqueue(value))
|
|
118
|
+
return queue
|
|
135
119
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.Queue=void 0;var
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.Queue=void 0,require("core-js/modules/esnext.iterator.constructor.js"),require("core-js/modules/esnext.iterator.for-each.js");var _LinkedList=require("../linked-list/LinkedList"),_Linker=require("../linked-list/Linker");class Queue{constructor(e=null,t=_LinkedList.LinkedList,r=_Linker.Linker){this.linkerClass=r,this.queuedList=null===e?new t(r):e}dequeue(){const e=this.queuedList.first;return null==e?null:(this.queuedList.remove(e),e.data)}empty(){return this.size()<=0}enqueue(e){return this.queuedList.append(new this.linkerClass({data:e})),this}peek(){const e=this.queuedList.first;return null==e?null:e.data}size(){return this.queuedList.length}[Symbol.iterator](){const e=this.queuedList[Symbol.iterator]();return{next:()=>{const t=e.next();return t.done?{done:!0,value:void 0}:{done:!1,value:t.value.data}}}}}exports.Queue=Queue,Queue.fromArray=(e=[],t=_LinkedList.LinkedList,r=_Linker.Linker)=>{const u=new Queue(null,t,r);return e.forEach((e=>u.enqueue(e))),u};
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file task queue
|
|
3
|
+
* @author Joshua Heagle <joshuaheagle@gmail.com>
|
|
4
|
+
* @version 1.1.0
|
|
5
|
+
* @memberOf module:collect-your-stuff
|
|
6
|
+
*/
|
|
7
|
+
import { Queueable } from './Queueable';
|
|
8
|
+
import { IsArrayable } from '../../recipes/IsArrayable';
|
|
9
|
+
import { IsLinker } from '../../recipes/IsLinker';
|
|
10
|
+
import { completeResponse } from '../../recipes/Runnable';
|
|
11
|
+
/**
|
|
12
|
+
* Maintain a series of queued tasks (Queueables): dequeue() takes the next task from the front and RUNS it, giving each
|
|
13
|
+
* task in turn a chance to run (a task which is not ready, or which has not finished, is placed at the back again).
|
|
14
|
+
* This is a task scheduler, for a plain first-in-first-out collection of items use Queue.
|
|
15
|
+
*/
|
|
16
|
+
export declare class TaskQueue {
|
|
17
|
+
/** The list which stores the queueables, the first is next to be dequeued. */
|
|
18
|
+
queuedList: IsArrayable<any>;
|
|
19
|
+
private listClass;
|
|
20
|
+
private queueableClass;
|
|
21
|
+
/**
|
|
22
|
+
* Instantiate the queue with the given queue list.
|
|
23
|
+
* @param {Iterable|LinkedList} queuedList Give the list of queueables to start in this queue.
|
|
24
|
+
* @param {IsArrayable} [listClass=LinkedList] The type of list to create when no queued list is given.
|
|
25
|
+
* @param {Queueable} [queueableClass=Queueable] The class used to wrap queued items.
|
|
26
|
+
*/
|
|
27
|
+
constructor(queuedList?: IsArrayable<any>, listClass?: any, queueableClass?: typeof Queueable);
|
|
28
|
+
/**
|
|
29
|
+
* Take a queued task from the front of the queue and run it if ready. A task which is not ready yet is kept in the
|
|
30
|
+
* queue (never dropped), a task which is still running is reported as blocking and left to finish on its own, and
|
|
31
|
+
* completed tasks are discarded.
|
|
32
|
+
* @return {completeResponse|*}
|
|
33
|
+
*/
|
|
34
|
+
dequeue(): completeResponse | any;
|
|
35
|
+
/**
|
|
36
|
+
* Return true if the queue is empty (there are no tasks in the queue list)
|
|
37
|
+
* @return {boolean}
|
|
38
|
+
*/
|
|
39
|
+
empty(): boolean;
|
|
40
|
+
/**
|
|
41
|
+
* Add a queued task to the end of the queue
|
|
42
|
+
* @param {Queueable} queueable Add a new queueable to the end of the queue
|
|
43
|
+
*/
|
|
44
|
+
enqueue(queueable: Queueable): void;
|
|
45
|
+
/**
|
|
46
|
+
* Take a look at the next queued task
|
|
47
|
+
* @return {Queueable}
|
|
48
|
+
*/
|
|
49
|
+
peek(): IsLinker;
|
|
50
|
+
/**
|
|
51
|
+
* Remove the next queued item and return it.
|
|
52
|
+
* @return {Queueable|null}
|
|
53
|
+
*/
|
|
54
|
+
remove(): Queueable | null;
|
|
55
|
+
/**
|
|
56
|
+
* Get the length of the current queue.
|
|
57
|
+
* @return {number}
|
|
58
|
+
*/
|
|
59
|
+
size(): number;
|
|
60
|
+
/**
|
|
61
|
+
* Convert an array to a TaskQueue.
|
|
62
|
+
* @param {Array} values An array of values which will be converted to queueables in this queue
|
|
63
|
+
* @param {Queueable} queueableClass The class to use for each queueable
|
|
64
|
+
* @param {TaskQueue|Iterable} listClass The class to use to manage the queueables
|
|
65
|
+
* @returns {TaskQueue}
|
|
66
|
+
*/
|
|
67
|
+
static fromArray: (values?: Array<any>, queueableClass?: typeof Queueable, listClass?: any) => TaskQueue;
|
|
68
|
+
}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', {
|
|
4
|
+
value: true
|
|
5
|
+
})
|
|
6
|
+
exports.TaskQueue = void 0
|
|
7
|
+
var _Queueable = require('./Queueable')
|
|
8
|
+
var _LinkedList = require('../linked-list/LinkedList')
|
|
9
|
+
/**
|
|
10
|
+
* @file task queue
|
|
11
|
+
* @author Joshua Heagle <joshuaheagle@gmail.com>
|
|
12
|
+
* @version 1.1.0
|
|
13
|
+
* @memberOf module:collect-your-stuff
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Maintain a series of queued tasks (Queueables): dequeue() takes the next task from the front and RUNS it, giving each
|
|
18
|
+
* task in turn a chance to run (a task which is not ready, or which has not finished, is placed at the back again).
|
|
19
|
+
* This is a task scheduler, for a plain first-in-first-out collection of items use Queue.
|
|
20
|
+
*/
|
|
21
|
+
class TaskQueue {
|
|
22
|
+
/**
|
|
23
|
+
* Instantiate the queue with the given queue list.
|
|
24
|
+
* @param {Iterable|LinkedList} queuedList Give the list of queueables to start in this queue.
|
|
25
|
+
* @param {IsArrayable} [listClass=LinkedList] The type of list to create when no queued list is given.
|
|
26
|
+
* @param {Queueable} [queueableClass=Queueable] The class used to wrap queued items.
|
|
27
|
+
*/
|
|
28
|
+
constructor (queuedList = null, listClass = _LinkedList.LinkedList, queueableClass = _Queueable.Queueable) {
|
|
29
|
+
this.listClass = listClass
|
|
30
|
+
this.queueableClass = queueableClass
|
|
31
|
+
if (queuedList === null) {
|
|
32
|
+
queuedList = new listClass(queueableClass)
|
|
33
|
+
}
|
|
34
|
+
this.queuedList = queuedList
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Take a queued task from the front of the queue and run it if ready. A task which is not ready yet is kept in the
|
|
39
|
+
* queue (never dropped), a task which is still running is reported as blocking and left to finish on its own, and
|
|
40
|
+
* completed tasks are discarded.
|
|
41
|
+
* @return {completeResponse|*}
|
|
42
|
+
*/
|
|
43
|
+
dequeue () {
|
|
44
|
+
let next = this.remove()
|
|
45
|
+
// Tasks which already completed are discarded when they reach the front of the queue
|
|
46
|
+
while (next && next.complete) {
|
|
47
|
+
next = this.remove()
|
|
48
|
+
}
|
|
49
|
+
if (!next) {
|
|
50
|
+
return {
|
|
51
|
+
success: 'No more queueable tasks in the queue',
|
|
52
|
+
error: false,
|
|
53
|
+
context: this.queuedList
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
if (next.running) {
|
|
57
|
+
// The unfinished task reports back through its own complete callback, so it is not kept in the queue
|
|
58
|
+
return {
|
|
59
|
+
success: false,
|
|
60
|
+
error: 'The queue has been blocked by an unfinished task.',
|
|
61
|
+
context: next
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
if (!next.isReady) {
|
|
65
|
+
// Keep the task (at the back, so the next dequeue can try the other tasks) rather than losing it
|
|
66
|
+
this.enqueue(next)
|
|
67
|
+
// We could go check the next in queue here but if we end up in a state where nothing is ready it would infinite loop
|
|
68
|
+
// Also, we want the loop handled externally
|
|
69
|
+
return {
|
|
70
|
+
success: false,
|
|
71
|
+
error: 'Unable to find ready task.',
|
|
72
|
+
context: next
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
if (!this.empty()) {
|
|
76
|
+
// Place back in queue to be checked once again next time, only if the queue will not be empty
|
|
77
|
+
this.enqueue(next)
|
|
78
|
+
}
|
|
79
|
+
return next.run.call(next)
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Return true if the queue is empty (there are no tasks in the queue list)
|
|
84
|
+
* @return {boolean}
|
|
85
|
+
*/
|
|
86
|
+
empty () {
|
|
87
|
+
return this.size() <= 0
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Add a queued task to the end of the queue
|
|
92
|
+
* @param {Queueable} queueable Add a new queueable to the end of the queue
|
|
93
|
+
*/
|
|
94
|
+
enqueue (queueable) {
|
|
95
|
+
this.queuedList.append(queueable)
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Take a look at the next queued task
|
|
100
|
+
* @return {Queueable}
|
|
101
|
+
*/
|
|
102
|
+
peek () {
|
|
103
|
+
return this.queuedList.first
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Remove the next queued item and return it.
|
|
108
|
+
* @return {Queueable|null}
|
|
109
|
+
*/
|
|
110
|
+
remove () {
|
|
111
|
+
if (this.empty()) {
|
|
112
|
+
return null
|
|
113
|
+
}
|
|
114
|
+
return this.queuedList.remove(this.queuedList.first)
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Get the length of the current queue.
|
|
119
|
+
* @return {number}
|
|
120
|
+
*/
|
|
121
|
+
size () {
|
|
122
|
+
return this.queuedList.length
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Convert an array to a TaskQueue.
|
|
127
|
+
* @param {Array} values An array of values which will be converted to queueables in this queue
|
|
128
|
+
* @param {Queueable} queueableClass The class to use for each queueable
|
|
129
|
+
* @param {TaskQueue|Iterable} listClass The class to use to manage the queueables
|
|
130
|
+
* @returns {TaskQueue}
|
|
131
|
+
*/
|
|
132
|
+
exports.TaskQueue = TaskQueue
|
|
133
|
+
TaskQueue.fromArray = (values = [], queueableClass = _Queueable.Queueable, listClass = _LinkedList.LinkedList) => {
|
|
134
|
+
const list = new listClass(queueableClass)
|
|
135
|
+
list.initialize(queueableClass.fromArray(values, queueableClass).head)
|
|
136
|
+
return new TaskQueue(list, listClass, queueableClass)
|
|
137
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.TaskQueue=void 0;var _Queueable=require("./Queueable"),_LinkedList=require("../linked-list/LinkedList");class TaskQueue{constructor(e=null,u=_LinkedList.LinkedList,s=_Queueable.Queueable){this.listClass=u,this.queueableClass=s,null===e&&(e=new u(s)),this.queuedList=e}dequeue(){let e=this.remove();for(;e&&e.complete;)e=this.remove();return e?e.running?{success:!1,error:"The queue has been blocked by an unfinished task.",context:e}:e.isReady?(this.empty()||this.enqueue(e),e.run.call(e)):(this.enqueue(e),{success:!1,error:"Unable to find ready task.",context:e}):{success:"No more queueable tasks in the queue",error:!1,context:this.queuedList}}empty(){return this.size()<=0}enqueue(e){this.queuedList.append(e)}peek(){return this.queuedList.first}remove(){return this.empty()?null:this.queuedList.remove(this.queuedList.first)}size(){return this.queuedList.length}}exports.TaskQueue=TaskQueue,TaskQueue.fromArray=(e=[],u=_Queueable.Queueable,s=_LinkedList.LinkedList)=>{const t=new s(u);return t.initialize(u.fromArray(e,u).head),new TaskQueue(t,s,u)};
|