void CallbackQueue::callAvailable(ros::WallDuration timeout) { setupTLS(); TLS* tls = tls_.get(); { boost::mutex::scoped_lock lock(mutex_); if (!enabled_) { return; } if (callbacks_.empty()) { if (!timeout.isZero()) { condition_.timed_wait(lock, boost::posix_time::microseconds(timeout.toSec() * 1000000.0f)); } if (callbacks_.empty() || !enabled_) { return; } } bool was_empty = tls->callbacks.empty(); tls->callbacks.insert(tls->callbacks.end(), callbacks_.begin(), callbacks_.end()); callbacks_.clear(); calling_ += tls->callbacks.size(); if (was_empty) { tls->cb_it = tls->callbacks.begin(); } } size_t called = 0; while (!tls->callbacks.empty()) { if (callOneCB(tls) != Empty) { ++called; } } { boost::mutex::scoped_lock lock(mutex_); calling_ -= called; } }
void MachOObject::load() { if (isLoaded()) throw std::logic_error("Module already loaded"); if (strcmp(m_file->platform(), ARCH_NAME) != 0) { std::stringstream ss; ss << "This version of Darling dyld cannot load binaries for " << m_file->platform() << "."; throw std::runtime_error(ss.str()); } loadSegments(); transitionState(dyld_image_state_mapped); if (m_slide > 0) rebase(); transitionState(dyld_image_state_rebased); readSymbols(); readExports(); MachOMgr::instance()->add(this, isMainModule()); loadDependencies(); performRelocations(); performBinds(); transitionState(dyld_image_state_bound); transitionState(dyld_image_state_dependents_initialized); // registerEHSection(); if (isMainModule()) fillInProgramVars(); fillInDyldData(); setInitialSegmentProtection(); setupTLS(); MachOMgr::instance()->notifyAdd(this); runInitializers(); transitionState(dyld_image_state_initialized); m_file->closeFd(); if (MachOMgr::instance()->printLibraries()) std::cerr << "dyld: Loaded " << this->path() << std::endl; }
CallbackQueue::CallOneResult CallbackQueue::callOne(ros::WallDuration timeout) { setupTLS(); TLS* tls = tls_.get(); CallbackInfo cb_info; { boost::mutex::scoped_lock lock(mutex_); if (!enabled_) { return Disabled; } if (callbacks_.empty()) { if (!timeout.isZero()) { condition_.timed_wait(lock, boost::posix_time::microseconds(timeout.toSec() * 1000000.0f)); } if (callbacks_.empty()) { return Empty; } if (!enabled_) { return Disabled; } } D_CallbackInfo::iterator it = callbacks_.begin(); for (; it != callbacks_.end();) { CallbackInfo& info = *it; if (info.marked_for_removal) { it = callbacks_.erase(it); continue; } if (info.callback->ready()) { cb_info = info; it = callbacks_.erase(it); break; } ++it; } if (!cb_info.callback) { return TryAgain; } ++calling_; } bool was_empty = tls->callbacks.empty(); tls->callbacks.push_back(cb_info); if (was_empty) { tls->cb_it = tls->callbacks.begin(); } CallOneResult res = callOneCB(tls); if (res != Empty) { boost::mutex::scoped_lock lock(mutex_); --calling_; } return res; }
void CallbackQueue::removeByID(uint64_t removal_id) { setupTLS(); { IDInfoPtr id_info; { boost::mutex::scoped_lock lock(id_info_mutex_); M_IDInfo::iterator it = id_info_.find(removal_id); if (it != id_info_.end()) { id_info = it->second; } else { return; } } // If we're being called from within a callback from our queue, we must unlock the shared lock we already own // here so that we can take a unique lock. We'll re-lock it later. if (tls_->calling_in_this_thread == id_info->id) { id_info->calling_rw_mutex.unlock_shared(); } { boost::unique_lock<boost::shared_mutex> rw_lock(id_info->calling_rw_mutex); boost::mutex::scoped_lock lock(mutex_); D_CallbackInfo::iterator it = callbacks_.begin(); for (; it != callbacks_.end();) { CallbackInfo& info = *it; if (info.removal_id == removal_id) { it = callbacks_.erase(it); } else { ++it; } } } if (tls_->calling_in_this_thread == id_info->id) { id_info->calling_rw_mutex.lock_shared(); } } // If we're being called from within a callback, we need to remove the callbacks that match the id that have already been // popped off the queue { D_CallbackInfo::iterator it = tls_->callbacks.begin(); D_CallbackInfo::iterator end = tls_->callbacks.end(); for (; it != end; ++it) { CallbackInfo& info = *it; if (info.removal_id == removal_id) { info.marked_for_removal = true; } } } { boost::mutex::scoped_lock lock(id_info_mutex_); id_info_.erase(removal_id); } }