Преобразование ключевого слова блокировки C # в C ++ - PullRequest
7 голосов
/ 03 января 2011

Как я могу реализовать ключевое слово блокировки C # в C ++?Код в c # выглядит следующим образом:

try
{
  lock (matrixLock)
  {
    ThisTransformation.get_Renamed(matrix);
  }
}

Ответы [ 9 ]

4 голосов
/ 20 ноября 2011

A.- Быстрый ответ

Предполагается, что у вас есть объект Mutex и Lock (ваш пробег может отличаться):

#define MY_OWN_LOCK(mm_mutex)                                         \
                                                                      \
    if(bool b_1227F2B8_136B_11E1_973D_7D0B4924019B = false)           \
        ;                                                             \
    else                                                              \
        for(Lock lock_1227F2B8_136B_11E1_973D_7D0B4924019B(mm_mutex); \
            !b_1227F2B8_136B_11E1_973D_7D0B4924019B;                  \
            b_1227F2B8_136B_11E1_973D_7D0B4924019B = true)

, который можно использовать как:

Mutex mutex ;

void foo()
{
    // not locked

    MY_OWN_LOCK(mutex)
    {
       // locked
    }

    // not locked
}

B.- Подробный ответ

Это зависит от библиотеки, которую вы будете использовать.

B.1 - Предварительные условия

Предположим, у вас есть:

  • a Mutex объект, который имеет lock() и unlock() методы
  • a Lock объект, который имеет конструктор с Mutex в качестве параметра и вызывает его lock() метод при строительстве и unlock() метод при разрушении

Итак, у вас есть что-то вроде:

class Mutex
{
    public :
        lock() ;
        unlock() ;
        // etc.
} ;

class Lock
{
    Mutex & m_mutex ;
    public :
        Lock(Mutex & p_mutex) : m_mutex(p_mutex)
            { this->m_mutex.lock() ; }
        ~Lock()
            { this->m_mutex.unlock() ; }
        // etc.
} ;

B.2 - Raw C + использование

Если вы не знакомы с RAII C ++, ваш код будет выглядеть следующим образом:

void foo()
{
   // not locked
   mutex.lock() ;
   // locked !
   mutex.unlock() ;
   // not locked
}

Этот код настолько неправильный, что я никогда не буду его обсуждать (Google "исключительная безопасность", если необходимо).

B.3 - использование необработанного C ++

void foo()
{
   // not locked
   {
      Lock lock(mutex) ;
      // locked !
   }
   // not locked
}

B.4 - использование макросов с расширенным C ++

со следующим макросом:

#define LOCK(mm_mutex)                                     \
                                                           \
                 if(bool b = false)                        \
                    ;                                      \
                 else                                      \
                    for(Lock lock(mm_mutex); !b; b = true)

Вы будетев состоянии написать:

void foo()
{
   // not locked

   LOCK(mutex)
   {
      // locked !
   }

   // not locked
}

B.5 - Почему это так сложно?

Большинство макросов блокировки полагаются на объект блокировки для проверки.Для этого требуется либо реализация Safe Bool Idiom (что является избыточным для текущего использования), либо необходимость в объекте блокировки, который можно привести к bool, что приводит к его собственному (большому) наборунедостатки в классе.

В текущей реализации if используется для объявления логического значения, которое будет контролировать выполнение тела for, тогда как сам for используется для объявления Lock сам объект.

Я полагаю, что этот шаблон называется чем-то вроде "инъекции переменной C ++".

B.6 - Производительность?

Обратите внимание, что вы что-то блокируетепоэтому код внутри mutex.lock() и mutex.unlock() будет занимать намного больше циклов, чем что-либо в макросе.

В неоптимизированных сборках будут отображаться переходы if и for (например,попробуйте пошагово на визуальном отладчике), но в оптимизированной сборке все if и for будут оптимизированы (нет разницы между сборкой, сгенерированной "использованием необработанного C ++" и макросом "использование C ++ ".

B.7 - Осторожно !!!

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

  • «пространство имен» имени макроса (то есть префикс его с каким-то уникальным именем, как BOOST_ часть макроса BOOST_FOREACH)
  • делает логическую b и переменную Lock lock уникальными, чтобы они не конфликтовали с кодом пользователя.Я обычно использую для этого суффикс GUID / UUID (например, b_ABCD_ABCD_AB_ABCDEF и lock_ABCD_ABCD_AB_ABCDEF)

B.8 - Источники

Я впервые увидел этот шаблон в статье (яверю Андрею Александреску), и действительно, я искал его, когда наткнулся на этот ТАК вопрос.

: -)

Как только я найду источник, я обновлю этоответ с правильной ссылкой.

Редактировать: Найдено источник !!!

3 голосов
/ 03 января 2011

Ключевое слово C # lock не является мьютексом . Вместо этого он вызывает Monitor::Enter() Попробуйте это. Также посмотрите на MSDN ссылка .

  // Request the lock, and block until it is obtained.
  Monitor::Enter(m_inputQueue);
  try
  {
     // Write your code here.
  }
  finally
  {
     // Ensure that the lock is released.
     Monitor::Exit(m_inputQueue);
  }

Примечание: этот ответ предполагает, что вы нацелены на C ++ CLI.

3 голосов
/ 03 января 2011

Вы можете использовать boost::mutex и boost::scoped_lock для этого:

boost::mutex matrix_mutex;

// ...
try {
    boost::scoped_lock lock(matrix_mutex);
    // ... everything in this scope is now locked
} // ....

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

1 голос
/ 24 февраля 2017

Я искал то же самое из фона c # и наткнулся на этот вопрос несколько раз ... Я знаю, что прошло много лет после того, как его спросили, но теперь с c ++ 11 вы можете использовать std :: lock_guard и синтаксисстало очень похоже на c #

, где в c # у вас есть

object syncObj;
...
lock(syncObj){ ... }

в c ++ 11, вы можете использовать мьютекс как синхронизацию и lock_guard аналогично блокировке

std::mutex m;
...
std::lock_guard<std::mutex> lock(m);{...}

если бы вы

#define lock(mutex) std::lock_guard<std::mutex> lock(mutex);

, тогда это действительно выглядело бы так же :)

1 голос
/ 03 января 2011

Я бы использовал библиотеку синхронизации Boost . Если вы не можете по какой-то причине, я бы взломал что-то вроде этого:

class CriticalSection {
    CRITICAL_SECTION m_cs;

public:
    CriticalSection() {
        ::InitializeCriticalSection(&m_cs);
    }

    ~CriticalSection() {
        ::DeleteCriticalSection(&m_cs);
    }

    void Lock() {
        ::EnterCriticalSection(&m_cs);
    }

    void Unlock() {
        ::LeaveCriticalSection(&m_cs);
    }
};

class CriticalSectionLocker {
    CriticalSection& m_cs;
    bool m_bLocked;
public:
    CriticalSectionLocker(CriticalSection& cs, bool bLockNow = true) : m_cs(cs), m_bLocked(bLockNow) {
        if(bLockNow)
            m_cs.Lock();
    }

    ~CriticalSectionLocker() {
        if(m_bLocked)
            m_cs.Unlock();
    }

    void Lock() {
        m_cs.Lock();
        m_bLocked = true;
    }

    void Unlock() {
        m_cs.Unlock();
        m_bLocked = false;
    }
};

Caveat Emptor: этот код не прошел через компилятор. YMMV.

Этот код позволяет вам делать такие вещи:

class SomeClass {
    CriticalSection m_cs;
    SomeResource m_resource;

public:
    void SomeOperation() {
        CriticalSectionLocker lock(m_cs);
        m_resource.DoSomething();
    }
};

Замок заблокирован в области действия SomeClass::SomeOperation(). Вы также можете снять блокировку, вызвав метод Unlock(), если вам больше не нужно удерживать блокировку.

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

1 голос
/ 03 января 2011

Вы не можете, такого ключевого слова не существует, самое близкое, что вы получите, это усиление блокировка области действия (которое может использовать буст-мьютекс).

1 голос
/ 03 января 2011

C ++ не имеет ключевого слова блокировки.Вы можете использовать мьютекс .

1 голос
/ 03 января 2011

Вот все, что вам нужно: Реализация ключевого слова блокировки в C ++

C ++ не имеет ключевого слова блокировки, но вы можете создать его самостоятельно. Учитывая класс Mutex, который имеет функции-члены Lock () и Unlock () (и, возможно, для удобства IsLocked ()), большинство программистов на C ++ немедленно пишут AutoLock, примерно так:

class AutoLock
{
public:
    AutoLock(Mutex& m): m_mutex(m)  { m_mutex.Lock(); }
    ~AutoLock()                     { m_mutex.Unlock(); }
    operator bool()                 { return m_mutex.IsLocked(); }
private:
    Mutex&   m_mutex;
};

Нормальное использование этой вещи будет выглядеть так:

{
    AutoLock lock(m_mutex);
    // my protected code here
}

Но с помощью простого трюка препроцессора вы можете сделать синтаксис идентичным C #:

#define lock(x) if (!(AutoLock _l = x)); else
0 голосов
/ 19 февраля 2019

Вы можете использовать std::lock_guard

Вот упрощенный пример из этой документации:

std::mutex resource_mutex;
...
{
    std::lock_guard<std::mutex> lock(resource_mutex); // The variable name ("lock") doesn't matter since it is not supposed to be used anywhere else.
    ...
    // safe to use resource here
    ...
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...