Я бы, вероятно, использовал robots.txt
поверх тега meta
. Robots.txt существует дольше и может быть более широко поддержан (но я не уверен на 100% в этом).
Что касается второй части, я думаю, что большинство пауков примут любой наиболее ограничивающий параметр для страницы - если есть несоответствие между robots.txt и метатегом.
Очень интересный выпуск.
Попробуйте следующее:
Измените цикл notifyAll на:
for (все зарегистрированные наблюдатели) { если (наблюдатель) наблюдатель-> уведомление (); }
Добавьте еще один цикл в конец notifyAll, чтобы удалить все пустые записи из вашего списка наблюдателей
Определите и используйте мощный итератор над контейнером уведомителей, который устойчив к удалению (например, обнуление, как упоминалось ранее) и может обрабатывать добавление (например, добавление)
с другой стороны, если вы хотите принудительно сохранить константу контейнера во время уведомления, объявите notifyAll и контейнер, для которого выполняется итерация, как const.
Как насчет наличия итератора-члена с именем current
(инициализированного как итератор end
). Тогда
void remObserver(Observer* obs)
{
list<Observer*>::iterator i = observers.find(obs);
if (i == current) { ++current; }
observers.erase(i);
}
void notifyAll()
{
current = observers.begin();
while (current != observers.end())
{
// it's important that current is incremented before notify is called
Observer* obs = *current++;
obs->notify();
}
}
Если ваша программа многопоточная, вам может потребоваться здесь некоторая блокировка.
В любом случае, из вашего описания кажется, что проблема не в параллелизме (многопоточность), а скорее в мутациях, вызванных вызовом Observer :: notify (). В этом случае вы можете решить проблему, используя вектор и обходя его через индекс, а не итератор.
for(int i = 0; i < observers.size(); ++i)
observers[i]->notify();
Есть несколько решений этой проблемы:
boost :: signal
позволяет автоматически удалять соединение при уничтожении объекта. Но вы должны быть очень осторожны с безопасностью потоков. boost :: weak_ptr
или tr1 :: weak_ptr
для управления наблюдателями и boost ::
поможет вам сделать объекты недействительными, weak_ptr сообщит вам, существует ли объект.
Если вы выполняете какой-либо цикл событий, убедитесь, что каждый наблюдатель не уничтожить себя, добавить себя или любого другого в тот же вызов. Просто отложите задание, то есть
SomeObserver :: notify ()
{
main_loop.post (boost :: bind (& SomeObserver :: someMember, это));
}
Вот вариант уже представленной идеи TED.
Пока remObserver может обнулять запись, а не сразу удалять ее, вы можете реализовать notifyAll как:
void Subject::notifyAll()
{
list<Observer*>::iterator i = m_Observers.begin();
while(i != m_Observers.end())
{
Observer* observer = *i;
if(observer)
{
observer->notify();
++i;
}
else
{
i = m_Observers.erase(i);
}
}
}
Это позволяет избежать потребность во втором цикле очистки. Однако это означает, что если какой-то конкретный вызов notify () вызывает удаление самого себя или наблюдателя, расположенного ранее в списке, то фактическое удаление элемента списка будет отложено до следующего notifyAll (). Но до тех пор, пока любые функции, которые работают со списком, должным образом проверяют наличие нулевых записей, когда это необходимо, это не должно быть проблемой.
Проблема в праве собственности. Вы можете использовать интеллектуальные указатели, например классы boost :: shared_ptr
и boost :: weak_ptr
, чтобы продлить время жизни ваших наблюдателей за пределы точки «освобождения».
Мужчина идет к врачу и говорит: «Док, когда я поднимаю руку как это очень больно! " Врач говорит: «Не делай этого»
. Самое простое решение - работать со своей командой и сказать им, чтобы они этого не делали. Если наблюдателям «действительно нужно» убить себя или всех наблюдателей, запланируйте действие, когда уведомление закончится. Или, еще лучше, измените функцию remObserver, чтобы знать, происходит ли процесс уведомления, и просто поставьте удаление в очередь, когда все будет сделано.
Как насчет использования связанного списка в вашем цикле for
?
Лично я использую boost :: signal для реализации моих наблюдателей; Мне нужно будет проверить, но я считаю, что он справляется с описанными выше сценариями ( отредактировано : нашел, см. «Когда могут происходить отключения» ). Это упрощает вашу реализацию и не полагается на создание специального класса:
class Subject {
public:
boost::signals::connection addObserver( const boost::function<void ()>& func )
{ return sig.connect(func); }
private:
boost::signal<void ()> sig;
void notifyAll() { sig(); }
};
void some_func() { /* impl */ }
int main() {
Subject foo;
boost::signals::connection c = foo.addObserver(boost::bind(&some_func));
c.disconnect(); // remove yourself.
}