crossplatform.ru

Здравствуйте, гость ( Вход | Регистрация )

5 страниц V   1 2 3 > »   
Ответить в данную темуНачать новую тему
Litkevich Yuriy
  опции профиля:
сообщение 4.5.2008, 20:04
Сообщение #1


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9669
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

Спасибо сказали: 807 раз(а)




Репутация:   94  


Подбираю шаблон проектирования для моей задачи.
Задача такая:
Есть программа типа MDI, хочу сделать в ней многопользовательскую работу, в одно время работает только один пользователь.
В зависимости от группы пользователя ему становится доступным определенный, для данной группы, набор пунктов меню.

Я это так прикинул:
1-Нужно хранить переменную, например, uid, в которой указан код текущего пользователя/группы.
2-Нужен диалог ввода имени и пароля, который будет где-нибудь искать есть ли такая пара логин/пароль. Если есть, то устанавливать найденное значение в переменной uid. Если нет - ругнутся на пользователя.
3-Основное окно программы получает от диалога результат: ОК-пользователь найден, надо обновить меню, НЕ ОК - пользователь не найден, ничего не делать.

Но я подумал, что какому нибудь еще окну может понадобится знать uid, и поэтому я думаю, что простая глобальная переменная будет неудобна, и хочу сделать класс, в котором будет реализовандиалог авторизации и прочие штуки в том числе статическая переменная uid, а в других классах динамически создавать экземпляры, если сделать этот класс как "одиночку", то uid должен быть общим для всех экземпляров.
----
Вот такие мысли в моей голове, может уже есть для подобной задачи отработаный подход, и моя мысль слишком замудренная?
Просвятите пожалуйста.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
ViGOur
  опции профиля:
сообщение 4.5.2008, 21:12
Сообщение #2


Мастер
******

Группа: Модератор
Сообщений: 3296
Регистрация: 9.10.2007
Из: Москва
Пользователь №: 4

Спасибо сказали: 231 раз(а)




Репутация:   40  


Для твоей задачи можно использовать как глобальную переменную, так и Singleton. Singleton правда "красивше". :)
Немогу понять, что в чем именно заключается вопрос? Если в реализации Singleton'а, то это достаточно просто:
class CSingleton
{
private:
   static CSingleton *m_pThis;
   static int m_nCounter;

private:
   CSingleton(){}
   CSingleton( const CSingleton &){}
   ~CSingleton(){}
   operator=( const CSingleton&){}

public:
   static CSingleton *InitInstance();
   static void FreeInstance();
};

CSingleton *CSingleton::m_pThis=0;
int CSingleton::m_nCounter=0;

CSingleton *CSingleton::InitInstance()
{
   if( !m_pThis)
      m_pThis = new CSingleton();

   m_nCounter++;
   
   return m_pThis;   
}

void CSingleton::FreeInstance()
{
   if( m_nCounter>0)
      m_nCounter--;
   else
      return;

   if( m_nCounter==0)
   {
      delete m_pThis;
      m_pThis = 0;
   }
}
Примерно так, на наличие ошибок завтра проверю, а то сейчас уже голова не варит и студии под рукой нет. :)

Сообщение отредактировал ViGOur - 5.5.2008, 9:12
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 4.5.2008, 21:19
Сообщение #3


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9669
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

Спасибо сказали: 807 раз(а)




Репутация:   94  


Цитата(ViGOur @ 5.5.2008, 1:12) *
Singleton правда "красивше". Немогу понять, что в чем именно заключается вопрос?

в этом собственно и вопрос, какой путь выбрать? да и вообще было интересно знать правильный ли я шаблон проектирования выбрал или нет.
Видимо правильно.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 5.5.2008, 8:54
Сообщение #4


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9669
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

Спасибо сказали: 807 раз(а)




Репутация:   94  


слушай а функции InitInstance() и FreeInstance(); разве не должны быть объявлены как static, ведь они имеют дело со статической переменной?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
ViGOur
  опции профиля:
сообщение 5.5.2008, 9:11
Сообщение #5


Мастер
******

Группа: Модератор
Сообщений: 3296
Регистрация: 9.10.2007
Из: Москва
Пользователь №: 4

Спасибо сказали: 231 раз(а)




Репутация:   40  


Угу, именно так, только не потому, что статические переменные члены использует, а чтобы не создавать объект, который запрещено создавать вне класса. :)

Поправил.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 5.5.2008, 9:16
Сообщение #6


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9669
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

Спасибо сказали: 807 раз(а)




Репутация:   94  


еще вопрос по теме задачи:
В голове крутится вариант без "Одиночки", т.е. класс прсто содержащий переменную uid обявленную как static, т.е. у всех классов она общая, краем уха слышал, что такой вариант чреват последствиями, но какими не знаю, может прояснишь?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
ViGOur
  опции профиля:
сообщение 5.5.2008, 9:27
Сообщение #7


Мастер
******

Группа: Модератор
Сообщений: 3296
Регистрация: 9.10.2007
Из: Москва
Пользователь №: 4

Спасибо сказали: 231 раз(а)




Репутация:   40  


Да никаких последствий вроде не должно быть. :)
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 5.5.2008, 10:08
Сообщение #8


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9669
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

Спасибо сказали: 807 раз(а)




Репутация:   94  


положим "одиночку" я кладу в два файла singleton.h и singleton.cpp, заголовочный подстегиваю к разным файлам, которым он может понадобиться, а в каком месте программы объявлять статические переменные:
CSingleton *CSingleton::m_pThis=0;
int CSingleton::m_nCounter=0;

:blush2:
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
ViGOur
  опции профиля:
сообщение 5.5.2008, 10:20
Сообщение #9


Мастер
******

Группа: Модератор
Сообщений: 3296
Регистрация: 9.10.2007
Из: Москва
Пользователь №: 4

Спасибо сказали: 231 раз(а)




Репутация:   40  


Принципиальной разницы не вижу, я обычно это делаю в *.cpp. :)
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 5.5.2008, 10:27
Сообщение #10


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9669
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

Спасибо сказали: 807 раз(а)




Репутация:   94  


просто я подумал, что если в хидере будет, то он несколько раз будет скормлен компилеру, и в последствии линкер может подавиться, или не подавится?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
ViGOur
  опции профиля:
сообщение 5.5.2008, 10:39
Сообщение #11


Мастер
******

Группа: Модератор
Сообщений: 3296
Регистрация: 9.10.2007
Из: Москва
Пользователь №: 4

Спасибо сказали: 231 раз(а)




Репутация:   40  


Для этого и существуют такие директивы препороцессора как:
#ifndef _MYCLASS_H_
#define _MYCLASS_H_

class CMyClass{ ... };

#endif // _MYCLASS_H_
;)
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 5.5.2008, 10:42
Сообщение #12


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9669
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

Спасибо сказали: 807 раз(а)




Репутация:   94  


хе, правильно хидер то один и тот же, туплю :)
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Tonal
  опции профиля:
сообщение 5.5.2008, 11:02
Сообщение #13


Активный участник
***

Группа: Участник
Сообщений: 452
Регистрация: 6.12.2007
Из: Новосибирск
Пользователь №: 34

Спасибо сказали: 69 раз(а)




Репутация:   17  


Обычно синглетон (одиночка) без FreeInstance и без подсчёта ссылок пишется.
Простейший:
struct singleton_t {
  static singleton_t& instance() {
    static singleton_t inst;
    return inst;
  }
  //Здесь пишем нужные методы
  private:
    singleton_t() {/*код инициализации*/}
    ~singleton_t() {/*код очистки*/}
    singleton_t(const singleton_t&);
    singleton_t& operator=(const singleton_t&);
};

Мне кажется, он хорошо подойдёт, т.к. те проблемы, которые он имеет, в данном случае не существенны.

Собственно проблемы:
1) Возможные гонки потоков при создании.
Решаются или более хитрым методом instance - с правильными блокировками, или принудительным созданием до запуска потоков.
2) Обращение к разрушенному объекту. Когда кто-нибудь пытается обратится к instance, когда inst уже разрушен.
Т.к. разрушается экземпляр такого одиночки после выхода из main, то такое может происходить, только если обращение идёт из деструкторов других глобальных объектов.
Решение - или запретить такие обращения, или создавать одиночку в куче и никогда не убивать (хорошо описано у Александреску).
3) Неясный порядок разрушения. Когда такой одиночка захватывает ресурсы время жизни которых завязано на другие ресурсы, неподконтрольные одиночке - например он держит открытый запрос, а конектом к базе занимается приложение.
Решение - не делать так! :)
Другое решение - предоставить метод очистки, который должен вызываться перед закрытием коннекта к базе. После закрытия, или возвращать признак ошибки, либо брасать исключение (может быть опасно если вылетит в деструкторе), либо возвращать заглушки. :)

Сообщение отредактировал Tonal - 5.5.2008, 11:04
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 5.5.2008, 11:12
Сообщение #14


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9669
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

Спасибо сказали: 807 раз(а)




Репутация:   94  


а зачем вот эта строка:
Цитата(ViGOur @ 5.5.2008, 1:12) *
operator=( const CSingleton&){}

Цитата(Tonal @ 5.5.2008, 15:02) *
singleton_t& operator=(const singleton_t&);

, какую пользу она дает?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Andrew Selivanov
  опции профиля:
сообщение 5.5.2008, 11:19
Сообщение #15


Участник
**

Группа: Участник
Сообщений: 249
Регистрация: 9.10.2007
Из: Москва
Пользователь №: 3

Спасибо сказали: 15 раз(а)




Репутация:   6  


Цитата(Litkevich Yuriy @ 5.5.2008, 11:42) *
хе, правильно хидер то один и тот же, туплю :)

Посмотри книгу Modern C++ Design: Generic Programming and Design Patterns Applied
By Andrei Alexandrescu. Там все очень хорошо про singleton-ы и прочие шаблоны расписано.
О, оказывается она у меня есть на русском :) Кому надо вышлю в приват.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 5.5.2008, 11:25
Сообщение #16


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9669
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

Спасибо сказали: 807 раз(а)




Репутация:   94  


у меня есть Эрих Гамма, там тоже есть примеры, но пока для меня это ново и требует время на переваривание, тем более, что я незнаю как лучше применить этот шаблон, толи сделать его универсальным, в отдельном модуле в виде шаблонного класса, и потом делать от него наследование, либо сделать класс только для моей задачи, но если мне опять понадобится "одиночка" писать заново.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
ViGOur
  опции профиля:
сообщение 5.5.2008, 11:44
Сообщение #17


Мастер
******

Группа: Модератор
Сообщений: 3296
Регистрация: 9.10.2007
Из: Москва
Пользователь №: 4

Спасибо сказали: 231 раз(а)




Репутация:   40  


Цитата(Litkevich Yuriy @ 5.5.2008, 12:12) *
какую пользу она дает?
Этим мы просто говорим, что оператор присваивания нашего Singleton'a закрытый, чтобы небыло неправомерной раздачи ссылок на него.
Как ты мог заметить также закрытыми созданы: конструктор, деструктор, и конструктор копирования.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 5.5.2008, 11:45
Сообщение #18


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9669
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

Спасибо сказали: 807 раз(а)




Репутация:   94  


да, про конструктор/деструктор я понял, это чтоб никто не мог создать дубликат
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 5.5.2008, 12:29
Сообщение #19


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9669
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

Спасибо сказали: 807 раз(а)




Репутация:   94  


Например, в Qt'ях я применяю такую строку:
QTextCodec::setCodecForCStrings(QTextCodec::codecForName("Windows-1251"));


Если я ни где не создаю экземпляр класса QTextCodec, то можно ли пользоватся таким вариантом в место "одиночки"?
Правильно ли я понял, что "одиночка" спасает от "случайного" создания/удаления экземпляра?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
ViGOur
  опции профиля:
сообщение 5.5.2008, 12:42
Сообщение #20


Мастер
******

Группа: Модератор
Сообщений: 3296
Регистрация: 9.10.2007
Из: Москва
Пользователь №: 4

Спасибо сказали: 231 раз(а)




Репутация:   40  


Тот пример, что ты привел, обычная статическая функция.
Класс одиночка - это класс для которого можно создать только один объект...
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 14.5.2008, 10:29
Сообщение #21


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9669
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

Спасибо сказали: 807 раз(а)




Репутация:   94  


=1=
ViGOur, у меня компилер ругается на такую строчку, из твоего варианта "одиночки":
operator=( const CSingleton&){}

говорит так:
Цитата
singleton.h:26: error: ISO C++ forbids declaration of `operator=' with no type

я его пока закоментировал и вроде проблем не испытываю, но хочется чтоб все было правильно, что нужно исправить?

=2=
Обязательно ли мои методы, не отоносящиеся к основным "одиночки" типа InitInstance() и FreeInstance(), помечать как sttic?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Andrew Selivanov
  опции профиля:
сообщение 14.5.2008, 11:11
Сообщение #22


Участник
**

Группа: Участник
Сообщений: 249
Регистрация: 9.10.2007
Из: Москва
Пользователь №: 3

Спасибо сказали: 15 раз(а)




Репутация:   6  


Цитата(Litkevich Yuriy @ 14.5.2008, 11:29) *
=1=
ViGOur, у меня компилер ругается на такую строчку, из твоего варианта "одиночки":
operator=( const CSingleton&){}

говорит так:
Цитата
singleton.h:26: error: ISO C++ forbids declaration of `operator=' with no type

я его пока закоментировал и вроде проблем не испытываю, но хочется чтоб все было правильно, что нужно исправить?

Попробуй вот так специфицировать
CSingleton& operator=( const CSingleton& )
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
ViGOur
  опции профиля:
сообщение 14.5.2008, 11:36
Сообщение #23


Мастер
******

Группа: Модератор
Сообщений: 3296
Регистрация: 9.10.2007
Из: Москва
Пользователь №: 4

Спасибо сказали: 231 раз(а)




Репутация:   40  


Цитата(Andrew Selivanov @ 14.5.2008, 12:11) *
Попробуй вот так специфицировать
Угу, я забыл написать... :)
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 14.5.2008, 11:43
Сообщение #24


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9669
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

Спасибо сказали: 807 раз(а)




Репутация:   94  


тогда вот так ругается :
Цитата
singleton.h:26: warning: no return statement in function returning non-void

хоть и не ошибка, но неприятно.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
LuckLess
  опции профиля:
сообщение 14.5.2008, 11:44
Сообщение #25


Студент
*

Группа: Новичок
Сообщений: 31
Регистрация: 10.10.2007
Пользователь №: 8

Спасибо сказали: 0 раз(а)




Репутация:   0  


return *this;
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 14.5.2008, 11:46
Сообщение #26


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9669
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

Спасибо сказали: 807 раз(а)




Репутация:   94  


LuckLess, да вот так:
Session& operator=(const Session&){return *this;}

вообще не ругается
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
LuckLess
  опции профиля:
сообщение 14.5.2008, 11:56
Сообщение #27


Студент
*

Группа: Новичок
Сообщений: 31
Регистрация: 10.10.2007
Пользователь №: 8

Спасибо сказали: 0 раз(а)




Репутация:   0  


еще такой вариант синглтона..
template <class T, int I = 0>
class LLSingleton
   {
private:
   LLSingleton ();
   LLSingleton (const LLSingleton&);
   LLSingleton& operator= (const LLSingleton&);
public:
   static T* Get ()
      {
      static T inst_;
      return &inst_;
      }
   };

typedef LLSingleton<int> TInt1;
typedef LLSingleton<int, 1> TInt2;

int main ()
   {
   *TInt1::Get () = 77;
   *TInt2::Get () = 88;

   std::cout << *TInt1::Get () << " " << *TInt2::Get ();
   }
Причина редактирования: поправил тег: code=cpp, так нагляднее
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 14.5.2008, 12:08
Сообщение #28


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9669
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

Спасибо сказали: 807 раз(а)




Репутация:   94  


а для чего int I, она ведь неиспользуется, в шаблоне?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
LuckLess
  опции профиля:
сообщение 14.5.2008, 14:13
Сообщение #29


Студент
*

Группа: Новичок
Сообщений: 31
Регистрация: 10.10.2007
Пользователь №: 8

Спасибо сказали: 0 раз(а)




Репутация:   0  


для того чтобы ты мог создать два разных синглтона, одного типа.
например у тебя есть class User; ты хочеш чтобы был скажем глобальный залогиненный юзер - пишеш
typedef LLSingleton<User> LoggedUser;
далее ты хочеш еще иметь некого глобального юзера, под которым программа имеет доступ к базе..
пишеш
typedef LLSingleton<User, 1> DbUser;

получиш два разных синглтона, которые оба возвращают User*.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 16.5.2008, 12:50
Сообщение #30


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9669
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

Спасибо сказали: 807 раз(а)




Репутация:   94  


с каждым днем начинаю понимать пользу от единственного экземпляра класса, раньше думал: "пиши окуратно и дело с концом", а на практике выходит, что окуратность особо и не причем :)
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 27.9.2009, 21:16
Сообщение #31


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9669
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

Спасибо сказали: 807 раз(а)




Репутация:   94  


В итоге получилось так:
singleton.h
#ifndef SINGLETON_H
#define SINGLETON_H

class Session
{
private:
    static Session    *p_this;
    static int        cnt;
    
private:
    Session();
    Session(const Session &){} // конструктор копирования, не использует побитовое копирование
    ~Session(){}
    Session& operator=(const Session&){return *this;}
    
public:
    static Session *InitInstance();    /*!< Создает экземпляр класса. */
    static void        FreeInstance();    /*!< Удаляет экземпляр класса. */

};

#endif //

singleton.cpp
/*!
 *    \file    singleton.cpp
 *    \brief    Реализация класса "Управлние сессиями".
 */
#include <QDir>
#include "singleton.h"

//определяем переменные и константы
Session *Session::p_this=0;
int Session::cnt=0;

Session::Session()
{
    // Инициализация внутренних прикладных потрохов

}

// Псевдоконструктор
Session *Session::InitInstance()
{
    if( !p_this)
    {
        p_this = new Session();
    }

    cnt++;
    return p_this;   
}

// Псевдодеструктор
void Session::FreeInstance()
{
    if (cnt>0)
        cnt--;
    else
        return;

    if (cnt==0)
    {
        delete p_this;
        p_this = 0;
    }
}

//===========================================================
//        Всякие внутренние прикладные функции
//===========================================================
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Влад
  опции профиля:
сообщение 27.9.2009, 21:47
Сообщение #32


Участник
**

Группа: Участник
Сообщений: 146
Регистрация: 20.3.2009
Из: Санкт-Петербург
Пользователь №: 627

Спасибо сказали: 46 раз(а)




Репутация:   8  


Юрий, по твоей реализации (кстати, практически классической!) у меня только два замечания:
1. конструкторы-деструкторы, которые ты хочешь скрыть, не обязательно реализовывать с пустым телом {}, достаточно просто объявить их private;
2. учти, что эта реализация работает только в строго однопоточной модели! В многопоточной ты либо "влетишь", либо надо реализовывать Double-Check Locking. Это, впрочем, тоже классика.

А так ничего, вполне себе красиво!...
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 27.9.2009, 23:17
Сообщение #33


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9669
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

Спасибо сказали: 807 раз(а)




Репутация:   94  


Цитата(Влад @ 28.9.2009, 1:47) *
1. конструкторы-деструкторы, которые ты хочешь скрыть, не обязательно реализовывать с пустым телом {}, достаточно просто объявить их private;
они у меня с пустым телом, т.к. в моём применении они были не нужны.

Цитата(Влад @ 28.9.2009, 1:47) *
надо реализовывать Double-Check Locking.
имеется в виду для основных переменных "Одиночки" (*p_this и cnt)?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
AD
  опции профиля:
сообщение 27.9.2009, 23:56
Сообщение #34


Профессионал
*****

Группа: Участник
Сообщений: 2003
Регистрация: 4.2.2008
Из: S-Petersburg
Пользователь №: 84

Спасибо сказали: 70 раз(а)




Репутация:   17  


Цитата(Litkevich Yuriy @ 28.9.2009, 0:17) *
Цитата(Влад @ 28.9.2009, 1:47) *
1. конструкторы-деструкторы, которые ты хочешь скрыть, не обязательно реализовывать с пустым телом {}, достаточно просто объявить их private;
они у меня с пустым телом, т.к. в моём применении они были не нужны.

Ну вот, раз не нужны, то можно объявлять вообще без тела!
Цитата(Litkevich Yuriy @ 28.9.2009, 0:17) *
имеется в виду для основных переменных "Одиночки" (*p_this и cnt)?

Нет. В смысле сделать так:
mutex.lock()
//<какая-то проверка>
mutex.lock()
/// что-то делается....
mutex.unlock()
mutex.unlock()

Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Влад
  опции профиля:
сообщение 28.9.2009, 11:23
Сообщение #35


Участник
**

Группа: Участник
Сообщений: 146
Регистрация: 20.3.2009
Из: Санкт-Петербург
Пользователь №: 627

Спасибо сказали: 46 раз(а)




Репутация:   8  


Не совсем так. Правильный (имхо) пример кода приведен ниже:
template <class T>
class Singleton
{
    .........
    
private:
    static T* volatile m_me;
};

template <class T>
T& Singleton<T>::Instance()
{
    if (!m_me)
    {
        Locker lock(m_cs);
        if (!m_me)
        {
            m_me = new T;
        }
    }
    return (*m_me);
}

template <class T>
void Singleton<T>::FreeInstance()
{
    if (m_me)
    {
        Locker lock(m_cs);
        if (m_me)
        {
            delete m_me;
            m_me = NULL;
        }
    }
}
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 28.9.2009, 18:45
Сообщение #36


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9669
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

Спасибо сказали: 807 раз(а)




Репутация:   94  


Влад, поясни пожалуйста свой код.

И m_cs что такое?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
AD
  опции профиля:
сообщение 28.9.2009, 20:25
Сообщение #37


Профессионал
*****

Группа: Участник
Сообщений: 2003
Регистрация: 4.2.2008
Из: S-Petersburg
Пользователь №: 84

Спасибо сказали: 70 раз(а)




Репутация:   17  


Цитата(Litkevich Yuriy @ 28.9.2009, 19:45) *
Влад, поясни пожалуйста свой код.

И m_cs что такое?

Я не Влад, но могу пояснить. Собственно, m_cs указатель на объект одиночки!
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 28.9.2009, 20:29
Сообщение #38


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9669
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

Спасибо сказали: 807 раз(а)




Репутация:   94  


AD, указатель в его примере - m_me
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Влад
  опции профиля:
сообщение 28.9.2009, 20:46
Сообщение #39


Участник
**

Группа: Участник
Сообщений: 146
Регистрация: 20.3.2009
Из: Санкт-Петербург
Пользователь №: 627

Спасибо сказали: 46 раз(а)




Репутация:   8  


Ага, этот пример кода выдран с корнем из реально работающего (уж года два как... в режиме 24x7) проекта. m_me - это как раз и есть объект-одиночка, а m_cs - это объект блокировки (под MFC это критическая секция, но, в принципе, с таким же точно успехом при минимальной модификации кода может быть и posix-ный mutex). В коде принципиально, что m_me должен быть именно volatile.

Это - просто пример реализации идиомы Double-Checked Locking, а более подробно о ней может рассказать и гугл; по-моему, тема подробно освещена у классиков типа Мейерса, Саттера.... вот только не помню, у кого точно.

Сообщение отредактировал Влад - 28.9.2009, 20:49
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 28.9.2009, 21:13
Сообщение #40


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9669
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

Спасибо сказали: 807 раз(а)




Репутация:   94  


Цитата(Влад @ 29.9.2009, 0:46) *
Double-Checked Locking
а Почему собственно Double? вроде в каждой фукции блокировка одна
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
AD
  опции профиля:
сообщение 28.9.2009, 21:16
Сообщение #41


Профессионал
*****

Группа: Участник
Сообщений: 2003
Регистрация: 4.2.2008
Из: S-Petersburg
Пользователь №: 84

Спасибо сказали: 70 раз(а)




Репутация:   17  


Цитата(Litkevich Yuriy @ 28.9.2009, 22:13) *
а Почему собственно Double? вроде в каждой фукции блокировка одна

Идет двойная проверка. А описано подробно у Александреску! А мне спать больше надо, тогда буду внимательнее... Простите, если что!

Сообщение отредактировал AD - 28.9.2009, 21:17
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 28.9.2009, 21:59
Сообщение #42


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9669
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

Спасибо сказали: 807 раз(а)




Репутация:   94  


ага, уже разобрался, в Вкикпедии прочитал
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Влад
  опции профиля:
сообщение 29.9.2009, 16:23
Сообщение #43


Участник
**

Группа: Участник
Сообщений: 146
Регистрация: 20.3.2009
Из: Санкт-Петербург
Пользователь №: 627

Спасибо сказали: 46 раз(а)




Репутация:   8  


Гм, ну если уж говорить о кроссплатформе, то наиболее изящным решением представляется применение boost::call_once вкупе с boost::once_flag.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение

5 страниц V   1 2 3 > » 
Быстрый ответОтветить в данную темуНачать новую тему
Теги
Нет тегов для показа


1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0


RSS Рейтинг@Mail.ru Текстовая версия Сейчас: 10.4.2025, 6:59