-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.html
107 lines (87 loc) · 5.03 KB
/
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
---
layout: default
title: Home
---
**AtomizeJS is a JavaScript library for writing distributed programs,
that run in the browser, without having to write any application
specific logic on the server.**
# Introduction
Writing concurrent programs is tricky. Languages tend to go down one
of two routes: either threads are allowed to access the same
data-structures directly, and it's left up to the programmer to decide
how to manage locking; or the language presents a model whereby each
thread has its own specific memory, and data is passed between threads
through message passing. The former approach gives the programmer a
slightly bigger gun to shoot themselves with: the ease of writing code
that deadlocks is unrivalled. The latter is conceptually much simpler
and more intuitive, but is relatively confined: languages such as
Erlang or dedicated actor frameworks such as Akka are about as
mainstream as it gets.
Writing distributed programs is trickier still. In addition to the
issues of writing concurrent programs, you have further difficulties
of dealing with the safe access or distribution of data across the
system, combined with the increased potential for partial failures.
AtomizeJS is a project which aims to make it easy to write programs in
JavaScript that can be both concurrent and distributed. It does this
by implementing Distributed Software Transactional Memory (DSTM).
The mental model you should have when using AtomizeJS is as follows:
* Assume there is an object graph that gets distributed automatically
to every browser looking at your site.
* To make safe changes to this object graph, you write functions which
change the objects as desired. These functions are then run by
AtomizeJS as transactions. AtomizeJS ensures that these transaction
functions are run:
* *atomically*: Transactions are atomic (all or nothing).
* *consistently*: Transactions preserve the object graph's
consistency. That is, a transaction transforms a consistent
state of the object graph into another consistent state, without
necessarily preserving consistency at all intermediate points.
* *in isolation*: Transactions are isolated from one another. That
is, even though in general there will be many transactions
running concurrently, any given transaction's updates are
concealed from all the rest, until that transaction
commits. Another way of saying that same thing is that, for any
two distinct transactions *T1* and *T2*, *T1* might see *T2*'s
updates (after *T2* has committed) or *T2* might see *T1*'s
updates (after *T1* has committed), but certainly not both.
Transactions cannot deadlock: when a transaction function is run,
AtomizeJS detects if other transactions have modified the same objects
that are being altered by this function. If so, this function is
automatically restarted with the updated current
state-of-the-world. If a transaction is restarted then it will be
because some other transaction has committed, thus the system as a
whole has made progress.
Transactions allow programmers to safely manipulate data-structures
shared between many threads, or in the case of AtomizeJS, clients
(such as web browsers). You don't need to write distribution
mechanisms as you would with message-passing: all the code you write
assumes the data is local - you never write `send` or have `receive`
call-backs.
# Writing applications with transactions
Many applications do more and more work on the client-side - i.e. in
the browser. But currently, if a client wants to modify some global
state, the usual practice is to make some sort of request to the
server, whether it's via XHR or WebSockets or some other means. The
server receives the message and acts on it. This means you have to
write both client-side code, and server-side code. *But with
AtomizeJS, you can **just** write client-side code*, and rely on
AtomizeJS to distribute the changes to all clients.
Indeed, I have written an
[entire multi-player game - *bomberman*](https://github.com/atomizejs/atomize-examples/blob/master/bomberman/index.html)
that has no server-side code at all beyond the AtomizeJS server.
# Beyond plain transactions
If a transaction allows you to safely modify global data, what about
*waiting* for someone else to modify a value? If you can *wait* for
someone else to modify a value then you can very easily implement the
observer pattern, which, across global distributed data gets you
broadcast and other general-purpose communication mechanisms, amongst
other things. Well, AtomizeJS supports both the [`retry`][] and
[`orElse`][] functions of STM, which gives you the ability to force a
transaction to suspend and be restarted only when values which have
been read as part of the transaction have been changed.
AtomizeJS also supports nested transactions.
On the server, a NodeJS server can also be a client to the AtomizeJS
system. This means that you can, when you need or want to, write
server side JavaScript that also uses AtomizeJS to safely modify
global state that is shared with clients. There are no API changes at
all.