Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Интересная задачка на использование препроцессора и ума :-)  (Прочитано 9297 раз)
0 Пользователей и 2 Гостей смотрят эту тему.
djyuran
Гость
« : 23-05-2004 05:55 » 

Вот так она звучит:

C++. Supposed you have class Mutex with two methods ‘lock’ and ‘unlock’ that can be used to guard the shared resource, for example:

Mutex mutex;
int sharedVariable;

mutex.lock();
sharedVariable = 5;
mutex.unlock();

In Java there is ‘synchronized’ keyword that is used to serialize access from different threads to the shared resource, and the above example could be written as

   Object mutex;
   int sharedVariable;

   synchronized(mutex)
   {
      sharedVariable = 5;
   }

which is more safe, since the synchronized scope is explicitly indicated with the curly braces and the compiler will complain if you omitted it. The question: how to implement this feature in C++ language? It should be undistinguished from Java. The hint: use preprocessor and scooping rules for object destructors. (approx. 1 hour)

Вообще можно ли сделать так же в С++. Вот если бы не было { } ( т.е. заключить синхронизируемый код в ( ) ), то тогда вроде бы понятно... Но в то же время если бы нельзя было сделать, то задачка бы не существовала Улыбаюсь
Записан
Xeysan
Гость
« Ответ #1 : 23-05-2004 17:02 » 

На ум приходит схема с инструкцией if...
#define SYNC( MUTEX_TYPE ) if( MUTEX_TYPE().lock() || true )
true - кривовато, чтобы if стработало.
Деструктор вызовет unlock.
Записан
npak
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #2 : 23-05-2004 17:17 » 

В языке с++ перменная, объявленная в инициализаторе цикла for, освобождается при завершения цикла.

Надо сделать класс, в конструкторе которого мутекс запирается, а в деструкторе мутекс отпирается, а так же две операции -- инкремент и проверка на завершение (для организации цикла)

Пример кода:
Код:
include <iostream>

class Mutex
{
private:
public:
    Mutex() {}
    ~Mutex() {}
    void lock() { std::cerr << "Locked\n"; }
    void unlock() { std::cerr << "Unocked\n"; }
};

class Local_Lock {
private:
    Mutex & _mutex;
    int _i;
public:
    Local_Lock(Mutex & mutex) : _mutex(mutex), _i(0) { _mutex.lock(); }
    ~Local_Lock() { _mutex.unlock(); }
    bool test() { return (_i == 0); }
    void next() { _i ++; }
};

#define syncronized(mutex) for (Local_Lock __local_lock_var(mutex); __local_lock_var.test(); __local_lock_var.next())

int main()
{
    Mutex & m = *(new Mutex);

    syncronized(m) {
        std::cerr << "In 'syncronized' block\n";
        Mutex & m2 = *(new Mutex);
        syncronized(m2) {std::cerr << "In 'syncronized' block, 2\n"; }
    }
    for (Local_Lock ll(m); ll.test() ; ll.next())
    { std::cerr << "In ''for'' block\n"; }
   
    return 0;
}

Программа порождает такой вывод:
Цитата
Locked
In 'syncronized' block
Locked
In 'syncronized' block, 2
Unocked
Unocked
Locked
In ''for'' block
Unocked
« Последнее редактирование: 25-11-2007 21:44 от Алексей1153++ » Записан

UniTesK -- индустриальная технология надежного тестирования.

http://www.unitesk.com/ru/
NetRaider
Гость
« Ответ #3 : 23-05-2004 22:58 » 

Для vc6 необходимо в начало макроса добавить 'if(false){}else'
Записан
Anonymous
Гость
« Ответ #4 : 24-05-2004 08:51 » 

NetRaider, прямо шаманство какое-то  Я шокирован!

Я свой пример проверял на g++ 3.3, работало нормально без этого трюка.  Спасибо за подсказку.
Записан
npak
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #5 : 24-05-2004 08:53 » 

это я оказался Гостем, коннект порвался Улыбаюсь
Записан

UniTesK -- индустриальная технология надежного тестирования.

http://www.unitesk.com/ru/
djyuran
Гость
« Ответ #6 : 24-05-2004 12:37 » 

Вот мой вариант. Не пойму, зачем цикл?

class TempMutex
{
      Mutex& m_mutex;
public:
      TempMutex(Mutex& mutex): m_mutex(mutex){m_mutex.lock(); }
      ~TempMutex() { m_mutex.unlock(); }
      operator bool() { return true; }
};

#define syncronized(mutex) if (TempMutex(mutex))

2NetRaider: у меня и так все работает!
Записан
npak
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #7 : 24-05-2004 12:53 » 

В твоём способе временный объект создаётся, производится проверка и объект УНИЧТОЖАЕТСЯ.  Сразу.  До выполнения кода в синхронизированном блоке.  То есть мутекс будет открыт в блоке и синхронизации достичь не удастся.
Цитата
mutex_1.lock
mutex_1.unlock
In 'syncronized' block
mutex_2.lock
mutex_2.unlock
In 'syncronized' block, 2


Цикл используется для того, чтобы гарантировать удаление временного объекта ПОСЛЕ блока.  NetRaider предложил обернуть цикл ещё в один блок (блок else), чтобы деструктор для временного объекта гарантированно вызвался СРАЗУ после синхронизированного блока.  Похоже, что в VC 6.0 вызов деструктора для временного объекта откладывается до конца объемлющего блока.
Записан

UniTesK -- индустриальная технология надежного тестирования.

http://www.unitesk.com/ru/
djyuran
Гость
« Ответ #8 : 24-05-2004 13:46 » 

2npak: Да ты прав - слона-то я и не заметил Улыбаюсь!
Записан
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines