2014-09-05 5 views
5

У меня есть эта статическая библиотека C, в которой мне нужно запускать многопоточность (потоки не взаимодействуют друг с другом, мне просто нужно несколько из них в одно и то же время, чтобы ускорить работу). Более того, я обернул библиотеку c в библиотеку cli C++, которая затем используется основным приложением C#.Есть ли более простой способ создания статической библиотеки?

Поскольку статическая библиотека плохо реагирует на несколько потоков, проходящих через нее (что не входит в мой контроль, у меня нет источника для его зависимостей), я прибегал к копированию (с небольшими вариациями) целую вещь несколько раз и помещает другую оболочку между библиотекой cli C++ (и ее копиями) и приложением C#, которое эмулирует копии как до 8 экземпляров объекта. Он работает, но его довольно грубо и громоздко, чтобы внести какие-либо изменения в функциональность библиотеки.

Кто-нибудь знает более простой способ добиться такого же эффекта? Лучше всего угадать, что у меня есть какая-то статическая часть памяти, где возникает конфликт между несколькими потоками, работающими в одной и той же библиотеке, есть ли способ заставить все статические переменные быть конкретными потоками? (без возможности перехода к ним добавить поток declspec).

+2

'Я прибегал к копированию (с небольшими вариациями) всего несколько раз. Как именно это помогает? Если вы изменяете имена глобальных/статических переменных, чтобы не возникало конфликтов, вы также можете обозначить их как протектора. Если вы не меняете имена, каковы эти незначительные вариации? –

+0

имена библиотек, поэтому они загружаются как «разные» вещи –

+5

Статические библиотеки не загружаются, они связаны. Имена библиотек не влияют на процесс связывания статических библиотек. DLL в Windows может вести себя, как вы описываете, но не статические библиотеки. –

ответ

0

Проблема заключается в том, что библиотека не является повторной. Если у вас есть доступ к исходному коду библиотеки, лучше всего сделать поиск по всем глобальным переменным и сделать их потоковыми локальными. Это можно сделать, используя ключевое слово thread_local на C++ 11 или используя ключевое слово __thread, если компилировать с помощью gcc/g ++.

Это гарантирует, что для каждого потока будет использоваться другая копия каждой глобальной переменной.

1

Поскольку вы используете C библиотеку из C# с помощью C++/CLI слоя, это звучит как ваша ссылка отношение выглядеть следующим образом:

(C# приложение) - динамический -> (C++/CLI DLL) - -static -> (библиотека C)

фон:

Потому что вы заявили, что у вас нет никакого способа изменить или иначе фиксируя вашу библиотеку C, вы на самом деле нет никакого способа решения проблемы безопасности потоков без дублирования библиотеки C в памяти так или иначе, что позволит эффективно дублировать глобальные данные, которые/безусловно, вызывают конфликты потоков.

Независимо от того, как вы на это смотрите, ваш единственный способ решить это путем дублирования DLL (ваш текущий подход) потребует от вас знать, сколько дубликатов вам нужно заблаговременно, и каждая из этих DLL будет немного отличаться экспортированные имена символов (например, каждому классу или пространству имен для каждого класса класса, управляемого C++/CLI, потребуется другое имя класса). Как вы заявили, это действительно грубо (и я добавлю трудно управлять и невозможно масштабировать).

Решение:

Я думаю, что ваш лучше и чище вариант с помощью дублирования EXE. Для этого вы вставляете новый EXE перед своей DLL C++/CLI и динамически связываете его с помощью механизма IPC по вашему выбору (IPC Mechanisms in C# - Usage and Best Practices). Позволяет называть этот EXE вашим сервисом EXE. Если вы создаете экземпляр службы EXE для каждого потока в основном приложении C#, то каждая служба EXE будет загружать свою собственную копию библиотеки C++/CLI DLL и, следовательно, собственную версию библиотеки C. Это означает, что каждый поток работает с копией библиотеки C через службу EXE.

Вот что ваша ссылка отношение будет выглядеть следующим образом:

(C# application)--IPC-->(C# service EXE)--dynamic-->(C++/CLI DLL)--static-->(C library) 

В натуральном выражении файла, он будет выглядеть следующим образом:

MainApp.exe--IPC-->ServiceApp.exe--dynamic-->CppCliWrapper.dll 

Для оптимизации этого решения, вы должны стараться избегать тяжелыми создание/удаление потоков, поскольку это связано с созданием/удалением службы EXE. Например, вы можете предварительно выделить потоки X при запуске и использовать эти потоки в течение всего жизненного цикла приложения. Вы также можете подумать о том, чтобы выполнить операции над оптимизацией расходов на IPC. Все это зависит от потребностей и деталей вашего приложения.

Чтобы это сделать еще больше, вы можете потенциально масштабировать это решение на всех компьютерах, если вы выберете механизм IPC, который работает через TCP/IP. Затем вы можете обрабатывать свои операции на столько машин, сколько хотите. Именно так многие компании превращают библиотеки DLL в горизонтально масштабируемые сервисы. Это не так просто, как кажется, но еда для вас, если вам нужно масштабировать эту штуку.

Смежные вопросы