Создание объекта C ++ (MFC CRecordset) потокобезопасным - PullRequest
1 голос
/ 06 октября 2009

Мы пытаемся создать класс, обеспечивающий безопасность потоков MFC CRecordset (или, на самом деле, CODBCRecordset ). На самом деле, кажется, что все отлично работает для различных функций, таких как открытие и перемещение по набору записей (мы заключаем эти вызовы с критическими секциями), однако остается одна проблема - проблема, которая, кажется, создает тупики на практике.

Проблема, похоже, заключается в нашем конструкторе, например:

CThreadSafeRecordset::CThreadSafeRecordset(void) : CODBCRecordset(g_db)
{ // <-- Deadlock!
}

Другим потоком может быть тот, который оказался в CThreadSafeRecordset :: Close (), несмотря на то, что мы охраняем вложенный вызов Close, но это не имеет большого значения, так как конструктор не выполняет потоки Я предполагаю, что оригинальный класс CRecordset является виновником, делающим плохие вещи во время строительства. Я искал методы программирования, чтобы обойти эту проблему, но я не уверен, что может быть лучшим решением? Поскольку у нас нет кода и мы не можем контролировать другой код в нашем конструкторе, мы не можем добавить что-то особенное в критическую секцию ...?

Обновление: Спасибо за ввод; Я отметил, что я закончил как ответ на мой вопрос. Это в сочетании с возвратом shared_ptr в качестве возвращенного экземпляра для простоты обновления существующего кода, не поддерживающего потоки.

Ответы [ 2 ]

2 голосов
/ 06 октября 2009

Вы можете сделать конструктор CThreadSafeRecordset приватным, а затем предоставить публичный метод фабрики, который участвует в вашей блокировке и возвращает экземпляр.

1 голос
/ 06 октября 2009

Если нет способа заставить CODBCRecordset переместить свои небезопасные операции из конструктора (скажем, конструктор по умолчанию, за которым следует вызов Initialize ()), вы всегда можете использовать композицию вместо наследования. Пусть CThreadSafeRecordset будет оберткой вокруг CODBCRecordset вместо его подкласса. Таким образом, вы можете явно создать свой набор записей в любое время и защитить его с любой строгостью.

Недостатком, конечно, является то, что вам придется обернуть каждый метод CODBCRecordset, который вы хотите показать, даже те, которые не имеют отношения к вашим гарантиям потоков. Макрос C в файле cpp (чтобы он не мог сбежать и поразить ваших клиентов) может помочь.

...