// 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 "InstanceImpl.h" using namespace nt; std::atomic InstanceImpl::s_default{-1}; std::atomic InstanceImpl::s_fast_instances[10]; wpi::UidVector InstanceImpl::s_instances; wpi::mutex InstanceImpl::s_mutex; using namespace std::placeholders; InstanceImpl::InstanceImpl(int inst) : logger_impl(inst), logger(std::bind(&LoggerImpl::Log, &logger_impl, _1, _2, _3, _4)), connection_notifier(inst), entry_notifier(inst, logger), rpc_server(inst, logger), storage(entry_notifier, rpc_server, logger), dispatcher(storage, connection_notifier, logger), ds_client(dispatcher, logger) { logger.set_min_level(logger_impl.GetMinLevel()); } InstanceImpl::~InstanceImpl() { logger.SetLogger(nullptr); } InstanceImpl* InstanceImpl::GetDefault() { return Get(GetDefaultIndex()); } InstanceImpl* InstanceImpl::Get(int inst) { if (inst < 0) { return nullptr; } // fast path, just an atomic read if (static_cast(inst) < (sizeof(s_fast_instances) / sizeof(s_fast_instances[0]))) { InstanceImpl* ptr = s_fast_instances[inst]; if (ptr) { return ptr; } } // slow path std::scoped_lock lock(s_mutex); // static fast-path block if (static_cast(inst) < (sizeof(s_fast_instances) / sizeof(s_fast_instances[0]))) { // double-check return s_fast_instances[inst]; } // vector if (static_cast(inst) < s_instances.size()) { return s_instances[inst]; } // doesn't exist return nullptr; } int InstanceImpl::GetDefaultIndex() { int inst = s_default; if (inst >= 0) { return inst; } // slow path std::scoped_lock lock(s_mutex); // double-check inst = s_default; if (inst >= 0) { return inst; } // alloc and save inst = AllocImpl(); s_default = inst; return inst; } int InstanceImpl::Alloc() { std::scoped_lock lock(s_mutex); return AllocImpl(); } int InstanceImpl::AllocImpl() { unsigned int inst = s_instances.emplace_back(nullptr); InstanceImpl* ptr = new InstanceImpl(inst); s_instances[inst] = ptr; if (inst < (sizeof(s_fast_instances) / sizeof(s_fast_instances[0]))) { s_fast_instances[inst] = ptr; } return static_cast(inst); } void InstanceImpl::Destroy(int inst) { std::scoped_lock lock(s_mutex); if (inst < 0 || static_cast(inst) >= s_instances.size()) { return; } if (static_cast(inst) < (sizeof(s_fast_instances) / sizeof(s_fast_instances[0]))) { s_fast_instances[inst] = nullptr; } delete s_instances[inst]; s_instances.erase(inst); }