Создание нескольких экземпляров глобальной статики в C++?

StackOverflow https://stackoverflow.com/questions/928568

  •  06-09-2019
  •  | 
  •  

Вопрос

Одна из библиотек, которые мы используем для нашего продукта, использует для доступа к нему синглтон.Я почти уверен, что он реализован как статический экземпляр (это не открытый исходный код).Это хорошо работает для приложения с одним документом, но в наше приложение может быть загружено более одного документа.Я предполагаю, что доступ к экземпляру написан примерно так:

Instance* getInstance() {
    static Instance* inst = new Instance();
    return inst;
}

В подобных ситуациях есть ли какой -нибудь способ надежно создать более одного экземпляра?Единственное, о чем я могу думать, — это иметь нечто большее, чем просто процесс, и использовать какой-то тип IPC, чтобы связать все это воедино.Я не могу придумать ничего менее хакерского.

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

Кори

Редактировать:

  • машина является машиной Windows
  • глобальная статика — это, по сути, большая фабрика.Мне нужен токен сеанса какого-то типа, чтобы я мог легко сказать «освободите все ресурсы из этого сеанса» (не существует способа повторно инициализировать глобальную статику, о которой я знаю)

Вместо того, чтобы пытаться делать какие-то хитрые махинации, чтобы получить то, что я хочу, я собираюсь обернуть все это в свой собственный класс и добавить сеансовый ключ к каждому методу получения.Внутренне я буду отслеживать, что было выделено, добавляя свой собственный метод выпуска для возврата ресурсов.Это неоптимально по многим причинам, но я не могу придумать лучшей идеи.

Спасибо всем за отличные отзывы.

Это было полезно?

Решение

Единственное, о чем я могу думать, это создать подкласс, если вам посчастливилось определить одноэлементный класс следующим образом:

class Document {
public:
    static Document* getInstance() {
        static Document inst;
        return &inst;
    }
    virtual ~Document();
protected:
    Document();
private:
    struct Impl;
    Impl *pImpl;
};

Если вы можете создать его подкласс и у подкласса будет доступ к конструктору, вы можете создать экземплярный подкласс, например:

class MyDocument: public Document {
public:
    MyDocument(): Document() {
    }
};

Это может быть не совсем безопасно, поскольку разработчик мог сделать некоторые неприятные предположения.Но это идея или некий подход, который может иметь некоторый шанс сработать.Если повезет, продавец согласится на этот вариант, если вы об этом упомянете...удачи.

Другие советы

Даже если бы вам удалось решить эту конкретную проблему, пока все происходило в процессе, я бы забеспокоился, что эта проблема с синглтоном — это лишь верхушка айсберга.Библиотека явно не была предназначена для вашего сценария.

Изолирование каждой загрузки DLL в отдельный процесс кажется мне правильным и несложным, хотя, конечно, это может быть дорого для вас.

К сожалению, я не вижу изъяна в ваших рассуждениях.Поставщик принял решение, и вы обязаны его соблюдать.Он решил использовать один экземпляр для каждого процесса, поэтому, если вам нужно несколько экземпляров, вам нужно иметь несколько процессов со всеми вытекающими отсюда последствиями.

Конечно, если вы предполагаете, что его решение об ограничении является произвольным и что для этого нет веской причины, вы можете попытаться обойти его.Чтобы начать этот путь, нужно выполнить некоторые этапы разборки/сборки в отладчике.Если вы можете подтвердить, что его фабрика экземпляров работает точно так, как вы пришли к выводу выше, вы, несомненно, сможете создать альтернативу, позволяющую создавать несколько экземпляров.

Но, конечно, огромный риск при таком подходе заключается в том, что каждая строка кода в кодовой базе поставщика, которая зависит от его решения иметь единственный экземпляр, становится бомбой замедленного действия, готовой взорваться вам в лицо.Этот код для вас невидим.Готовы ли вы поспорить, что таких линий ноль?Я знаю, что сказал бы Клинт Иствуд в такой ситуации;"Я чувствую себя счастливчиком, панк, ладно?" :-)

Не существует элегантных способов иметь несколько экземпляров одного объекта в одном программном пространстве, но это сделано специально.В общем, вы используете синглтон только в том случае, когда нежелательно иметь несколько экземпляров.Если поставщик реализовал свой продукт с использованием синглтона, для такого выбора могут быть веские причины.

Возможно, если вы опишете свою проблему более подробно, возможны и другие подходы.Трудно сказать на основании предоставленной информации.Что делает объект-одиночка?Зачем вам нужно несколько экземпляров?

За исключением предложенного вами межпроцессного взаимодействия, лучший хак, который я могу придумать, — это скопировать dll в новый файл, вручную загрузить новую dll и импортировать все функции, которые вы используете для каждого создаваемого вами экземпляра.

Надеемся, это означает, что статические переменные не будут конфликтовать между разными экземплярами, поскольку технически они не находятся в одной и той же dll.Однако в этом решении есть много плохих моментов, например, весь код в dll клонируется для каждой версии, и вы не сможете использовать библиотеку импорта, а вам придется загружать dll и импортировать все функции вручную.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top