问题
I'm writing an XML-RPC module in OCaml using the xml-rpc-light library. I'd like to have a server which can receive concurrent requests and gather the data sent by all the requests in a common 'state'. To be concrete, but simplifying the real problem, suppose the server provides the function
send : int -> bool
which sends an integer and returns true on success and false on failure, and that the server wants to keep a list of all the integers that were ever called since it started (including duplicates).
I understand the XML-RPC part. The part I'm having trouble to implement in OCaml is synchronizing the various client calls on the server side so that they are thread safe.
I've written a client class
class client =
object
val xr_client = new XmlRpc.client "http://localhost:11111"
method send n = xr_client#call "send_integer" [`Int n] in
end
which calls the appropriate send_integer
remote method with some integer n
.
I've also written a server class
class server =
object(self)
val mutable state = (ref [] : int list ref)
val xr_server = new XmlRpcServer.netplex ()
val m = Mutex.create ()
method send n =
let send_sync s n = (Mutex.lock m; s := n::!s; Mutex.unlock m) in
(send_sync state n; `Boolean true)
method init () =
xr_server#register "send_integer"
~signatures:[[`Int; `Boolean]]
(function
| [`Int x] -> self#send x;
| _ -> XmlRpcServer.invalid_params ());
xr_server#run ()
end
which has a mutable state
to keep all the integers and a send
method to actually execute the client calls. For each client call, I just update the state. But if a second call comes before the second is finished, I run into thread safety problems. That's why I've added the Mutex
bit which uses a single class field mutex to acquire a lock on updating the state.
My questions are:
- Would synchronization be achieved by this?
- Are there neater ways of doing it?
- Is synchronization built-in in the XML-RPC server already, making all of this unnecessary?
回答1:
After solving compilation problems with this code, I realised that we can't use the threads library together with xmlrpc-light; at least directly. So, we can't use the Mutex
module anyway.
Synchronisation is obtained by configuring the XML-RPC server to allow only one thread at a time during runtime. This can be achieved by providing our server with a configuration file similar to the adder example but setting max_threads = 1
in the last line. If we allow, say, 2 threads, then sometimes the change is made in the mutable state of one thread, sometimes it is made in the mutable state of the other.
来源:https://stackoverflow.com/questions/6605404/synchronizing-client-calls-in-an-xml-rpc-light-server-in-ocaml