межпроцессное прохождение объекта - PullRequest
0 голосов
/ 29 января 2012

Мне нужен класс с одним действием, которое выполняется один раз в 5 секунд в своем собственном потоке. Это веб-сервис, поэтому необходимо указать конечную точку. Во время выполнения объекта основной поток может изменить конечную точку. Это мой класс:

class Worker
{
    public:
    void setEndpoint(const std::string& endpoint); 

    private:
    void activity (void);

    mutex endpoint_mutex;
    volatile std::auto_ptr<std::string> newEndpoint;

    WebServiceClient client;
} 

Нужно ли объявлять объект newEndpoint как volatile? Я бы, конечно, сделал бы это, если бы чтение было в каком-то цикле (чтобы компилятор не оптимизировал его), но здесь я не знаю.

В каждом запуске функция activity() проверяет новую конечную точку (если новая есть, затем передает ее клиенту и выполняет некоторые шаги переподключения) и выполняет свою работу.

void Worker::activity(void)
{
    endpoint_mutex.lock(); //don't consider exceptions
    std::auto_ptr<std::string>& ep = const_cast<std::auto_ptr<string> >(newEndpoint);
    if (NULL != ep.get())
    {
        client.setEndpoint(*ep);
        ep.reset(NULL);
        endpoint_mutex.unlock();
        client.doReconnectionStuff();
        client.doReconnectionStuff2();
    }
    else
    {
        endpoint_mutex.unlock();
    }

    client.doSomeStuff();
    client.doAnotherStuff();
    .....
}

Я блокирую мьютекс, что означает, что объект newEndpoint больше не может изменяться, поэтому я удаляю спецификацию класса volatile , чтобы иметь возможность вызывать const методы.

Метод setEndpoint (вызывается из других потоков):

void Worker::setEndpoint(const std::string& endpoint)
{
    endpoint_mutex.lock(); //again - don't consider exceptions
    std::auto_ptr<std::string>& ep = const_cast<std::auto_ptr<string> >(newEndpoint);
    ep.reset(new std::string(endpoint);
    endpoint_mutex.unlock();
}

Является ли эта штука поточно-безопасной? Если нет, то в чем проблема? Нужно ли, чтобы объект newEndpoint был volatile?

1 Ответ

1 голос
/ 29 января 2012

volatile используется в следующих случаях для MSDN:

Ключевое слово volatile - это спецификатор типа, используемый для объявления того, что объект может быть изменен в программе с помощью чего-либо, например операционной системы.аппаратное обеспечение или одновременно выполняющийся поток.

Объекты, объявленные как volatile, не используются в определенных оптимизациях, поскольку их значения могут измениться в любое время .Система всегда считывает текущее значение энергозависимого объекта в точке, в которой оно запрашивается, даже если предыдущая инструкция запрашивала значение из того же объекта.Кроме того, значение объекта записывается сразу при назначении.

Вопрос в вашем случае, как часто ваш NewEndPoint действительно изменяется?Вы создаете соединение в потоке A, а затем выполняете некоторую работу.Пока это происходит, ничто другое не может возиться с вашей конечной точкой, так как она заблокирована мьютексом.Итак, согласно моему анализу, и из того, что я вижу в вашем коде, эта переменная не обязательно изменяется достаточно.

Я не вижу сайт вызова вашего класса, поэтому я не знаю, используете ли вы один и тот же экземпляр класса 100 раз или более, или вы создаете новые объекты.

Это тот тип анализа, который вам необходимо выполнить, когда спрашиваете, должно ли что-то быть volatile или нет.

Кроме того, что касается безопасности ваших потоков, что происходит в следующих функциях:

 client.doReconnectionStuff();
 client.doReconnectionStuff2();

Используют ли они какое-либо общее состояние из вашего Worker класса?Они разделяют и изменяют любое другое использование состояния другим потоком?Если да, вам нужно выполнить соответствующую синхронизацию.

Если нет, то все в порядке.

Потоки требуют некоторого размышления, вам нужно задать себе эти вопросы.Вам нужно посмотреть на все состояние и задаться вопросом, разделяете ли вы.Если вы имеете дело с указателями, вам нужно знать, кто владеет указателем, и делитесь ли вы им когда-либо между потоками, случайно или нет, и действовать соответствующим образом.Если вы передаете указатель на функцию, которая запускается в другом потоке, вы делитесь объектом, на который указывает указатель.Если затем вы измените то, на что он указывает, в этом новом потоке, вы поделитесь им и должны синхронизироваться.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...