Синхронизация объекта контекста - PullRequest
1 голос
/ 27 февраля 2012

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

class SomeType1;
class SomeType2;    
class dummy;

//context for first domain
class foo
{
public:
    virtual void setPtr1 (SomeType1* val) = 0;
    virtual SomeType2* getPtr2 () = 0;

    static foo* getCTX()
    {
        //statement bellow is a singleton which creates one instance of dummy and
        //returns its address as foo*
        return AppCTX::AccessorType<dummy>::getCTX<foo>();
    }
    virtual ~foo();
};

//context for second domain
class bar
{
public:
    virtual void setPtr2 (SomeType2* val) = 0;
    virtual SomeType1* getPtr1 () = 0;
    static bar* getCTX()
    {
         //same as above but casts dummy* to bar*
         return AppCTX::AccessorType<dummy>::getCTX<bar>();
    }
    virtual ~bar();
};

//dummy is a singleton created in AppCTX::AccessorType<dummy>
class dummy: public foo, public bar
{
public:
    virtual void setPtr1 (SomeType1* val)
    {
         ptr1 = val;
    }

    virtual SomeType1* getPtr1 ()
    {
         return ptr1;
    } 

    virtual void setPtr2 (SomeType2* val)
    {
         ptr2 = val;
    }

    virtual SomeType2* getPtr2 ()
    {
         return ptr2;
    } 
    virtual ~dummy();
private:
    SomeType1* ptr1;
    SomeType2* ptr2;
};

Мои домены запускают несколько потоков, которые также используют контекст, поэтому к ptr1 и ptr2 можно обращаться параллельно. Нужно ли синхронизировать setPtrs и getPtrs с мьютексами? Есть ли вероятность, что ptr1 и ptr2 могут как-то испортиться?

1 Ответ

1 голос
/ 27 февраля 2012

Будет не очень полезно мьютексировать функции getPtr и setPtr. Даже после того, как вызывающая сторона получает указатель и освобождает мьютекс, она все равно может делать с полученным указателем все, что захочет. Это определенно может вызвать проблемы с несколькими потоками.

Вы действительно хотите поместить свои механизмы блокировки в сами классы SomeType1 и SomeType2. Например, вы можете получить мьютекс в начале каждой функции-члена SomeType1, а затем освободить мьютекс перед возвратом каждой функции-члена.

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

Но если вас беспокоит то, что сами переменные-указатели будут повреждены, это зависит от архитектуры машины, для которой вы компилируете. Для многих систем (для которых присвоение 32-битного указателя является атомарной операцией) это не будет проблемой вообще. На этот вопрос дан более полный ответ здесь .

...