gen_server With Rotating List
// December 15th, 2009 // Uncategorized
For those of you who didn’t go to SF Erlounge, it was a blast. In addition to getting to hear Tom Preston-Werner’s exciting presentation on BERT, BERT-RPC, and the new GitHub architecture, I also got to meet quite a few people who are interested in Erlang, but don’t have a lot of experience.
The great thing about these people is that they are great at bringing simple (for me) problems. One of these problems was so simple that it occurred to me to write it and post the source.
This particular problem is dead simple. He wanted to be able to have (possibly many) workers retrieve values from a list, rotating the list on each step. Using gen_server to serialize the requests was obvious, but I also think that this is a great example that illustrates how gen_server can be used to wrap useful, functional (i.e. tail-recursive) code.
Have a look at the source.
- shuffler.erl — main gen_server
- demo_slow.erl — demo that loads data in slowly with running clients
- demo_fast.erl — demo that preloads lots of data, then starts clients
It’s a simple gen_server that maintains two lists as its only state. The first list is a list of "fresh" entries, and the second is a list of "stale" entries. All it does is retrieve entries from the fresh list, one at a time; returns them to the user; and then accumulates them in another list of used entries.
When the fresh list would become empty, it returns the value to the caller, then automatically reverses the stale list (with the last value). This is a minor optimization so that clients don’t have to wait on lists:reverse/1 unless absolutely necessary.
The demos each contain a start function, and the data they use is just the module list as managed by the code server.
To compile this, just use erlc on each file, or run erl -make with them in a directory. To run them, try something like "erl -s demo_slow start". You’ll need to kill the VM to stop it (use ctrl+c to break out and q to quit).