// Copyright (c) FIRST and other WPILib contributors. // Open Source Software; you can modify and/or share it under the terms of // the WPILib BSD license file in the root directory of this project. #include "EntryNotifier.h" #include "Log.h" using namespace nt; EntryNotifier::EntryNotifier(int inst, wpi::Logger& logger) : m_inst(inst), m_logger(logger) { m_local_notifiers = false; } void EntryNotifier::Start() { DoStart(m_inst); } bool EntryNotifier::local_notifiers() const { return m_local_notifiers; } bool impl::EntryNotifierThread::Matches(const EntryListenerData& listener, const EntryNotification& data) { if (!data.value) { return false; } // Flags must be within requested flag set for this listener. // Because assign messages can result in both a value and flags update, // we handle that case specially. unsigned int listen_flags = listener.flags & ~(NT_NOTIFY_IMMEDIATE | NT_NOTIFY_LOCAL); unsigned int flags = data.flags & ~(NT_NOTIFY_IMMEDIATE | NT_NOTIFY_LOCAL); unsigned int assign_both = NT_NOTIFY_UPDATE | NT_NOTIFY_FLAGS; if ((flags & assign_both) == assign_both) { if ((listen_flags & assign_both) == 0) { return false; } listen_flags &= ~assign_both; flags &= ~assign_both; } if ((flags & ~listen_flags) != 0) { return false; } // must match local id or prefix if (listener.entry != 0 && data.entry != listener.entry) { return false; } if (listener.entry == 0 && !wpi::StringRef(data.name).startswith(listener.prefix)) { return false; } return true; } unsigned int EntryNotifier::Add( std::function callback, StringRef prefix, unsigned int flags) { if ((flags & NT_NOTIFY_LOCAL) != 0) { m_local_notifiers = true; } return DoAdd(callback, prefix, flags); } unsigned int EntryNotifier::Add( std::function callback, unsigned int local_id, unsigned int flags) { if ((flags & NT_NOTIFY_LOCAL) != 0) { m_local_notifiers = true; } return DoAdd(callback, Handle(m_inst, local_id, Handle::kEntry), flags); } unsigned int EntryNotifier::AddPolled(unsigned int poller_uid, wpi::StringRef prefix, unsigned int flags) { if ((flags & NT_NOTIFY_LOCAL) != 0) { m_local_notifiers = true; } return DoAdd(poller_uid, prefix, flags); } unsigned int EntryNotifier::AddPolled(unsigned int poller_uid, unsigned int local_id, unsigned int flags) { if ((flags & NT_NOTIFY_LOCAL) != 0) { m_local_notifiers = true; } return DoAdd(poller_uid, Handle(m_inst, local_id, Handle::kEntry), flags); } void EntryNotifier::NotifyEntry(unsigned int local_id, StringRef name, std::shared_ptr value, unsigned int flags, unsigned int only_listener) { // optimization: don't generate needless local queue entries if we have // no local listeners (as this is a common case on the server side) if ((flags & NT_NOTIFY_LOCAL) != 0 && !m_local_notifiers) { return; } DEBUG0("notifying '" << name << "' (local=" << local_id << "), flags=" << flags); Send(only_listener, 0, Handle(m_inst, local_id, Handle::kEntry).handle(), name, value, flags); }