diff --git a/example/README.md b/example/README.md
index 64d3083..6853e51 100644
--- a/example/README.md
+++ b/example/README.md
@@ -72,8 +72,8 @@ if something is missing!
-- [**`w-long-polling`**](w-long-polling#files) — asynchronous
- communication without WebSockets.
+- [**`w-long-polling`**](w-long-polling#files) — old form of
+ asynchronous communication without WebSockets.
- [**`w-query`**](w-query#files) — reading URL query
parameters.
- [**`w-server-sent-events`**](w-server-sent-events#files) —
diff --git a/example/w-long-polling/README.md b/example/w-long-polling/README.md
index 62533be..6120adf 100644
--- a/example/w-long-polling/README.md
+++ b/example/w-long-polling/README.md
@@ -2,12 +2,53 @@
-**Next steps:**
+*Long polling* is a technique, largely made obsolete by
+[WebSockets](../k-websocket#files), where a client sends a request, but the
+server does not respond until some data is available. This delayed response
+works as a sort of “push” from the client's point of view, because it comes at
+a time of the server's choosing.
+
+The example implements a long-polling client and server. The core server
+function is `message_loop`:
+
+```ocaml
+let rec message_loop () =
+ let%lwt () = Lwt_unix.sleep (Random.float 2.) in
+ incr last_message;
+
+ let message = string_of_int !last_message in
+ Dream.log "Generated message %s" message;
+
+ begin match !server_state with
+ | Client_waiting f ->
+ server_state := Messages_accumulating [];
+ f message
+ | Messages_accumulating list ->
+ server_state := Messages_accumulating (message::list)
+ end;
+
+ message_loop ()
+```
-[Up to the example index](../#readme)
+This generates a “message” on the server up to every two seconds, to simulate,
+perhaps, other clients sending messages.
-
-
-
+If there is already a client waiting for a response, the message is used to
+respond to the client. If not, the message is placed in a list. The next time a
+client sends a request, the messages already in the list are used to respond to
+the client immediately. If a client sends the next request before any more
+messages are generated, the server waits to respond — hence, “long
+polling.”
+
+
+
+**See also:**
+
+- [**`k-websocket`**](../k-websocket#files) for a more modern way of achieving
+ asynchronous client-server communication.
+
+
+
+[Up to the example index](../#examples)
diff --git a/example/w-long-polling/long_polling.eml.ml b/example/w-long-polling/long_polling.eml.ml
index 4f5aa66..28178ff 100644
--- a/example/w-long-polling/long_polling.eml.ml
+++ b/example/w-long-polling/long_polling.eml.ml
@@ -37,8 +37,10 @@ let last_message =
let rec message_loop () =
let%lwt () = Lwt_unix.sleep (Random.float 2.) in
incr last_message;
+
let message = string_of_int !last_message in
Dream.log "Generated message %s" message;
+
begin match !server_state with
| Client_waiting f ->
server_state := Messages_accumulating [];
@@ -46,6 +48,7 @@ let rec message_loop () =
| Messages_accumulating list ->
server_state := Messages_accumulating (message::list)
end;
+
message_loop ()
let () =