Как стать автором
Обновить

Комментарии 50

А давайте просто скажем одно ключевое слово — RAII, и не просто дадим людям рыбу, но и научим её ловить раз и навсегда?
Спасибо, добавил в начале упоминание об этом.
Конечно. Но использовать QT в качестве коллекции велосипедов, как мне кажется, не очень разумно. Не особо представляю себе причины, которые могут побудить человека использовать QT в демоне, например.
А что с QT в этом смысле не так?
Размер программы, в первую очередь.
Да и ни к чему тянуть сторонние библиотеки ради пары макросов и классов.
>Размер программы, в первую очередь.

$ cat main_stl.cpp 
#include <string>
#include <iostream>

int main(int argc, char* argv[]) {
	std::string s = "Hello, world!";
	std::cout << s << std::endl;
	return 0;
}

$ cat main_qt.cpp 
#include <QString>
#include <QDebug>

int main(int argc, char* argv[]) {
	QString s = "Hello, world!";
	qDebug() << s;
	return 0;
}

$ cat strings_qt.pro 
TARGET   = strings_qt
SOURCES  = main_qt.cpp

$ qmake && make 1>/dev/null 2>1
$ g++ main_stl.cpp -o strings_stl
$ ls -l strings_*
-rwxr-xr-x 1 mikhail mikhail 9125 2009-11-13 15:45 strings_qt
-rwxr-xr-x 1 mikhail mikhail 9364 2009-11-13 15:45 strings_stl

$ strip strings_*
$ ls -l strings_*
-rwxr-xr-x 1 mikhail mikhail 5692 2009-11-13 15:46 strings_qt
-rwxr-xr-x 1 mikhail mikhail 5684 2009-11-13 15:46 strings_stl

Вы какой именно размер имели в виду? :)

>Да и ни к чему тянуть сторонние библиотеки ради пары макросов и классов.

Сторонние библиотеки для того и созданы ;)
Что касается Qt — то libQtCore весит 2 мегабайта. Как по мне — вполне приемлемый размер (для того, что она несёт внутри).
НЛО прилетело и опубликовало эту надпись здесь
Да просто смысла нет. =)
А почему бы не построить некоторые моменты демона на томже Qt, проблемы в этом не вижу. Знаю пример решения задачи разработки демона под FreeBSD (тз такое), но человек владел разработкой только под WIN, а разбираться в тонкостях UNIX времени не было. На помощь пришел Qt, что облегчило разработку в разы:
— любимыая, удобная IDE;
— интуитивно понятная архитектура библиотеки;
— все необходимые абстракции от платформы.

Как итог все счастливы и довольны.
Ну, если надо срочно, а опыта с никсами нет, то может и осмысленно. Но в обычном случае это все-таки из пушки по воробьям.
Да, есть что-то похожее, но:
— нужно подключать стороннюю библиотеку
— не понял исходя из текста, каким образом в упомянутых классах я могу выбрать объект синхронизации: мютекс или критическая секция (Win).
— слишком «много букв» :)

Там шаблон на шаблоне и шаблоном погоняет. Какой объект ему подставишь туда, такой и будет. И никаких системных типов, все через объекты той же библиотеки.
Кстати, подключать там вроде бы ничего особо не надо. Половина boost — это только .h, линковать там что-то приходится не так уж часто, особенно в таких вот «оберточных» частях.
НЛО прилетело и опубликовало эту надпись здесь
А что бы вы хотели услышать?
В STL есть очень удобный класс-шаблон std::auto_ptr<>, освобождающий память по указателю при уничтожении объекта этого класса.
Который объявлен deprecated в c++0x. Вместо auto_ptr следует использовать unique_ptr, так как он поддерживает только явные операции с семантикой смены владения объектом.
НЛО прилетело и опубликовало эту надпись здесь
В MSDN по этому поводу пишут кратко и емко.
Я не сказал бы, что имеет смысл действительно ипользовать эту штуковину в реальных проектах, ведь есть множество уже готовых и заведомо лучших решений.
Однако, большое спасибо за статью об устройстве мьютексов.
Проблема: макрос SCOPE_LOCK_MUTEX не получится использовать два раза в одном и том же блоке.
обычно это и не нужно
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
inline для метода, объявленного внутри класса вообще не нужно, оно там подразумевается.
НЛО прилетело и опубликовало эту надпись здесь
ISO 14882, 7.1.2.3:

A function defined within a class definition is an inline function. The inline specifier shall not appear on a block scope function declaration.
НЛО прилетело и опубликовало эту надпись здесь
Далеко не всегда это можно так просто решить. Вот вы определите функцию в файле code.cc, а в заголовке оставите только forward declaration. Тут может помочь только whole program optimization при условии что компилируются сразу все файлы исходного кода вместе. А если перенесёте функцию из code.cc в заголовочный файл, то опишете её как static, иначе получите одну и ту же функцию определённую несколько раз в разных объектниках. Теперь если такой заголовок включить в code2.cc, в котором именно эта функция не нужна, но нужна какая-то другая, то получим warning от компилятора про неиспользуемую функцию.
НЛО прилетело и опубликовало эту надпись здесь
code.h: void f() {...}
code2.cc: #include «code.h»
code3.cc: #include «code.h»

компилируем
code2.cc ->code2.o
code3.cc ->code3.o

линкуем
code2.o + code3.o = error, f() два раза определена
согласен, убрал
Поправьте пожалуйста первый кусок кода. Там вместо CAutoMutex тот же CMutexLock.
опередили:)
поправлено
еще неплохо бы дописать про рекурсивные мьютексы тогда.
А именно

f()
{
AutoMutex m;
f();
}

рекурсивный мьютекс — сможет зайти сам в себя, нерекурсивный нет.

зы. boost::mutex::scoped_lock lock(mutex); тоже кстати решает эту задачу
В Windows мютексы по умолчанию рекурсивные, а в Unix — нерекурсивные.
Чтобы в Unix сделать мютекс рекурсивным, необходимо установить соответствующий флаг при инициализации. Класс CAutoMutex выглядел бы так (проверки возвращаемых значений не показаны для компактности):
class CAutoMutex
{
  pthread_mutex_t m_mutex;

  CAutoMutex(const CAutoMutex&);
  CAutoMutex& operator=(const CAutoMutex&);

public:
  inline CAutoMutex()
  {
    pthread_mutexattr_t attr;
    pthread_mutexattr_init(&attr);
    pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
    pthread_mutex_init(&m_mutex, &attr);
    pthread_mutexattr_destroy(&attr);
  }
  inline ~CAutoMutex()
  {
    pthread_mutex_destroy(&m_mutex);
  }
  inline pthread_mutex_t& get()
  {
    return m_mutex;
  }
};


* This source code was highlighted with Source Code Highlighter.

а как в винде сделать нерекурсивный?
полностью аналогичным образом можно использовать семафор с максимальным счетчиком 1, он будет нерекурсивным.
HANDLE sem_1 = CreateSemaphore(NULL, 1, 1, NULL)

> При написании многопоточных приложений…

Виндовые мьютексы для синхронизации тредов — не из пушки ли по воробьям? Критической секции обычно хватает за глаза.
> Ниже рассматривается работа с мютексами в Windows и Unix
И где там Unix?
1. Зачем каждый раз писать get в auto locker-e? Можно сделать чтобы он принимал не только handle но и объект мютекс вами написаный.
2. Зачем делать #define не понятно. Какая разница что запоминать, как класс автолокера называется или как макрос пишется?
Для элегантности еще убрать макрос хорошо было бы.
Ну и упоминание про Unix как-то не к месту, позиксовые мютексы отличаются в обработке, заметно.
Присоединяюсь ко всем остальным по поводу той мысли, что не надо строить велосипеды, но спешу добавить, что порой, сделать велосипед — это единственный способ разобраться в чем-либо. Совет автору статьи — почитайте Рихтера «Windows via C/C++» и скачайте примеры кода к этой книге, там уже большинство всего необходимого реализовано.
>спешу добавить, что порой, сделать велосипед — это единственный способ разобраться в чем-либо.
полностью согласен

Статья в себе сочетает отрывки из Стивенсова про мьютексы и принципа Александреску: один ресурс — один класс, Конструктор — захват ресурса, деструктор — освобождение. Но в целом — хорошее пособие для начинающего в многопоточности… Мне статья понравилась, жаль примеров нет или тестов, Это совет автору на будущее.

что касается замечания по использованию сторонних библиотек — не всегда рационально тащить из-за одной-двух компонент громадную стороннюю библиотеку. Однако, возможности таких библиотек как STL & Boost надо использовать максимально.
А я правильно понял, что рекурсивные мьютексы отличаются от рекурсивных тем что:
— Рекурсивный может захватываться одним и темже потоком много раз, и никого не пустит, пока не будет отдан потоком столько же раз. (типа захват ++а, релиз --а, пускает когда а==0)
— А нерекурсивный можно захватывать тоже сколько угодно раз, но позволит всем ходить он как только его отпустят ( (типа захват ++а, релиз а=0, пускает когда а==0)
?
Про рекурсивный вы поняли верно, а с нерекурсивным дело обстоит иначе: при повторной попытке захватить нерекурсивный мютекс в одном потоке возникнет deadlock.
Спасибо. Собственно это и был вопрос, с виндовыми я собаку съел (ведь если их не отпустить n раз то тоже дедлок). Собака на 2х концах :)
На память себе, и для нагугливших эту статью раньше остальных: Критическая секция (critical section) под виндой делает то же самое, что и mutex, но лишь в пределах одного процесса и быстрее. А mutex это получается глобальный объект системы для межпроцессного взаимодействия. см. также Mutex или CRITICAL_SECTION? В каких случаях что использовать?
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации