Синхронизация клиентских вызовов на сервере xml-rpc-light в OCaml - PullRequest
1 голос
/ 07 июля 2011

Я пишу модуль XML-RPC в OCaml, используя библиотеку xml-rpc-light . Я хотел бы иметь сервер, который может принимать параллельные запросы и собирать данные, отправленные по всем запросам, в общем «состоянии». Чтобы быть конкретным, но упростить реальную проблему, предположим, что сервер предоставляет функцию

send : int -> bool

, который отправляет целое число и возвращает true в случае успеха и false в случае сбоя, и что сервер хочет сохранить список всех целых чисел, которые были вызваны с момента его запуска (включая дубликаты).

Я понимаю часть XML-RPC. Часть, которую мне трудно реализовать в OCaml, - это синхронизация различных клиентских вызовов на стороне сервера, чтобы они были поточно-ориентированными.

Я написал клиентский класс

class client =
    object
        val xr_client = new XmlRpc.client "http://localhost:11111"
        method send n = xr_client#call "send_integer" [`Int n] in
    end

, который вызывает соответствующий send_integer удаленный метод с некоторым целым числом n.

Я также написал серверный класс

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

, который имеет изменяемый state для хранения всех целых чисел и метод send для фактического выполнения клиентских вызовов. Для каждого звонка клиента я просто обновляю состояние. Но если второй вызов приходит до того, как второй закончен, я сталкиваюсь с проблемами безопасности потоков. Вот почему я добавил бит Mutex, который использует мьютекс поля одного класса, чтобы получить блокировку при обновлении состояния.

Мои вопросы:

  1. Будет ли достигнута синхронизация этим?
  2. Есть ли более аккуратные способы сделать это?
  3. Встроена ли синхронизация на сервере XML-RPC, что делает все это ненужным?

1 Ответ

0 голосов
/ 22 июля 2011

После решения проблем компиляции с этим кодом я понял, что мы не можем использовать библиотеку потоков вместе с xmlrpc-light; по крайней мере, напрямую. Поэтому мы все равно не можем использовать модуль Mutex.

Синхронизация достигается путем настройки сервера XML-RPC для разрешения только одного потока за раз во время выполнения. Это может быть достигнуто путем предоставления нашему серверу файла конфигурации, аналогичного примеру сумматора , но с настройкой max_threads = 1 в последней строке. Если мы допустим, скажем, 2 потока, то иногда изменение выполняется в изменяемом состоянии одного потока, иногда оно выполняется в изменяемом состоянии другого.

...