void GwObjectHost::serviceDisconnected(ServiceId id) { boost::upgrade_lock<boost::shared_mutex> lock(_mutex); boost::upgrade_to_unique_lock<boost::shared_mutex> unique_lock(lock); _servicesMetaObjects.erase(id); std::map<ServiceId, std::list<GwObjectId> >::iterator findIt = _objectsUsedOnServices.find(id); if (findIt == _objectsUsedOnServices.end()) return; std::list<GwObjectId>& objects = findIt->second; for (std::list<GwObjectId>::iterator it = objects.begin(), end = objects.end(); it != end; ++it) { std::pair<TransportSocketPtr, ObjectAddress>& addr = _objectsOrigin[*it]; Message terminateMessage; terminateMessage.setFunction(Message::BoundObjectFunction_Terminate); terminateMessage.setObject(addr.second.object); terminateMessage.setService(addr.second.service); terminateMessage.setType(Message::Type_Call); terminateMessage.setValue(AnyReference::from(addr.second.object), "I"); addr.first->send(terminateMessage); } objects.clear(); _objectsUsedOnServices.erase(id); }
MapBlock * Map::getBlockBuffered(v3s16 & p) { MapBlock *block; { auto lock = try_shared_lock(m_block_cache_mutex); if(m_block_cache && p == m_block_cache_p) return m_block_cache; } // If block doesn't exist, return NULL { auto lock = m_blocks.lock_shared_rec(); auto n = m_blocks.find(p); if(n == m_blocks.end()) { block = NULL; } // If block exists, return it else{ block = n->second; } } // Cache the last result auto lock = unique_lock(m_block_cache_mutex); m_block_cache_p = p; m_block_cache = block; return block; }
void GwObjectHost::clientDisconnected(TransportSocketPtr socket) { boost::upgrade_lock<boost::shared_mutex> lock(_mutex); // If the client had not registered any object, return. if (_hostObjectBank.find(socket) == _hostObjectBank.end()) return; std::map<ObjectAddress, GwObjectId>& bank = _hostObjectBank[socket]; if (bank.size() == 0) return; std::vector<GwObjectId> allIds; allIds.reserve(bank.size()); boost::upgrade_to_unique_lock<boost::shared_mutex> unique_lock(lock); for (std::map<ObjectAddress, GwObjectId>::iterator it = bank.begin(), end = bank.end(); it != end; ++it) { ServiceId service = it->first.service; GwObjectId object = it->second; std::list<GwObjectId>& used = _objectsUsedOnServices[service]; allIds.push_back(object); std::list<GwObjectId>::iterator uit = std::find(used.begin(), used.end(), object); if (uit != used.end()) used.erase(uit); if (used.size() == 0) _objectsUsedOnServices.erase(service); } for (std::vector<GwObjectId>::iterator it = allIds.begin(), end = allIds.end(); it != end; ++it) { _objectsMetaObjects.erase(*it); _objectsOrigin.erase(*it); } _hostObjectBank.erase(socket); }
Status Config::update(const std::map<std::string, std::string>& config) { // A config plugin may call update from an extension. This will update // the config instance within the extension process and the update must be // reflected in the core. if (Registry::external()) { for (const auto& source : config) { PluginRequest request = { {"action", "update"}, {"source", source.first}, {"data", source.second}, }; // A "update" registry item within core should call the core's update // method. The config plugin call action handling must also know to // update. Registry::call("config", "update", request); } } // Request a unique write lock when updating config. boost::unique_lock<boost::shared_mutex> unique_lock(getInstance().mutex_); ConfigData conf; for (const auto& source : config) { if (Registry::external()) { VLOG(1) << "Updating extension config source: " << source.first; } else { VLOG(1) << "Updating config source: " << source.first; } getInstance().raw_[source.first] = source.second; } // Now merge all sources together. for (const auto& source : getInstance().raw_) { mergeConfig(source.second, conf); } // Call each parser with the optionally-empty, requested, top level keys. for (const auto& plugin : Registry::all("config_parser")) { auto parser = std::static_pointer_cast<ConfigParserPlugin>(plugin.second); if (parser == nullptr || parser.get() == nullptr) { continue; } // For each key requested by the parser, add a property tree reference. std::map<std::string, ConfigTree> parser_config; for (const auto& key : parser->keys()) { if (conf.all_data.count(key) > 0) { parser_config[key] = conf.all_data.get_child(key); } else { parser_config[key] = pt::ptree(); } } parser->update(parser_config); } getInstance().data_ = conf; return Status(0, "OK"); }
void Map::deleteBlock(MapBlockP block) { auto block_p = block->getPos(); (*m_blocks_delete)[block] = 1; m_blocks.erase(block_p); #if CMAKE_THREADS && !CMAKE_HAVE_THREAD_LOCAL auto lock = unique_lock(m_block_cache_mutex); #endif m_block_cache = nullptr; }
MeterErrorCode Meter::reset_rates() { auto lock = unique_lock(); for (MeterRate &rate : rates) { rate.valid = false; } configured = false; return SUCCESS; }
void Meter::serialize(std::ostream *out) const { auto lock = unique_lock(); (*out) << configured << "\n"; if (configured) { for (const auto &rate : rates) (*out) << rate.info_rate << " " << rate.burst_size << "\n"; } }
void wait_for_data_to_process() { boost::unique_lock<boost::mutex> unique_lock(mutex); while(!data_ready) { condition_variable.wait(unique_lock); } process_data(); }
void FailOverCacheAsyncBridge::run() { boost::unique_lock<decltype(mutex_)> unique_lock(mutex_); while (not stop_) { try { if (not oldOnes.empty()) { LOG_DEBUG("Writing " << oldOnes.size() << " entries to the failover cache"); cache_->addEntries(oldOnes); oldOnes.clear(); LOG_DEBUG("Written"); } else { // Y42 The machine that goes ping cache_->flush(); } condvar_.wait_for(unique_lock, timeout_); if (oldOnes.empty()) { //we get here by a timeout -> time to swap //no risk for deadlock as addEntry only does a tryLock on mutex_ LOCK_NEW_ONES(); std::swap(newOnes, oldOnes); std::swap(newData, oldData); } } catch (std::exception& e) { LOG_ERROR("Exception in failover thread: " << e.what()); if(degraded_fun_) { degraded_fun_(); } LOCK_NEW_ONES(); stop_ = true; newOnes.clear(); oldOnes.clear(); // This thread cleans up itself when it is detached thread_->detach(); thread_ = nullptr; cache_ = nullptr; } // Z42: catch (...) ? } }
std::vector<Meter::rate_config_t> Meter::get_rates() const { std::vector<rate_config_t> configs; auto lock = unique_lock(); if (!configured) return configs; // elegant but probably not the most efficient for (const MeterRate &rate : rates) configs.push_back(rate_config_t::make(rate.info_rate, rate.burst_size)); std::reverse(configs.begin(), configs.end()); return configs; }
void LocalFiberRef::send(const PendingEvent& pendingEvent) { boost::shared_lock<boost::upgrade_mutex> shared_lock(block->mutex); block->mailbox->enqueue(pendingEvent); if (block->status == Suspended) { boost::upgrade_lock<boost::upgrade_mutex> upgrade_lock(std::move(shared_lock), boost::try_to_lock); if (upgrade_lock.owns_lock()) { boost::unique_lock<boost::upgrade_mutex> unique_lock(std::move(upgrade_lock)); system->schedule(block, std::move(unique_lock)); } } }
void GwObjectHost::assignClientMessageObjectsGwIds(const Signature& signature, Message& msg, TransportSocketPtr sender) { // if there's no chance of any object being in the call we're done. if (!hasObjectsSomewhere(signature)) return; AnyReference callParameters = msg.value(signature, sender); // re-serialize the arguments so that the objects can receive a GW-specific objectId // ObjectHost uses a static int for its objectId so we're OK instantiating multiple // ones. Message forward; MockObjectHost host(Message::Service_Server); forward.setFlags(msg.flags()); forward.setValue(callParameters, signature, &host, sender.get()); msg.setBuffer(forward.buffer()); // The message will store all the objects it serializes in the host. const ObjectHost::ObjectMap& objects = host.objects(); std::map<GwObjectId, MetaObject> newObjectsMetaObjects; std::map<GwObjectId, std::pair<TransportSocketPtr, ObjectAddress> > newObjectsOrigin; std::map<ObjectAddress, GwObjectId> newHostObjectBank; for (ObjectHost::ObjectMap::const_iterator it = objects.begin(), end = objects.end(); it != end; ++it) { GwObjectId oid = it->first; ServiceBoundObject* sbo = static_cast<ServiceBoundObject*>(it->second.get()); RemoteObject* ro = static_cast<RemoteObject*>(sbo->object().asGenericObject()->value); ObjectAddress addr; addr.service = ro->service(); addr.object = ro->object(); ro->setTransportSocket(TransportSocketPtr()); newObjectsMetaObjects[oid] = ro->metaObject(); newObjectsOrigin[oid] = std::make_pair(sender, addr); newHostObjectBank[addr] = oid; // We set an empty transportsocket. // Otherwise when we destroy `passed` below, the remoteobject // will attempt to send back home a `terminate` message, which we don't want. // By setting a null socket the object will stay alive on the remote end. qiLogDebug() << "Message " << msg.address() << ", Object connection: {" << addr.service << "," << addr.object << "} <=> {0," << oid << "}"; } { boost::upgrade_lock<boost::shared_mutex> lock(_mutex); boost::upgrade_to_unique_lock<boost::shared_mutex> unique_lock(lock); _objectsMetaObjects.insert(newObjectsMetaObjects.begin(), newObjectsMetaObjects.end()); _objectsOrigin.insert(newObjectsOrigin.begin(), newObjectsOrigin.end()); _hostObjectBank[sender].insert(newHostObjectBank.begin(), newHostObjectBank.end()); } callParameters.destroy(); }
Value get(const CalculateFunction& calculate) { boost::upgrade_lock<boost::upgrade_mutex> shared_lock(mContainerMutex); if (mHas) return mValue; // This is controversial but we prefer to block any other access while // calculating. This will prevent double calculation. boost::upgrade_to_unique_lock<boost::upgrade_mutex> unique_lock(shared_lock); mHas = true; return mValue = calculate(); }
void Meter::deserialize(std::istream *in) { auto lock = unique_lock(); (*in) >> configured; if (configured) { for (size_t i = 0; i < rates.size(); i++) { rate_config_t config; (*in) >> config.info_rate; (*in) >> config.burst_size; set_rate(i, config); } } }
//TODO: REMOVE THIS func and use Map::getBlock MapBlock* Map::getBlockNoCreateNoEx(v3POS p, bool trylock, bool nocache) { #ifndef NDEBUG ScopeProfiler sp(g_profiler, "Map: getBlock"); #endif #if !ENABLE_THREADS nocache = true; //very dirty hack. fix and remove. Also compare speed: no cache and cache with lock #endif if (!nocache) { #if ENABLE_THREADS && !HAVE_THREAD_LOCAL auto lock = try_shared_lock(m_block_cache_mutex, TRY_TO_LOCK); if(lock.owns_lock()) #endif if(m_block_cache && p == m_block_cache_p) { #ifndef NDEBUG g_profiler->add("Map: getBlock cache hit", 1); #endif return m_block_cache; } } MapBlockP block; { auto lock = trylock ? m_blocks.try_lock_shared_rec() : m_blocks.lock_shared_rec(); if (!lock->owns_lock()) return nullptr; auto n = m_blocks.find(p); if(n == m_blocks.end()) return nullptr; block = n->second; } if (!nocache) { #if ENABLE_THREADS && !HAVE_THREAD_LOCAL auto lock = unique_lock(m_block_cache_mutex, TRY_TO_LOCK); if(lock.owns_lock()) #endif { m_block_cache_p = p; m_block_cache = block; } } return block; }
Value get(const HandleSPtr& handle, Args... args, const CalculateFunction& calculate) { const auto& key = mContainer.key(handle, args...); boost::upgrade_lock<boost::shared_mutex> shared_lock(mContainerMutex); const auto& holder = mContainer.holder(key); if (mContainer.has(holder)) return mContainer.get(holder); // This is controversial but we prefer to block any other access while // calculating. This will prevent double calculation. boost::upgrade_to_unique_lock<boost::shared_mutex> unique_lock(shared_lock); const Value& value = calculate(args...); mContainer.put(key, value); return value; }
Status Config::update(const std::map<std::string, std::string>& config) { // A config plugin may call update from an extension. This will update // the config instance within the extension process and the update must be // reflected in the core. if (Registry::external()) { for (const auto& source : config) { PluginRequest request = { {"action", "update"}, {"source", source.first}, {"data", source.second}, }; // A "update" registry item within core should call the core's update // method. The config plugin call action handling must also know to // update. Registry::call("config", "update", request); } } // Request a unique write lock when updating config. boost::unique_lock<boost::shared_mutex> unique_lock(getInstance().mutex_); ConfigData conf; for (const auto& source : config) { if (Registry::external()) { VLOG(1) << "Updating extension config source: " << source.first; } else { VLOG(1) << "Updating config source: " << source.first; } getInstance().raw_[source.first] = source.second; } // Now merge all sources together. for (const auto& source : getInstance().raw_) { mergeConfig(source.second, conf); } getInstance().data_ = conf; return Status(0, "OK"); }
/** * @brief Remove all in progress timeouts. */ void CancelAll() { UniqueLock unique_lock(mutex_); timeout_timer_.cancel(); while (!data_.empty()) { auto event = std::move( data_.begin()->second ); data_.erase(data_.begin()); #ifdef MINGW32_LIMITED_ERRC std::errc errc_error = std::errc::interrupted; #else std::errc errc_error = std::errc::operation_canceled; #endif io_service_->post( boost::bind( event_processor_, std::move(event), std::make_error_code(errc_error))); } data_.clear(); }
Meter::color_t Meter::execute(const Packet &pkt) { color_t packet_color = 0; if (!configured) return packet_color; clock::time_point now = clock::now(); int64_t micros_since_init = duration_cast<ticks>(now - time_init).count(); auto lock = unique_lock(); /* I tried to make this as accurate as I could. Everything is computed compared to a single time point (init). I do not use the interval since last update, because it would require multiple consecutive approximations. Maybe this is an overkill or I am underestimating the code I wrote for BMv1. The only thing that could go wrong is if tokens_since_init grew too large, but I think it would take years even at high throughput */ for (MeterRate &rate : rates) { uint64_t tokens_since_init = static_cast<uint64_t>(micros_since_init * rate.info_rate); assert(tokens_since_init >= rate.tokens_last); size_t new_tokens = tokens_since_init - rate.tokens_last; rate.tokens_last = tokens_since_init; rate.tokens = std::min(rate.tokens + new_tokens, rate.burst_size); size_t input = (type == MeterType::PACKETS) ? 1u : pkt.get_ingress_length(); if (rate.tokens < input) { packet_color = rate.color; break; } else { rate.tokens -= input; } } return packet_color; }
// Only call on io_service void ResetTimer() { const auto now = std::chrono::steady_clock::now(); UniqueLock unique_lock(mutex_); while (running_ && !data_.empty()) { auto map_front_it = data_.begin(); const auto timeout = map_front_it->first; if ( timeout <= now ) { // Effeciently extract the value so we can move it. auto event = std::move( map_front_it->second ); data_.erase(map_front_it); // Unlock incase callback calls a TimedActions method. unique_lock.unlock(); event_processor_(std::move(event), std::error_code()); unique_lock.lock(); } else { timeout_timer_.expires_at(timeout); timeout_timer_.async_wait( boost::bind( &TimedEvents<Event>::HandleTimeout, this->shared_from_this(), boost::asio::placeholders::error ) ); break; } } }
void blockingSet(const K& key, const V& value) { size_t index = _hasher(key) % _size; boost::unique_lock<boost::shared_mutex> unique_lock(_mutexs[index]); _maps[index][key] = value; }
void blockingSet(const K& key, const V& value) { boost::unique_lock<boost::shared_mutex> unique_lock(_mutex); (*this)[key] = value; }
void Map::getBlockCacheFlush() { #if ENABLE_THREADS && !HAVE_THREAD_LOCAL auto lock = unique_lock(m_block_cache_mutex); #endif m_block_cache = nullptr; }
void InterfaceManagerImpl::updateDevices() { unique_lock(mMutex); GVariant* deviceList = nullptr; GError* error = nullptr; GCancellable* c = nullptr; try { if(mNetManagerProxy == nullptr){ throw std::runtime_error("Network Manager proxy not initialized"); } deviceList = g_dbus_proxy_call_sync(mNetManagerProxy, NM_METHOD_GET_DEVICES, NULL, G_DBUS_CALL_FLAGS_NONE, 1000, //timout of operation c, &error); if (deviceList == NULL && error != NULL){ throw std::runtime_error(error->message); } /**< iteration through the list */ GVariantIter deviceIter1, deviceIter2; GVariant *deviceNode1, *deviceNode2; g_variant_iter_init(&deviceIter1, deviceList); while ((deviceNode1 = g_variant_iter_next_value(&deviceIter1))) { g_variant_iter_init(&deviceIter2, deviceNode1); while ((deviceNode2 = g_variant_iter_next_value(&deviceIter2))) { gsize strlength = 256; const gchar* devicePath = g_variant_get_string(deviceNode2, &strlength); InterfaceInfo info = getDeviceInfo(devicePath); mInterfaces.insert(InterfaceInfoPair(devicePath, info)); } } } catch(const std::exception& e) { if(deviceList != nullptr){ g_variant_unref(deviceList); } if(error != nullptr){ g_error_free(error); } if(c != nullptr){ g_cancellable_release_fd(c); } std::cout<<e.what()<<std::endl; updateFailedSignal(); } }
void GwObjectHost::harvestServiceOriginatingObjects(Message& msg, TransportSocketPtr sender) { Signature signature; { boost::upgrade_lock<boost::shared_mutex> lock(_mutex); MetaObject* metaObject = NULL; const Signature& (MetaMethod::*signatureGetter)() const = NULL; if (msg.type() == Message::Type_Reply || msg.type() == Message::Type_Error) { std::map<ServiceId, std::map<ObjectId, MetaObject> >::iterator sit = _servicesMetaObjects.find(msg.service()); if (msg.function() == Message::BoundObjectFunction_MetaObject && sit->second.find(msg.object()) == sit->second.end()) { boost::upgrade_to_unique_lock<boost::shared_mutex> unique_lock(lock); _servicesMetaObjects[msg.service()][Message::GenericObject_Main] = extractReturnedMetaObject(msg, sender); return; } metaObject = &_servicesMetaObjects[msg.service()][msg.object()]; signatureGetter = &MetaMethod::returnSignature; } else if (msg.type() == Message::Type_Call || msg.type() == Message::Type_Post) { // if a service does a CALL, he does so on a user-supplied object. std::map<GwObjectId, MetaObject>::iterator mit = _objectsMetaObjects.find(msg.object()); assert(mit != _objectsMetaObjects.end()); metaObject = &mit->second; signatureGetter = &MetaMethod::parametersSignature; } const MetaMethod* method = metaObject->method(msg.function()); if (!method) return; signature = (method->*signatureGetter)(); } if (!hasObjectsSomewhere(signature)) { // no object can be here return; } AnyReference passed = msg.value(signature, sender); StreamContext filler; MockObjectHost host(Message::Service_Server); Message dummy; // we don't want to pollute the original message and potentially change valid id // of contained objects, so we do it in an unrelated message. dummy.setValue(passed, signature, &host, &filler); const ObjectHost::ObjectMap& objects = host.objects(); std::map<ObjectId, MetaObject> newServicesMetaObject; for (ObjectHost::ObjectMap::const_iterator it = objects.begin(), end = objects.end(); it != end; ++it) { ServiceBoundObject* sbo = static_cast<ServiceBoundObject*>(it->second.get()); RemoteObject* ro = static_cast<RemoteObject*>(sbo->object().asGenericObject()->value); // We set an empty transportsocket. // Otherwise when we destroy `passed` below, the remoteobject // will attempt to send back home a `terminate` message, which we don't want. // By setting a null socket the object will stay alive on the remote end. ro->setTransportSocket(TransportSocketPtr()); newServicesMetaObject[ro->object()] = ro->metaObject(); } { boost::upgrade_lock<boost::shared_mutex> lock(_mutex); boost::upgrade_to_unique_lock<boost::shared_mutex> unique_lock(lock); _servicesMetaObjects[msg.service()].insert(newServicesMetaObject.begin(), newServicesMetaObject.end()); } passed.destroy(); }