Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
Форум программистов > C/C++: Общие вопросы > Singleton в нескольких потоках |
Автор: azesmcar 24.3.2009, 13:42 | ||
Добрый день, Есть класс SomeThread который делает конкретную задачу..обьектов этого класса - несколько. Каждый обьект имеет свое сойденение с базой данных и в принципе абсолютно изолирован (т.е. никаких глобальных данных и тому подобного, каждый обьект оперирует со своими локальными данными). Но как понимаете весь функционал не написан в модуле SomeThread, а он использует некие вспомогательные классы SystemUser, UserActionHandler и тому подобное. Вопрос в том что в каждом модуле мне нужно подключение к базе данных которое создано в классе SomeThread, а передавать его в каждый модуль, как-то некрасиво. Можно конечно создать синглтон, но..это потоки, т.е. на каждый поток должно быть свое подключение. Как это можно сделать? Было бы красиво что-то вроде
но вот как это реализовать? |
Автор: Lazin 24.3.2009, 14:07 |
например, с помощью boost::call_once |
Автор: azesmcar 24.3.2009, 14:16 | ||
а без буста? меня больше принцип реализации интересует |
Автор: jonie 24.3.2009, 22:36 |
если я правильно понял задачу, то на каждый поток у вас свое подключение. почему нельзя сделать в том классе что вы привели static map<threadId, connectionPtr> connections и при каждом обращении из конкретного потока (его id мы всегда сможем узнать) в каждой функции либо брать кешированное соединение либо создавать, пихать в кеш и использовать ? замечания: 1) map это НЕ std::map ! т.к. последний не потокобезопасен (хотя можно доступ к нему сделать таковым) 2) кешировать соединение не очень хорошо (точнее очень нехорошо). могут быть проблемы. все зависит от задачи. 3) конечно нужна функции "отключится от объекта" |
Автор: Cтpaнник 24.3.2009, 23:13 |
Если дело происходит в Windows и кроссплатформенность кода не нужна, то имеет смысл посмотреть в сторону платформенно-специфичных средств (а именно, в Win это TLS). Например, в MSVC++ есть конструкция __declspec(thread) <тип данных> <имя переменной>; - таким образом создается экземпляр переменной, специфичный для вызывающего потока. Это позволит разделить connectionPtr и за каждым потоком закрепить свой экземпляр оного. Если применить еще и идиому RTTI, то, возможно, удастся решить и проблемы с "зависшими" или незакрытыми соединениями.... |
Автор: azesmcar 25.3.2009, 06:04 | ||||||||
Абсолютно верно.
так и думал сделать, но
если учесть что в этот мап значения добавляются всего один раз в начале одним потоком, а потом ТОЛЬКО читают из него методом find, могут ли быть проблемы..со вчерашнего дня об этом и думаю.
нет, мне скорее нужно под линукс..но код кроссплатформенный. |
Автор: jonie 25.3.2009, 07:54 | ||
|
Автор: azesmcar 27.3.2009, 08:43 | ||
ну это понятно, но тут есть что-то что мне не нравится, фактически потоки, у которых свое сойденение к базе должны ждать, хоть и недолго, но все же ждать пока поиск закончится..не нравится мне это. Может стоит сменить архитектуру пока не поздно? Но другого ничего не приходит на ум. Не писать же все в одном модуле? Никто не сталкивался с подобным что ли? Синглтон очень нужная в нашей жизни штука, а многопоточное приложение в наше время не редкость.. |
Автор: azesmcar 27.3.2009, 09:50 | ||||
Все!!! управился, привожу решение кому интересно. В виндоуз есть такая штука как TLS (Thread Local Storage). Вещь полезная и полностью решающая данную задачу. В никсах она добавлена как патч, но это было давно и в принципе на данный момент вы вряд ли найдете систему которая не поддерживает TLS.
вот и все..обявляем статические переменные как
и наслаждаемся Thread Scope Static переменными! Всем спасибо. |
Автор: Lazin 27.3.2009, 11:12 | ||
нельзя использовать в dll, если ты будет загружать dll динамически, то будут проблемы Добавлено через 7 минут и 7 секунд workaround
|
Автор: azesmcar 27.3.2009, 13:36 | ||
я и не собираюсь, но спасибо за информацию, почитаю про это. |
Автор: 0xDX 28.3.2009, 03:42 |
Делай селектор, А в селекторе возвращаемые объекты вычисляй по ID потока Что то вроде switch(IdThread) { case First: retunrn array_object[1]; case Second: retunrn array_object[1]; default: return 0; } Весь код я не писал, если надо то скажи. |
Автор: azesmcar 28.3.2009, 09:13 |
0xDX ![]() 1. Количество потоков - динамическое, еслиб я точно знал их количество - я бы придумал решения и покрасивей..хотя бы с шаблонами. 2. Откуда ты возьмешь First и Second? Это не константные значения. ИД потока изменяется при каждом запуске программы. 3. Чем тебе не нравится мое решение? Думаешь свитч красивее? |
Автор: 0xDX 30.3.2009, 00:54 | ||
azesmcar на винд работать не будет.
Ассоциативный контейнер полечит. |
Автор: jonie 30.3.2009, 08:45 |
я собственно предлагал использовать map-у и настоящий синглетон (только сделать его потокобезопасным)... этот вариант хотябы кросплатформенный, чего не скажешь о каком-то TLS-е... еще непонятно как этот TLS покажет себя в отладке... |
Автор: azesmcar 30.3.2009, 08:52 | ||||
уже работает
а чем этот ненастоящий? это статик изолированный в потоке, об этом заботится сама система а не мы..товарищи, давайте говорить обоснованно, я не утверждаю что TLS - это шедевр созданный великими умами, я о нем недавно прочитал..и прочитал в статье по решению именно моей проблемы..если у кого-то есть данные что ТЛС не есть хорошо поделитесь, я не спорю..просто писать до хрена кода только потому что непонятно как ТЛС покажет себя в отладке - по моему не стоит..можно проверить..вроде до сих пор проблем не было, технология не новая..в чем проблема то? |
Автор: Lazin 30.3.2009, 09:08 |
в использовании локальной памяти потока нет ничего плохого, в pthread, AFAIK, это то-же возможно... |
Автор: azesmcar 30.3.2009, 09:14 | ||||
я тоже немало об этом прочитал, ничего плохого не увидел..
решение которе я написал - кроссплатформенное. там ifdef стоит. Проверял, работает на ура. |