git ssb

0+

wanderer🌟 / js-primea-hypervisor



Tree: e8b4f99fd6e0dfe281b7a34b3472f07323a34c0d

Files: e8b4f99fd6e0dfe281b7a34b3472f07323a34c0d / actor.js

3718 bytesRaw
1const Message = require('primea-message')
2const CapsManager = require('./capsManager.js')
3const Inbox = require('./inbox.js')
4
5module.exports = class Actor {
6 /**
7 * the Kernel manages the varous message passing functions and provides
8 * an interface for the containers to use
9 * @param {Object} opts
10 * @param {Object} opts.id - the UUID of the Kernel
11 * @param {Object} opts.state - the state of the container
12 * @param {Object} opts.hypervisor
13 * @param {Object} opts.container - the container constuctor and argments
14 */
15 constructor (opts) {
16 this.state = opts.state
17 this.code = opts.code
18 this.treeNode = opts.treeNode
19 this.hypervisor = opts.hypervisor
20 this.id = opts.id
21 this.container = new opts.container.Constructor(this, opts.container.args)
22 this.inbox = new Inbox(Object.assign({
23 actor: this
24 }, opts))
25
26 this.ticks = 0
27 this.containerState = 'idle'
28
29 // create the port manager
30 this.caps = new CapsManager(opts)
31 }
32
33 mintCap (tag = 0) {
34 return {
35 destId: this.id,
36 tag: tag
37 }
38 }
39
40 /**
41 * adds a message to this containers message queue
42 * @param {string} portName
43 * @param {object} message
44 */
45 queue (message) {
46 this.inbox.queue(message)
47 this._startMessageLoop()
48 }
49
50 async create (message) {
51 await this.message(message, 'onCreation')
52 this._startMessageLoop()
53 }
54
55 // waits for the next message
56 async _startMessageLoop () {
57 // this ensure we only every have one loop running at a time
58 if (this.containerState !== 'running') {
59 this.containerState = 'running'
60 while (1) {
61 const message = await this.inbox.getNextMessage()
62 if (!message) break
63
64 // if the message we recived had more ticks then we currently have then
65 // update it
66 if (message._fromTicks > this.ticks) {
67 this.ticks = message._fromTicks
68 this.hypervisor.scheduler.update(this)
69 }
70 // run the next message
71 await this.message(message)
72 }
73
74 this.containerState = 'idle'
75 this.container.onIdle()
76 }
77 }
78
79 shutdown () {
80 this.hypervisor.scheduler.done(this.id)
81 }
82
83 startup () {
84 return this.container.onStartup()
85 }
86
87 /**
88 * run the kernels code with a given enviroment
89 * @param {object} message - the message to run
90 * @param {boolean} init - whether or not to run the intialization routine
91 * @returns {Promise}
92 */
93 async message (message, method = 'onMessage') {
94 const responseCap = message.responseCap
95 delete message.responseCap
96
97 let result
98 try {
99 result = await this.container[method](message)
100 } catch (e) {
101 console.log(e)
102 result = {
103 exception: true,
104 exceptionError: e
105 }
106 }
107
108 if (responseCap) {
109 this.send(responseCap, new Message({
110 data: result
111 }))
112 }
113 this.caps.clist.clear()
114 }
115
116 /**
117 * updates the number of ticks that the container has run
118 * @param {Number} count - the number of ticks to add
119 */
120 incrementTicks (count) {
121 this.ticks += count
122 this.hypervisor.scheduler.update(this)
123 }
124
125 createInstance (type, message) {
126 const id = this.generateNextId()
127 return this.hypervisor.createInstance(type, message, id)
128 }
129
130 generateNextId () {
131 const id = {
132 nonce: this.state.nonce,
133 parent: this.id
134 }
135
136 this.state.nonce++
137 return id
138 }
139
140 /**
141 * sends a message to a given port
142 * @param {Object} portRef - the port
143 * @param {Message} message - the message
144 */
145 send (cap, message) {
146 message._fromTicks = this.ticks
147 message._fromId = this.id
148 message.tag = cap.tag
149
150 return this.hypervisor.send(cap, message)
151 }
152}
153

Built with git-ssb-web