Operations are now Garbage Collected!

This commit is contained in:
Kevin Jahns
2014-09-17 16:10:41 +02:00
parent b03f477a3f
commit 68c17f1876
63 changed files with 2420 additions and 934 deletions

View File

@@ -9,12 +9,18 @@
execution_listener = [];
Operation = (function() {
function Operation(uid) {
if (uid == null) {
this.is_deleted = false;
this.doSync = true;
if (uid != null) {
this.doSync = !isNaN(parseInt(uid.op_number));
} else {
uid = HB.getNextOperationIdentifier();
}
this.creator = uid['creator'], this.op_number = uid['op_number'];
}
Operation.prototype.type = "Insert";
Operation.prototype.on = function(events, f) {
var e, _base, _i, _len, _results;
if (this.event_listeners == null) {
@@ -71,6 +77,26 @@
}
};
Operation.prototype.isDeleted = function() {
return this.is_deleted;
};
Operation.prototype.applyDelete = function(garbagecollect) {
if (garbagecollect == null) {
garbagecollect = true;
}
if (!this.isDeleted()) {
this.is_deleted = true;
if (garbagecollect) {
return HB.addToGarbageCollector(this);
}
}
};
Operation.prototype.cleanup = function() {
return HB.removeOperation(this);
};
Operation.prototype.setParent = function(parent) {
this.parent = parent;
};
@@ -82,10 +108,15 @@
Operation.prototype.getUid = function() {
return {
'creator': this.creator,
'op_number': this.op_number
'op_number': this.op_number,
'sync': this.doSync
};
};
Operation.prototype.dontSync = function() {
return this.doSync = false;
};
Operation.prototype.execute = function() {
var l, _i, _len;
this.is_executed = true;
@@ -140,6 +171,8 @@
Delete.__super__.constructor.call(this, uid);
}
Delete.prototype.type = "Delete";
Delete.prototype._encode = function() {
return {
'type': "Delete",
@@ -179,19 +212,47 @@
Insert.__super__.constructor.call(this, uid);
}
Insert.prototype.type = "Insert";
Insert.prototype.applyDelete = function(o) {
var garbagecollect;
if (this.deleted_by == null) {
this.deleted_by = [];
}
this.deleted_by.push(o);
if ((this.parent != null) && this.deleted_by.length === 1) {
return this.parent.callEvent("delete", this);
if ((this.parent != null) && !this.isDeleted()) {
this.parent.callEvent("delete", this);
}
if (o != null) {
this.deleted_by.push(o);
}
garbagecollect = false;
if (this.prev_cl.isDeleted()) {
garbagecollect = true;
} else if (this.next_cl.isDeleted()) {
this.next_cl.applyDelete();
}
return Insert.__super__.applyDelete.call(this, garbagecollect);
};
Insert.prototype.isDeleted = function() {
var _ref;
return ((_ref = this.deleted_by) != null ? _ref.length : void 0) > 0;
Insert.prototype.cleanup = function() {
var d, o, _i, _len, _ref;
if (this.prev_cl.isDeleted()) {
_ref = this.deleted_by;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
d = _ref[_i];
d.cleanup();
}
o = this.next_cl;
while (o.type !== "Delimiter") {
if (o.origin === this) {
o.origin = this.prev_cl;
}
o = o.next_cl;
}
this.prev_cl.next_cl = this.next_cl;
this.next_cl.prev_cl = this.prev_cl;
return Insert.__super__.cleanup.apply(this, arguments);
}
};
Insert.prototype.getDistanceToOrigin = function() {
@@ -203,53 +264,21 @@
break;
}
d++;
if (this === this.prev_cl) {
throw new Error("this should not happen ;) ");
}
o = o.prev_cl;
}
return d;
};
Insert.prototype.update_sl = function() {
var o;
o = this.prev_cl;
({
update: function(dest_cl, dest_sl) {
var _results;
_results = [];
while (true) {
if (o.isDeleted()) {
_results.push(o = o[dest_cl]);
} else {
this[dest_sl] = o;
break;
}
}
return _results;
}
});
update("prev_cl", "prev_sl");
return update("next_cl", "prev_sl");
};
Insert.prototype.execute = function() {
var distance_to_origin, i, o, parent, _ref, _ref1, _ref2;
if (this.is_executed != null) {
return this;
}
var distance_to_origin, i, o, parent, _ref;
if (!this.validateSavedOperations()) {
return false;
} else {
if (((_ref = this.prev_cl) != null ? _ref.validateSavedOperations() : void 0) && ((_ref1 = this.next_cl) != null ? _ref1.validateSavedOperations() : void 0) && this.prev_cl.next_cl !== this) {
distance_to_origin = 0;
if (this.prev_cl != null) {
distance_to_origin = this.getDistanceToOrigin();
o = this.prev_cl.next_cl;
i = 0;
i = distance_to_origin;
while (true) {
if (o == null) {
console.log(JSON.stringify(this.prev_cl.getUid()));
console.log(JSON.stringify(this.next_cl.getUid()));
}
if (o !== this.next_cl) {
if (o.getDistanceToOrigin() === i) {
if (o.creator < this.creator) {
@@ -278,7 +307,7 @@
this.prev_cl.next_cl = this;
this.next_cl.prev_cl = this;
}
parent = (_ref2 = this.prev_cl) != null ? _ref2.getParent() : void 0;
parent = (_ref = this.prev_cl) != null ? _ref.getParent() : void 0;
if (parent != null) {
this.setParent(parent);
this.parent.callEvent("insert", this);
@@ -295,7 +324,7 @@
if (prev instanceof Delimiter) {
break;
}
if ((prev.isDeleted != null) && !prev.isDeleted()) {
if (!prev.isDeleted()) {
position++;
}
prev = prev.prev_cl;
@@ -314,6 +343,8 @@
ImmutableObject.__super__.constructor.call(this, uid, prev, next, origin);
}
ImmutableObject.prototype.type = "ImmutableObject";
ImmutableObject.prototype.val = function() {
return this.content;
};
@@ -331,15 +362,15 @@
if (this.next_cl != null) {
json['next'] = this.next_cl.getUid();
}
if ((this.origin != null) && this.origin !== this.prev_cl) {
json["origin"] = this.origin.getUid();
if (this.origin != null) {
json["origin"] = this.origin().getUid();
}
return json;
};
return ImmutableObject;
})(Insert);
})(Operation);
parser['ImmutableObject'] = function(json) {
var content, next, origin, prev, uid;
uid = json['uid'], content = json['content'], prev = json['prev'], next = json['next'], origin = json['origin'];
@@ -355,8 +386,21 @@
Delimiter.__super__.constructor.call(this, uid);
}
Delimiter.prototype.isDeleted = function() {
return false;
Delimiter.prototype.type = "Delimiter";
Delimiter.prototype.applyDelete = function() {
var o;
Delimiter.__super__.applyDelete.call(this);
o = this.next_cl;
while (o != null) {
o.applyDelete();
o = o.next_cl;
}
return void 0;
};
Delimiter.prototype.cleanup = function() {
return Delimiter.__super__.cleanup.call(this);
};
Delimiter.prototype.execute = function() {

File diff suppressed because one or more lines are too long

View File

@@ -78,6 +78,14 @@
JsonType.prototype.type = "JsonType";
JsonType.prototype.applyDelete = function() {
return JsonType.__super__.applyDelete.call(this);
};
JsonType.prototype.cleanup = function() {
return JsonType.__super__.cleanup.call(this);
};
JsonType.prototype.toJson = function() {
var json, name, o, val;
val = this.val();
@@ -100,16 +108,18 @@
return json;
};
JsonType.prototype.setReplaceManager = function(rm) {
this.parent = rm.parent;
JsonType.prototype.setReplaceManager = function(replace_manager) {
this.replace_manager = replace_manager;
return this.on(['change', 'addProperty'], function() {
var _ref;
return (_ref = rm.parent).forwardEvent.apply(_ref, [this].concat(__slice.call(arguments)));
if (replace_manager.parent != null) {
return (_ref = replace_manager.parent).forwardEvent.apply(_ref, [this].concat(__slice.call(arguments)));
}
});
};
JsonType.prototype.getParent = function() {
return this.parent;
return this.replace_manager.parent;
};
JsonType.prototype.mutable_default = true;
@@ -126,12 +136,11 @@
};
JsonType.prototype.val = function(name, content, mutable) {
var json, o, o_name, obj, word;
var json, obj, word;
if (typeof name === 'object') {
for (o_name in name) {
o = name[o_name];
this.val(o_name, o, content);
}
json = new JsonType(void 0, name, content);
HB.addOperation(json).execute();
this.replace_manager.replace(json);
return this;
} else if ((name != null) && ((content != null) || content === null)) {
if (mutable != null) {

File diff suppressed because one or more lines are too long

View File

@@ -18,6 +18,22 @@
MapManager.__super__.constructor.call(this, uid);
}
MapManager.prototype.type = "MapManager";
MapManager.prototype.applyDelete = function() {
var name, p, _ref;
_ref = this.map;
for (name in _ref) {
p = _ref[name];
p.applyDelete();
}
return MapManager.__super__.applyDelete.call(this);
};
MapManager.prototype.cleanup = function() {
return MapManager.__super__.cleanup.call(this);
};
MapManager.prototype.val = function(name, content) {
var o, obj, result, _ref, _ref1;
if (content != null) {
@@ -60,8 +76,18 @@
AddName.__super__.constructor.call(this, uid);
}
AddName.prototype.type = "AddName";
AddName.prototype.applyDelete = function() {
return AddName.__super__.applyDelete.call(this);
};
AddName.prototype.cleanup = function() {
return AddName.__super__.cleanup.call(this);
};
AddName.prototype.execute = function() {
var beg, end, uid_beg, uid_end, uid_r;
var beg, end, uid_beg, uid_end, uid_r, _base;
if (!this.validateSavedOperations()) {
return false;
} else {
@@ -76,6 +102,7 @@
end = HB.addOperation(new types.Delimiter(uid_end, beg, void 0)).execute();
this.map_manager.map[this.name] = HB.addOperation(new ReplaceManager(void 0, uid_r, beg, end));
this.map_manager.map[this.name].setParent(this.map_manager, this.name);
((_base = this.map_manager.map[this.name]).add_name_ops != null ? _base.add_name_ops : _base.add_name_ops = []).push(this);
this.map_manager.map[this.name].execute();
}
return AddName.__super__.execute.apply(this, arguments);
@@ -116,6 +143,8 @@
ListManager.__super__.constructor.call(this, uid, prev, next, origin);
}
ListManager.prototype.type = "ListManager";
ListManager.prototype.execute = function() {
if (this.validateSavedOperations()) {
this.beginning.setParent(this);
@@ -170,7 +199,7 @@
return ListManager;
})(types.Insert);
})(types.Operation);
ReplaceManager = (function(_super) {
__extends(ReplaceManager, _super);
@@ -181,11 +210,35 @@
}
}
ReplaceManager.prototype.type = "ReplaceManager";
ReplaceManager.prototype.applyDelete = function() {
var o, _i, _len, _ref;
o = this.beginning;
while (o != null) {
o.applyDelete();
o = o.next_cl;
}
if (this.add_name_ops != null) {
_ref = this.add_name_ops;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
o = _ref[_i];
o.applyDelete();
}
}
return ReplaceManager.__super__.applyDelete.call(this);
};
ReplaceManager.prototype.cleanup = function() {
return ReplaceManager.__super__.cleanup.call(this);
};
ReplaceManager.prototype.replace = function(content, replaceable_uid) {
var o, op;
o = this.getLastOperation();
op = new Replaceable(content, this, replaceable_uid, o, o.next_cl);
return HB.addOperation(op).execute();
HB.addOperation(op).execute();
return void 0;
};
ReplaceManager.prototype.setParent = function(parent, property_name) {
@@ -232,8 +285,8 @@
json['prev'] = this.prev_cl.getUid();
json['next'] = this.next_cl.getUid();
}
if ((this.origin != null) && this.origin !== this.prev_cl) {
json["origin"] = this.origin.getUid();
if (this.origin != null) {
json["origin"] = this.origin().getUid();
}
return json;
};
@@ -252,12 +305,14 @@
function Replaceable(content, parent, uid, prev, next, origin) {
this.saveOperation('content', content);
this.saveOperation('parent', parent);
if (!((prev != null) && (next != null) && (content != null))) {
throw new Error("You must define content, prev, and next for Replaceable-types!");
if (!((prev != null) && (next != null))) {
throw new Error("You must define prev, and next for Replaceable-types!");
}
Replaceable.__super__.constructor.call(this, uid, prev, next, origin);
}
Replaceable.prototype.type = "Replaceable";
Replaceable.prototype.val = function() {
return this.content;
};
@@ -266,23 +321,47 @@
return this.parent.replace(content);
};
Replaceable.prototype.applyDelete = function() {
if (this.content != null) {
this.content.applyDelete();
this.content.dontSync();
}
this.beforeDelete = this.content;
this.content = null;
return Replaceable.__super__.applyDelete.apply(this, arguments);
};
Replaceable.prototype.cleanup = function() {
return Replaceable.__super__.cleanup.apply(this, arguments);
};
Replaceable.prototype.execute = function() {
var _base;
var ins_result, _ref;
if (!this.validateSavedOperations()) {
return false;
} else {
if (typeof (_base = this.content).setReplaceManager === "function") {
_base.setReplaceManager(this.parent);
if ((_ref = this.content) != null) {
if (typeof _ref.setReplaceManager === "function") {
_ref.setReplaceManager(this.parent);
}
}
return Replaceable.__super__.execute.apply(this, arguments);
ins_result = Replaceable.__super__.execute.call(this);
if (ins_result) {
if (this.next_cl.type === "Delimiter" && this.prev_cl.type !== "Delimiter") {
this.prev_cl.applyDelete();
} else if (this.next_cl.type !== "Delimiter") {
this.applyDelete();
}
}
return ins_result;
}
};
Replaceable.prototype._encode = function() {
var json;
var json, _ref;
json = {
'type': "Replaceable",
'content': this.content.getUid(),
'content': (_ref = this.content) != null ? _ref.getUid() : void 0,
'ReplaceManager': this.parent.getUid(),
'prev': this.prev_cl.getUid(),
'next': this.next_cl.getUid(),

File diff suppressed because one or more lines are too long

View File

@@ -32,6 +32,8 @@
TextInsert.__super__.constructor.call(this, uid, prev, next, origin);
}
TextInsert.prototype.type = "TextInsert";
TextInsert.prototype.getLength = function() {
if (this.isDeleted()) {
return 0;
@@ -40,8 +42,13 @@
}
};
TextInsert.prototype.applyDelete = function() {
this.content = null;
return TextInsert.__super__.applyDelete.apply(this, arguments);
};
TextInsert.prototype.val = function(current_position) {
if (this.isDeleted()) {
if (this.isDeleted() || (this.content == null)) {
return "";
} else {
return this.content;
@@ -57,7 +64,7 @@
'prev': this.prev_cl.getUid(),
'next': this.next_cl.getUid()
};
if ((this.origin != null) && this.origin !== this.prev_cl) {
if (this.origin !== this.prev_cl) {
json["origin"] = this.origin.getUid();
}
return json;
@@ -80,13 +87,33 @@
WordType.prototype.type = "WordType";
WordType.prototype.applyDelete = function() {
var o;
o = this.beginning;
while (o != null) {
o.applyDelete();
o = o.next_cl;
}
return WordType.__super__.applyDelete.call(this);
};
WordType.prototype.cleanup = function() {
return WordType.__super__.cleanup.call(this);
};
WordType.prototype.insertText = function(position, content) {
var c, o, op, _i, _len;
o = this.getOperationByPosition(position);
var c, ith, left, op, right, _i, _len;
ith = this.getOperationByPosition(position);
left = ith.prev_cl;
while (left.isDeleted()) {
left = left.prev_cl;
}
right = left.next_cl;
for (_i = 0, _len = content.length; _i < _len; _i++) {
c = content[_i];
op = new TextInsert(c, void 0, o.prev_cl, o);
op = new TextInsert(c, void 0, left, right);
HB.addOperation(op).execute();
left = op;
}
return this;
};
@@ -278,8 +305,8 @@
if (this.next_cl != null) {
json['next'] = this.next_cl.getUid();
}
if ((this.origin != null) && this.origin !== this.prev_cl) {
json["origin"] = this.origin.getUid();
if (this.origin != null) {
json["origin"] = this.origin().getUid();
}
return json;
};

File diff suppressed because one or more lines are too long