Synchronizing client calls in an xml-rpc-light ser

2019-08-02 21:34发布

问题:

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:

  1. Would synchronization be achieved by this?
  2. Are there neater ways of doing it?
  3. 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.