2015-02-20 1 views
3

У меня есть приложение с очень простой плагиновой системой, которая строится вокруг ядра, которое заботится о тяжелом подъеме, но оставляет любую обработку за пределами основ плагинов. Теперь я хотел бы сделать эту систему многопотоковой или, по крайней мере, позволить отдельным плагинам запускать собственные потоки, чтобы они могли блокировать индивидуально без замораживания ядра.Совместное однонаправленное состояние в многопотоковой архитектуре плагинов

Естественно, это означает, что обеспечить надежную защиту сердечника, чтобы плагины могли свободно работать с функциями, защищенными резьбой от указанного сердечника. Это не так сложно для многих случаев, но проблема возникает, когда результатом одной из этих функций-членов является (const) ссылка на некоторую внутреннюю среду, поддерживаемую ядром. Плагины не должны изменять его, но ядро, запущенное в другом потоке, может обновлять его в любой момент времени, пока плагин все еще держится за ссылку и, возможно, в середине обработки.

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

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

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

Какой был бы мой лучший выбор? Какие варианты, которые я не рассмотрел, могут помочь мне здесь?

+0

Может ли внутренний компонент быть общим указателем, а функция возвращает общий указатель? Если вы можете это сделать, вы можете закодировать свое ядро, если если количество ссылок на общий указатель больше 1, вы не можете его изменить. – NathanOliver

+0

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

ответ

0

Этот вопрос довольно основан на мнениях, но, основываясь на прошлом опыте, я бы рекомендовал использовать copy-on-write. Вы можете сделать это на верхнем уровне, скопировав весь объект, или вы можете делать это по частям, что может привести к накладным расходам на копирование. Например:

struct BigData; 
struct Shared 
{ 
    std::shared_ptr<const BigData> a; 
    std::shared_ptr<const BigData> b; 
    std::shared_ptr<const BigData> c; 
} 

Вы бы тогда только скопировать части, которые вы модифицируете и прислать копию Shared плагиной. Поэтому, если вы что-то измените в a, b и c все равно укажут на тот же объект, но a укажет на новый BigData, который был скопирован с оригинала, а затем изменен.