diff options
author | Adam Chlipala <adam@chlipala.net> | 2016-08-26 19:27:16 -0400 |
---|---|---|
committer | Adam Chlipala <adam@chlipala.net> | 2016-08-26 19:27:16 -0400 |
commit | cd95bbc160511e06d5534cd59bbaab277c5362e2 (patch) | |
tree | 7dc7325de515427fa54db5bdbdffe7ae2ee13c5b | |
parent | f0c60c01bb078da639efd3aaf33bc2f0ff996169 (diff) | |
parent | 4330e7007078d680c1a3092d77831ed0c0fcf9b7 (diff) |
Merge branch 'master' of ssh://github.com/urweb/urweb
-rw-r--r-- | doc/manual.tex | 8 | ||||
-rw-r--r-- | lib/js/urweb.js | 21 | ||||
-rw-r--r-- | src/c/Makefile.am | 7 |
3 files changed, 27 insertions, 9 deletions
diff --git a/doc/manual.tex b/doc/manual.tex index 76f69330..8c12102e 100644 --- a/doc/manual.tex +++ b/doc/manual.tex @@ -2095,6 +2095,12 @@ Configure the policy for meta names with the \texttt{allow} and \texttt{deny} \t Ur/Web supports running code on web browsers, via automatic compilation to JavaScript. +The concurrency model is \emph{cooperative multithreading}. Like with, say, POSIX threads, which uses the \emph{preemptive multithreading} model, there may be multiple threads of control active at a time. However, unlike with preemptive multithreading, the currently running thread gets to run interrupted until a well-defined \emph{context-switch} point. Specifically, four functions defined below are the context-switch points. They are $\mt{sleep}$, $\mt{rpc}$, $\mt{tryRpc}$, and $\mt{recv}$. (We explain their purposes as we come to them below.) Additional functions added via the foreign function interface might also have context-switching behavior. In any case, it is guaranteed that a running thread ``owns the processor'' until it calls a context-switching function, at which time we may switch to running a different thread instead. + +This concurrency paradigm has many nice properties. For instance, there is almost never any need for locking or other synchronization between threads. + +Readers used to the standard JavaScript model may recognize this style as the natural one that we obtain by imposing a thread-based perspective on top of the usual JavaScript callback-based API. Indeed, every context-switching Ur/Web function is implemented with an underlying JavaScript call that asks for some callback to be triggered when an event happens. + \subsubsection{The Basics} All of the functions in this subsection are client-side only. @@ -2245,7 +2251,7 @@ The $\mt{channel}$ and $\mt{send}$ operations may only be executed on the server Clients and channels live only as long as the web browser page views that they are associated with. When a user surfs away, his client and its channels will be garbage-collected, after that user is not heard from for the timeout period. Garbage collection deletes any database row that contains a client or channel directly. Any reference to one of these types inside an $\mt{option}$ is set to $\mt{None}$ instead. Both kinds of handling have the flavor of weak pointers, and that is a useful way to think about clients and channels in the database. -\emph{Note}: Currently, there are known concurrency issues with multi-threaded applications that employ message-passing on top of database engines that don't support true serializable transactions. Postgres 9.1 is the only supported engine that does this properly. +\emph{Note}: Currently, there are known concurrency issues with multi-threaded applications that employ message-passing on top of database engines that don't support true serializable transactions. Postgres (versions 9.1 and up) is the only supported engine that does this properly. \section{Ur/Web Syntax Extensions} diff --git a/lib/js/urweb.js b/lib/js/urweb.js index 68e7979d..222a8322 100644 --- a/lib/js/urweb.js +++ b/lib/js/urweb.js @@ -731,6 +731,8 @@ function flattenLocal(s) { // Dynamic tree management function populate(node) { + if (node.dead) return; + var s = node.signal; var oldSources = node.sources; try { @@ -760,8 +762,7 @@ function sv(s, v) { s.data = v; for (var ls = s.dyns; ls; ls = ls.next) - if (!ls.dead) - populate(ls.data); + populate(ls.data); } } function sg(s) { @@ -1099,12 +1100,18 @@ function active(s) { function input(x, s, recreate, type, name) { if (name) x.name = name; if (type) x.type = type; - x.dead = false; - x.signal = ss(s); - x.sources = null; - x.recreate = recreate(x); addNode(x); - populate(x); + + var sc = document.createElement("script"); + sc.dead = false; + sc.signal = ss(s); + sc.sources = null; + sc.recreate = recreate(x); + + if (x.parentNode) + x.parentNode.insertBefore(sc, x); + + populate(sc); return x; } diff --git a/src/c/Makefile.am b/src/c/Makefile.am index d117d018..f4d9bef8 100644 --- a/src/c/Makefile.am +++ b/src/c/Makefile.am @@ -8,9 +8,14 @@ liburweb_static_la_SOURCES = static.c AM_CPPFLAGS = -I$(srcdir)/../../include/urweb $(OPENSSL_INCLUDES) AM_CFLAGS = -Wimplicit -Wall -Werror -Wno-format-security -Wno-deprecated-declarations -U_FORTIFY_SOURCE $(PTHREAD_CFLAGS) -liburweb_la_LDFLAGS = $(AM_LDFLAGS) $(OPENSSL_LDFLAGS) +liburweb_la_LDFLAGS = $(AM_LDFLAGS) $(OPENSSL_LDFLAGS) \ + -export-symbols-regex '^(client_pruner|pthread_create_big|strcmp_nullsafe|uw_.*)' liburweb_la_LIBADD = $(PTHREAD_LIBS) -lm $(OPENSSL_LIBS) liburweb_http_la_LIBADD = liburweb.la +liburweb_http_la_LDFLAGS = -export-symbols-regex '^(main|uw_.*)' liburweb_cgi_la_LIBADD = liburweb.la +liburweb_cgi_la_LDFLAGS = -export-symbols-regex '^(main|uw_.*)' liburweb_fastcgi_la_LIBADD = liburweb.la +liburweb_fastcgi_la_LDFLAGS = -export-symbols-regex '^(main|uw_.*)' liburweb_static_la_LIBADD = liburweb.la +liburweb_static_la_LDFLAGS = -export-symbols-regex '^(main|uw_.*)' |