Adds SetDefault methods to NetworkTables (#54)

There was no way to atomically check for a key in the table,
and then setting if it if non existant. Back before persistent
this was not a problem, however now it is, as its possible for
values to be added before team's robot programs start. This makes
the old method of calling Put*** methods in RobotInit invalid.
This adds SetDefault methods, which do this atomically.
This commit is contained in:
Thad House
2016-07-13 00:31:03 -07:00
committed by Peter Johnson
parent 6615a34e99
commit 58092c5190
15 changed files with 785 additions and 1 deletions

View File

@@ -464,6 +464,48 @@ std::shared_ptr<Value> Storage::GetEntryValue(StringRef name) const {
return i == m_entries.end() ? nullptr : i->getValue()->value;
}
bool Storage::SetDefaultEntryValue(StringRef name,
std::shared_ptr<Value> value) {
if (!value) return false; // can't compare to a null value
if (name.empty()) return false; // can't compare empty name
std::unique_lock<std::mutex> lock(m_mutex);
auto& new_entry = m_entries[name];
if (new_entry) { // entry already exists
auto old_value = new_entry->value;
// if types match return true
if (old_value && old_value->type() == value->type()) return true;
else return false; // entry exists but doesn't match type
}
// if we've gotten here, entry does not exist, and we can write it.
new_entry.reset(new Entry(name));
Entry* entry = new_entry.get();
// don't need to compare old value as we know it will assign
entry->value = value;
// if we're the server, assign an id if it doesn't have one
if (m_server && entry->id == 0xffff) {
unsigned int id = m_idmap.size();
entry->id = id;
m_idmap.push_back(entry);
}
// notify (for local listeners)
if (m_notifier.local_notifiers()) {
// always a new entry if we got this far
m_notifier.NotifyEntry(name, value, NT_NOTIFY_NEW | NT_NOTIFY_LOCAL);
}
// generate message
if (!m_queue_outgoing) return true;
auto queue_outgoing = m_queue_outgoing;
auto msg = Message::EntryAssign(name, entry->id, entry->seq_num.value(),
value, entry->flags);
lock.unlock();
queue_outgoing(msg, nullptr, nullptr);
return true;
}
bool Storage::SetEntryValue(StringRef name, std::shared_ptr<Value> value) {
if (name.empty()) return true;
if (!value) return true;

View File

@@ -67,6 +67,7 @@ class Storage {
// User functions. These are the actual implementations of the corresponding
// user API functions in ntcore_cpp.
std::shared_ptr<Value> GetEntryValue(StringRef name) const;
bool SetDefaultEntryValue(StringRef name, std::shared_ptr<Value> value);
bool SetEntryValue(StringRef name, std::shared_ptr<Value> value);
void SetEntryTypeValue(StringRef name, std::shared_ptr<Value> value);
void SetEntryFlags(StringRef name, unsigned int flags);

View File

@@ -305,6 +305,13 @@ bool NetworkTable::PutNumber(StringRef key, double value) {
return nt::SetEntryValue(path, nt::Value::MakeDouble(value));
}
bool NetworkTable::SetDefaultNumber(StringRef key, double defaultValue) {
llvm::SmallString<128> path(m_path);
path += PATH_SEPARATOR_CHAR;
path += key;
return nt::SetDefaultEntryValue(path, nt::Value::MakeDouble(defaultValue));
}
double NetworkTable::GetNumber(StringRef key) const {
llvm::SmallString<128> path(m_path);
path += PATH_SEPARATOR_CHAR;
@@ -332,6 +339,13 @@ bool NetworkTable::PutString(StringRef key, StringRef value) {
return nt::SetEntryValue(path, nt::Value::MakeString(value));
}
bool NetworkTable::SetDefaultString(StringRef key, StringRef defaultValue) {
llvm::SmallString<128> path(m_path);
path += PATH_SEPARATOR_CHAR;
path += key;
return nt::SetDefaultEntryValue(path, nt::Value::MakeString(defaultValue));
}
std::string NetworkTable::GetString(StringRef key) const {
llvm::SmallString<128> path(m_path);
path += PATH_SEPARATOR_CHAR;
@@ -360,6 +374,13 @@ bool NetworkTable::PutBoolean(StringRef key, bool value) {
return nt::SetEntryValue(path, nt::Value::MakeBoolean(value));
}
bool NetworkTable::SetDefaultBoolean(StringRef key, bool defaultValue) {
llvm::SmallString<128> path(m_path);
path += PATH_SEPARATOR_CHAR;
path += key;
return nt::SetDefaultEntryValue(path, nt::Value::MakeBoolean(defaultValue));
}
bool NetworkTable::GetBoolean(StringRef key) const {
llvm::SmallString<128> path(m_path);
path += PATH_SEPARATOR_CHAR;
@@ -388,6 +409,14 @@ bool NetworkTable::PutBooleanArray(llvm::StringRef key,
return nt::SetEntryValue(path, nt::Value::MakeBooleanArray(value));
}
bool NetworkTable::SetDefaultBooleanArray(StringRef key,
llvm::ArrayRef<int> defaultValue) {
llvm::SmallString<128> path(m_path);
path += PATH_SEPARATOR_CHAR;
path += key;
return nt::SetDefaultEntryValue(path, nt::Value::MakeBooleanArray(defaultValue));
}
std::vector<int> NetworkTable::GetBooleanArray(
llvm::StringRef key, llvm::ArrayRef<int> defaultValue) const {
llvm::SmallString<128> path(m_path);
@@ -407,6 +436,14 @@ bool NetworkTable::PutNumberArray(llvm::StringRef key,
return nt::SetEntryValue(path, nt::Value::MakeDoubleArray(value));
}
bool NetworkTable::SetDefaultNumberArray(StringRef key,
llvm::ArrayRef<double> defaultValue) {
llvm::SmallString<128> path(m_path);
path += PATH_SEPARATOR_CHAR;
path += key;
return nt::SetDefaultEntryValue(path, nt::Value::MakeDoubleArray(defaultValue));
}
std::vector<double> NetworkTable::GetNumberArray(
llvm::StringRef key, llvm::ArrayRef<double> defaultValue) const {
llvm::SmallString<128> path(m_path);
@@ -426,6 +463,14 @@ bool NetworkTable::PutStringArray(llvm::StringRef key,
return nt::SetEntryValue(path, nt::Value::MakeStringArray(value));
}
bool NetworkTable::SetDefaultStringArray(StringRef key,
llvm::ArrayRef<std::string> defaultValue) {
llvm::SmallString<128> path(m_path);
path += PATH_SEPARATOR_CHAR;
path += key;
return nt::SetDefaultEntryValue(path, nt::Value::MakeStringArray(defaultValue));
}
std::vector<std::string> NetworkTable::GetStringArray(
llvm::StringRef key, llvm::ArrayRef<std::string> defaultValue) const {
llvm::SmallString<128> path(m_path);
@@ -444,6 +489,14 @@ bool NetworkTable::PutRaw(llvm::StringRef key, llvm::StringRef value) {
return nt::SetEntryValue(path, nt::Value::MakeRaw(value));
}
bool NetworkTable::SetDefaultRaw(StringRef key,
StringRef defaultValue) {
llvm::SmallString<128> path(m_path);
path += PATH_SEPARATOR_CHAR;
path += key;
return nt::SetDefaultEntryValue(path, nt::Value::MakeRaw(defaultValue));
}
std::string NetworkTable::GetRaw(llvm::StringRef key,
llvm::StringRef defaultValue) const {
llvm::SmallString<128> path(m_path);
@@ -462,6 +515,14 @@ bool NetworkTable::PutValue(StringRef key, std::shared_ptr<nt::Value> value) {
return nt::SetEntryValue(path, value);
}
bool NetworkTable::SetDefaultValue(StringRef key,
std::shared_ptr<nt::Value> defaultValue) {
llvm::SmallString<128> path(m_path);
path += PATH_SEPARATOR_CHAR;
path += key;
return nt::SetDefaultEntryValue(path, defaultValue);
}
std::shared_ptr<nt::Value> NetworkTable::GetValue(StringRef key) const {
llvm::SmallString<128> path(m_path);
path += PATH_SEPARATOR_CHAR;

View File

@@ -124,6 +124,12 @@ void NT_GetEntryValue(const char *name, size_t name_len,
ConvertToC(*v, value);
}
int NT_SetDefaultEntryValue(const char* name, size_t name_len,
const struct NT_Value *set_value) {
return nt::SetDefaultEntryValue(StringRef(name, name_len),
ConvertFromC(*set_value));
}
int NT_SetEntryValue(const char *name, size_t name_len,
const struct NT_Value *value) {
return nt::SetEntryValue(StringRef(name, name_len), ConvertFromC(*value));
@@ -701,6 +707,57 @@ NT_String *NT_GetValueStringArray(const struct NT_Value *value,
return arr;
}
int NT_SetDefaultEntryBoolean(const char *name, size_t name_len,
int default_boolean) {
return nt::SetDefaultEntryValue(StringRef(name, name_len),
Value::MakeBoolean(default_boolean != 0));
}
int NT_SetDefaultEntryDouble(const char *name, size_t name_len,
double default_double) {
return nt::SetDefaultEntryValue(StringRef(name, name_len),
Value::MakeDouble(default_double));
}
int NT_SetDefaultEntryString(const char *name, size_t name_len,
const char *default_value, size_t default_len) {
return nt::SetDefaultEntryValue(StringRef(name, name_len),
Value::MakeString(StringRef(default_value,
default_len)));
}
int NT_SetDefaultEntryRaw(const char *name, size_t name_len,
const char *default_value, size_t default_len) {
return nt::SetDefaultEntryValue(StringRef(name, name_len),
Value::MakeString(StringRef(default_value,
default_len)));
}
int NT_SetDefaultEntryBooleanArray(const char *name, size_t name_len,
const int *default_value,
size_t default_size) {
return nt::SetDefaultEntryValue(StringRef(name, name_len),
Value::MakeBooleanArray(llvm::makeArrayRef(default_value, default_size)));
}
int NT_SetDefaultEntryDoubleArray(const char *name, size_t name_len, const double *default_value,
size_t default_size) {
return nt::SetDefaultEntryValue(StringRef(name, name_len),
Value::MakeDoubleArray(llvm::makeArrayRef(default_value, default_size)));
}
int NT_SetDefaultEntryStringArray(const char *name, size_t name_len,
const struct NT_String* default_value,
size_t default_size) {
std::vector<std::string> vec;
vec.reserve(default_size);
for (size_t i = 0; i < default_size; ++i)
vec.push_back(ConvertFromC(default_value[i]));
return nt::SetDefaultEntryValue(StringRef(name, name_len),
Value::MakeStringArray(std::move(vec)));
}
int NT_GetEntryBoolean(const char *name, size_t name_len,
unsigned long long *last_change, int *v_boolean) {
auto v = nt::GetEntryValue(StringRef(name, name_len));

View File

@@ -29,6 +29,10 @@ std::shared_ptr<Value> GetEntryValue(StringRef name) {
return Storage::GetInstance().GetEntryValue(name);
}
bool SetDefaultEntryValue(StringRef name, std::shared_ptr<Value> value) {
return Storage::GetInstance().SetDefaultEntryValue(name, value);
}
bool SetEntryValue(StringRef name, std::shared_ptr<Value> value) {
return Storage::GetInstance().SetEntryValue(name, value);
}