Commit b291d6df authored by Linshizhi's avatar Linshizhi

Add RBLKS, WBLKS field to channel.

parent 77d8fb3f
...@@ -3,8 +3,33 @@ ...@@ -3,8 +3,33 @@
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
class CpySchedule { class CpySchedule {
first = { pos: 0, size: 0 } first = { pos : 0, size: 0 };
second = { pos: 0, size: 0 } second = { pos : 0, size: 0 };
isEmptySchedule() {
return first.size == 0 && second.size == 0;
}
reset() {
first.pos = 0;
first.size = 0;
second.pos = 0;
second.size = 0;
}
}
const CHANNEL_MODE = Object.freeze({
BYTE : 0,
BLOCK : 1,
});
const WRITE_PHASE = Object.freeze({
NO_STEP_WRITE : 0,
WAIT_CALLER_WRITE : 1,
});
function createChnlBuffer(size, bufferType=SharedArrayBuffer) {
return new bufferType(size+12+1);
} }
/* An abstraction that help to /* An abstraction that help to
...@@ -20,18 +45,26 @@ class Channel { ...@@ -20,18 +45,26 @@ class Channel {
* 2.Read Position * 2.Read Position
* *
* Figure: * Figure:
* -------------------------------------------------------------------------------------------- * -------------------------------------------------------------------------------------------------------------------------------
* | ReadPointer (4 bytes) | WritePointer (4 Bytes) | Private (4 Bytes) | Data Area (N bytes) | * | ReadPointer (4 bytes) | WritePointer (4 Bytes) | RBlks (1 Byte) | WBlks (1 Bytes) | Private (2 Bytes) | Data Area (N bytes) |
* -------------------------------------------------------------------------------------------- * -------------------------------------------------------------------------------------------------------------------------------
*
* where N >= 2 * where N >= 2
* *
* */ * */
#rFieldPosLen = 4; #rFieldPosLen = 4;
#wFieldPosLen = 4; #wFieldPosLen = 4;
#priFieldLen = 4; #rBlkFieldLen = 1;
#numOfMetaField = 3 #wBlkFieldLen = 1;
#priFieldLen = 2;
#fieldSize = 0; #fieldSize = 0;
#rPtrShift = 0;
#wPtrShift = this.#rPtrShift + this.#rFieldPosLen;
#rBlkShift = this.#wPtrShift + this.#wFieldPosLen;
#wBlkShift = this.#rBlkShift + this.#rBlkFieldLen;
#priShift = this.#wBlkShift + this.#wBlkFieldLen;
#metaSize = 0; #metaSize = 0;
#size = 0; #size = 0;
#totalSize = 0; #totalSize = 0;
...@@ -40,10 +73,18 @@ class Channel { ...@@ -40,10 +73,18 @@ class Channel {
#view = undefined; #view = undefined;
#buffer = undefined; #buffer = undefined;
#mode = CHANNEL_MODE.BYTE;
#blockSize = 0;
#writePointerCache = 0; #writePointerCache = 0;
#readPointerCache = 0; #readPointerCache = 0;
#endPos = 0; #endPos = 0;
#writePhase = WRITE_PHASE.NO_STEP_WRITE;
#writePhaseEndPos = 0;
#scheduler = undefined;
// size's unit is byte // size's unit is byte
// bufferType parameter is mainly for testability. // bufferType parameter is mainly for testability.
constructor(size, bufferType = SharedArrayBuffer, shMem = null) { constructor(size, bufferType = SharedArrayBuffer, shMem = null) {
...@@ -53,7 +94,8 @@ class Channel { ...@@ -53,7 +94,8 @@ class Channel {
this.#size = size+1; this.#size = size+1;
// Init shared memory // Init shared memory
this.#metaSize = this.#rFieldPosLen + this.#wFieldPosLen + this.#priFieldLen; this.#metaSize = this.#rFieldPosLen + this.#wFieldPosLen +
this.#rBlkFieldLen + this.#wBlkFieldLen + this.#priFieldLen;
this.#shMem = shMem == null ? new bufferType(this.#size + this.#metaSize) : shMem; this.#shMem = shMem == null ? new bufferType(this.#size + this.#metaSize) : shMem;
this.#view = new DataView(this.#shMem); this.#view = new DataView(this.#shMem);
...@@ -64,20 +106,21 @@ class Channel { ...@@ -64,20 +106,21 @@ class Channel {
// Init readPointer and writePointer to // Init readPointer and writePointer to
// the first bytes of data area. // the first bytes of data area.
this.#view.setUint32(0, this.#writePointerCache); this.#view.setUint32(this.#wPtrShift, this.#writePointerCache);
this.#view.setUint32(4, this.#readPointerCache); this.#view.setUint32(this.#rPtrShift, this.#readPointerCache);
this.#totalSize = this.#metaSize + this.#size; this.#totalSize = this.#metaSize + this.#size;
this.#endPos = this.#metaSize + this.#size; this.#endPos = this.#metaSize + this.#size;
this.#scheduler = new CopyStrategyInByte(this.#size, this.#metaSize);
} }
#getReadPointer() { #getReadPointer() {
return this.#view.getUint32(0); return this.#view.getUint32(this.#rPtrShift);
} }
#getWritePointer() { #getWritePointer() {
return this.#view.getUint32(4); return this.#view.getUint32(this.#wPtrShift);
} }
metaSize() { metaSize() {
...@@ -85,12 +128,12 @@ class Channel { ...@@ -85,12 +128,12 @@ class Channel {
} }
readPriv() { readPriv() {
return this.#view.getUint32(8); return this.#view.getUint16(this.#priShift);
} }
writePriv(privData) { writePriv(privData) {
try { try {
this.#view.setUint32(8, privData); this.#view.setUint16(this.#priShift, privData);
} catch (error) { } catch (error) {
if (error instanceof RangeError) if (error instanceof RangeError)
return false; return false;
...@@ -99,6 +142,47 @@ class Channel { ...@@ -99,6 +142,47 @@ class Channel {
return true; return true;
} }
enableBlockMode(size) {
let capacity = this.#size - 1;
if (capacity % size) {
return false;
}
this.#readPointerUpdate(this.#metaSize);
this.#writePointerUpdate(this.#metaSize);
this.#mode = CHANNEL_MODE.BLOCK;
this.#blockSize = size;
}
enableByteMode() {
this.#readPointerUpdate(this.#metaSize);
this.#writePointerUpdate(this.#metaSize);
this.#mode = CHANNEL_MODE.BYTE;
}
getRBlks() {
return this.#view.getUint8(this.#rBlkShift);
}
setRBlks(num) {
this.#view.setUint8(this.#rBlkShift, num);
}
getWBlks() {
return this.#view.getUint8(this.#wBlkShift);
}
setWBlks(num) {
this.#view.setUint8(this.#wBlkShift, num);
}
isSetPriv(flag) {
let flags = this.readPriv();
return flags & flag;
}
setPriv(flag) { setPriv(flag) {
let old = this.readPriv(); let old = this.readPriv();
this.writePriv(flag | old); this.writePriv(flag | old);
...@@ -106,7 +190,7 @@ class Channel { ...@@ -106,7 +190,7 @@ class Channel {
unsetPriv(flag) { unsetPriv(flag) {
let old = this.readPriv(); let old = this.readPriv();
flag = flag ^ 0x11111111; flag = flag ^ 0x1111;
this.writePriv(flag & old); this.writePriv(flag & old);
} }
...@@ -127,6 +211,19 @@ class Channel { ...@@ -127,6 +211,19 @@ class Channel {
} }
#remain() { #remain() {
switch (this.#mode) {
case CHANNEL_MODE.BYTE:
return this.#remainBytes();
case CHANNEL_MODE.BLOCK:
return this.#remainBlocks();
}
}
#remainBlocks() {
}
#remainBytes() {
this.#readPointerCache = this.#getReadPointer(); this.#readPointerCache = this.#getReadPointer();
if (this.#writePointerCache == this.#readPointerCache) { if (this.#writePointerCache == this.#readPointerCache) {
...@@ -147,26 +244,8 @@ class Channel { ...@@ -147,26 +244,8 @@ class Channel {
* Caution: Before making a copy schedule you must * Caution: Before making a copy schedule you must
* make sure there has enough spaces.*/ * make sure there has enough spaces.*/
#cpySchedule(size) { #cpySchedule(size) {
let firstCpySize = 0, secondCpySize = 0, spaceToTail = 0; return this.#scheduler.schedule(
let schedule = new CpySchedule(); this.#readPointerCache, this.#writePointerCache , size);
let readPos = this.#getReadPointer();
if (this.#writePointerCache >= readPos) {
spaceToTail = this.#endPos - this.#writePointerCache;
firstCpySize = Math.min(size, spaceToTail);
secondCpySize = firstCpySize < size ? size - firstCpySize : 0;
secondCpySize = Math.min(secondCpySize, readPos - this.#metaSize);
schedule.first.pos = this.#writePointerCache;
schedule.first.size = firstCpySize;
schedule.second.pos = secondCpySize > 0 ? this.#metaSize : 0;
schedule.second.size = secondCpySize;
} else {
schedule.first.pos = this.#writePointerCache;
schedule.first.size = Math.min(readPos - this.#writePointerCache - 1, size);
}
return schedule;
} }
dataView() { dataView() {
...@@ -216,7 +295,62 @@ class Channel { ...@@ -216,7 +295,62 @@ class Channel {
return readBuffer; return readBuffer;
} }
/* Return array of buffers to caller
* so caller able to directly write to
* channel. */
writeStep1(size) {
this.#writePointerCache = this.#getWritePointer();
this.#readPointerCache = this.#getReadPointer();
if (!this.#isAbleToWrite(size)) {
return [];
}
if (this.#writePhase != WRITE_PHASE.NO_STEP_WRITE)
throw new Error("Unable to call multiple writeStep1() consecutively")
this.#writePhase = WRITE_PHASE.WAIT_CALLER_WRITE;
let schedule = this.#cpySchedule(size);
let plan_1 = schedule['first'];
let plan_2 = schedule['second'];
console.log(plan_1);
console.log(plan_2);
let endPos = undefined;
let buffers = [];
if (plan_1.size != 0) {
endPos = plan_1.pos + plan_1.size;
buffers.push(this.#buffer.subarray(
plan_1.pos, endPos));
}
if (plan_2.size != 0) {
endPos = plan_2.pos + plan_2.size;
buffers.push(this.#buffer.subarray(
plan_2.pos, endPos));
}
if (endPos != undefined)
this.#writePhaseEndPos = endPos;
return buffers;
}
writeStep2() {
if (this.#writePhase != WRITE_PHASE.WAIT_CALLER_WRITE)
return;
this.#writePointerUpdate(this.#writePhaseEndPos);
this.#writePhase = WRITE_PHASE.NO_STEP_WRITE;
}
push(data /* Uint8Array */) { push(data /* Uint8Array */) {
if (this.#writePhase != WRITE_PHASE.NO_STEP_WRITE) {
throw new Error("Unable to push into Channel during Step Write");
}
let writePos = this.#writePointerCache; let writePos = this.#writePointerCache;
this.#readPointerCache = this.#getReadPointer(); this.#readPointerCache = this.#getReadPointer();
...@@ -233,11 +367,9 @@ class Channel { ...@@ -233,11 +367,9 @@ class Channel {
// Perfrom write schedule // Perfrom write schedule
let srcPos = 0, plan; let srcPos = 0, plan;
let length = 0;
for (let key in schedule) { for (let key in schedule) {
plan = schedule[key]; plan = schedule[key];
if (plan.size == 0) if (plan.size == 0)
continue; continue;
...@@ -245,8 +377,6 @@ class Channel { ...@@ -245,8 +377,6 @@ class Channel {
this.#buffer.set(d_, plan.pos); this.#buffer.set(d_, plan.pos);
srcPos += plan.size; srcPos += plan.size;
writePos = plan.pos+plan.size; writePos = plan.pos+plan.size;
length += plan.size;
} }
// Caution: 'Write Pointer' must be updated after // Caution: 'Write Pointer' must be updated after
...@@ -255,22 +385,69 @@ class Channel { ...@@ -255,22 +385,69 @@ class Channel {
// oppsite side may read invalid datas. // oppsite side may read invalid datas.
this.#writePointerUpdate(writePos); this.#writePointerUpdate(writePos);
return true; return true;
} }
#writePointerUpdate(pos) { #writePointerUpdate(pos) {
this.#writePointerCache = pos; this.#writePointerCache = pos;
this.#view.setUint32(4, pos); this.#view.setUint32(this.#wPtrShift, pos);
} }
#readPointerUpdate(pos) { #readPointerUpdate(pos) {
this.#readPointerCache = pos; this.#readPointerCache = pos;
this.#view.setUint32(0, pos); this.#view.setUint32(this.#rPtrShift, pos);
} }
} }
///////////////////////////////////////////////////////////////////////////////
// Copy Strategies //
///////////////////////////////////////////////////////////////////////////////
class CopyStrategy {
schedule(rPos, wPos) {
return NEED_TO_IMPLEMENT;
}
};
class CopyStrategyInByte extends CopyStrategy {
#size = 0;
#shift = 0;
#endPos = 0;
constructor(size, shift) {
super();
this.#size = size;
this.#shift = shift;
this.#endPos = this.#shift + this.#size;
}
schedule(rPos, wPos, size) {
let firstCpySize = 0, secondCpySize = 0, spaceToTail = 0;
let schedule = new CpySchedule();
if (wPos >= rPos) {
spaceToTail = this.#endPos - wPos;
firstCpySize = Math.min(size, spaceToTail);
secondCpySize = firstCpySize < size ? size - firstCpySize : 0;
secondCpySize = Math.min(secondCpySize, rPos - this.#shift);
schedule.first.pos = wPos;
schedule.first.size = firstCpySize;
schedule.second.pos = secondCpySize > 0 ? this.#shift : 0;
schedule.second.size = secondCpySize;
} else {
schedule.first.pos = wPos;
schedule.first.size = Math.min(rPos - wPos - 1, size);
}
return schedule;
}
};
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// Message Definitions // // Message Definitions //
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
......
...@@ -44,19 +44,26 @@ export class Channel { ...@@ -44,19 +44,26 @@ export class Channel {
* 2.Read Position * 2.Read Position
* *
* Figure: * Figure:
* ---------------------------------------------------------------------------------------------------------------- * -------------------------------------------------------------------------------------------------------------------------------
* | ReadPointer (4 bytes) | WritePointer (4 Bytes) | Private (4 Bytes) | WBlocks (2 Bytes) | RBlocks (2 Bytes) | Data Area (N bytes) | * | ReadPointer (4 bytes) | WritePointer (4 Bytes) | RBlks (1 Byte) | WBlks (1 Bytes) | Private (2 Bytes) | Data Area (N bytes) |
* ---------------------------------------------------------------------------------------------------------------- * -------------------------------------------------------------------------------------------------------------------------------
* *
* where N >= 2 * where N >= 2
* *
* */ * */
#rFieldPosLen = 4; #rFieldPosLen = 4;
#wFieldPosLen = 4; #wFieldPosLen = 4;
#priFieldLen = 4; #rBlkFieldLen = 1;
#numOfMetaField = 3; #wBlkFieldLen = 1;
#priFieldLen = 2;
#fieldSize = 0; #fieldSize = 0;
#rPtrShift = 0;
#wPtrShift = this.#rPtrShift + this.#rFieldPosLen;
#rBlkShift = this.#wPtrShift + this.#wFieldPosLen;
#wBlkShift = this.#rBlkShift + this.#rBlkFieldLen;
#priShift = this.#wBlkShift + this.#wBlkFieldLen;
#metaSize = 0; #metaSize = 0;
#size = 0; #size = 0;
#totalSize = 0; #totalSize = 0;
...@@ -86,7 +93,8 @@ export class Channel { ...@@ -86,7 +93,8 @@ export class Channel {
this.#size = size+1; this.#size = size+1;
// Init shared memory // Init shared memory
this.#metaSize = this.#rFieldPosLen + this.#wFieldPosLen + this.#priFieldLen; this.#metaSize = this.#rFieldPosLen + this.#wFieldPosLen +
this.#rBlkFieldLen + this.#wBlkFieldLen + this.#priFieldLen;
this.#shMem = shMem == null ? new bufferType(this.#size + this.#metaSize) : shMem; this.#shMem = shMem == null ? new bufferType(this.#size + this.#metaSize) : shMem;
this.#view = new DataView(this.#shMem); this.#view = new DataView(this.#shMem);
...@@ -97,8 +105,8 @@ export class Channel { ...@@ -97,8 +105,8 @@ export class Channel {
// Init readPointer and writePointer to // Init readPointer and writePointer to
// the first bytes of data area. // the first bytes of data area.
this.#view.setUint32(0, this.#writePointerCache); this.#view.setUint32(this.#wPtrShift, this.#writePointerCache);
this.#view.setUint32(4, this.#readPointerCache); this.#view.setUint32(this.#rPtrShift, this.#readPointerCache);
this.#totalSize = this.#metaSize + this.#size; this.#totalSize = this.#metaSize + this.#size;
this.#endPos = this.#metaSize + this.#size; this.#endPos = this.#metaSize + this.#size;
...@@ -107,11 +115,11 @@ export class Channel { ...@@ -107,11 +115,11 @@ export class Channel {
} }
#getReadPointer() { #getReadPointer() {
return this.#view.getUint32(0); return this.#view.getUint32(this.#rPtrShift);
} }
#getWritePointer() { #getWritePointer() {
return this.#view.getUint32(4); return this.#view.getUint32(this.#wPtrShift);
} }
metaSize() { metaSize() {
...@@ -119,12 +127,12 @@ export class Channel { ...@@ -119,12 +127,12 @@ export class Channel {
} }
readPriv() { readPriv() {
return this.#view.getUint32(8); return this.#view.getUint16(this.#priShift);
} }
writePriv(privData) { writePriv(privData) {
try { try {
this.#view.setUint32(8, privData); this.#view.setUint16(this.#priShift, privData);
} catch (error) { } catch (error) {
if (error instanceof RangeError) if (error instanceof RangeError)
return false; return false;
...@@ -153,6 +161,22 @@ export class Channel { ...@@ -153,6 +161,22 @@ export class Channel {
this.#mode = CHANNEL_MODE.BYTE; this.#mode = CHANNEL_MODE.BYTE;
} }
getRBlks() {
return this.#view.getUint8(this.#rBlkShift);
}
setRBlks(num) {
this.#view.setUint8(this.#rBlkShift, num);
}
getWBlks() {
return this.#view.getUint8(this.#wBlkShift);
}
setWBlks(num) {
this.#view.setUint8(this.#wBlkShift, num);
}
isSetPriv(flag) { isSetPriv(flag) {
let flags = this.readPriv(); let flags = this.readPriv();
return flags & flag; return flags & flag;
...@@ -165,7 +189,7 @@ export class Channel { ...@@ -165,7 +189,7 @@ export class Channel {
unsetPriv(flag) { unsetPriv(flag) {
let old = this.readPriv(); let old = this.readPriv();
flag = flag ^ 0x11111111; flag = flag ^ 0x1111;
this.writePriv(flag & old); this.writePriv(flag & old);
} }
...@@ -277,7 +301,6 @@ export class Channel { ...@@ -277,7 +301,6 @@ export class Channel {
this.#writePointerCache = this.#getWritePointer(); this.#writePointerCache = this.#getWritePointer();
this.#readPointerCache = this.#getReadPointer(); this.#readPointerCache = this.#getReadPointer();
console.log(this.#readPointerCache, this.#writePointerCache);
if (!this.#isAbleToWrite(size)) { if (!this.#isAbleToWrite(size)) {
return []; return [];
...@@ -366,12 +389,12 @@ export class Channel { ...@@ -366,12 +389,12 @@ export class Channel {
#writePointerUpdate(pos) { #writePointerUpdate(pos) {
this.#writePointerCache = pos; this.#writePointerCache = pos;
this.#view.setUint32(4, pos); this.#view.setUint32(this.#wPtrShift, pos);
} }
#readPointerUpdate(pos) { #readPointerUpdate(pos) {
this.#readPointerCache = pos; this.#readPointerCache = pos;
this.#view.setUint32(0, pos); this.#view.setUint32(this.#rPtrShift, pos);
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment