CurrentQueue() : queue_(kCurrentQueueSize) { if (FLAGS_observer_manager_pool_size < 1) { LOG(ERROR) << "--observer_manager_pool_size should be >= 1"; FLAGS_observer_manager_pool_size = 1; } for (int32_t i = 0; i < FLAGS_observer_manager_pool_size; ++i) { threads_.emplace_back([this, i]() { folly::setThreadName( folly::sformat("{}{}", kObserverManagerThreadNamePrefix, i)); ObserverManager::inManagerThread_ = true; while (true) { Function<void()> task; queue_.blockingRead(task); if (!task) { return; } try { task(); } catch (...) { LOG(ERROR) << "Exception while running CurrentQueue task: " << exceptionStr(std::current_exception()); } } }); } }
fbstring exception_wrapper::what() const { if (item_) { return exceptionStr(*item_); } else if (eptr_) { return estr_; } else { return fbstring(); } }
fbstring exception_wrapper::what() const { if (item_) { return exceptionStr(*item_); } else if (eptr_ && eobj_) { return class_name() + ": " + eobj_->what(); } else if (eptr_ && etype_) { return class_name(); } else { return class_name(); } }
void FunctionScheduler::runOneFunction(std::unique_lock<std::mutex>& lock, steady_clock::time_point now) { DCHECK(lock.mutex() == &mutex_); DCHECK(lock.owns_lock()); // The function to run will be at the end of functions_ already. // // Fully remove it from functions_ now. // We need to release mutex_ while we invoke this function, and we need to // maintain the heap property on functions_ while mutex_ is unlocked. RepeatFunc func(std::move(functions_.back())); functions_.pop_back(); if (!func.cb) { VLOG(5) << func.name << "function has been canceled while waiting"; return; } currentFunction_ = &func; // Update the function's next run time. if (steady_) { // This allows scheduler to catch up func.setNextRunTimeSteady(); } else { // Note that we set nextRunTime based on the current time where we started // the function call, rather than the time when the function finishes. // This ensures that we call the function once every time interval, as // opposed to waiting time interval seconds between calls. (These can be // different if the function takes a significant amount of time to run.) func.setNextRunTimeStrict(now); } // Release the lock while we invoke the user's function lock.unlock(); // Invoke the function try { VLOG(5) << "Now running " << func.name; func.cb(); } catch (const std::exception& ex) { LOG(ERROR) << "Error running the scheduled function <" << func.name << ">: " << exceptionStr(ex); } // Re-acquire the lock lock.lock(); if (!currentFunction_) { // The function was cancelled while we were running it. // We shouldn't reschedule it; return; } // Clear currentFunction_ CHECK_EQ(currentFunction_, &func); currentFunction_ = nullptr; // Re-insert the function into our functions_ heap. // We only maintain the heap property while running_ is set. (running_ may // have been cleared while we were invoking the user's function.) functions_.push_back(std::move(func)); if (running_) { std::push_heap(functions_.begin(), functions_.end(), fnCmp_); } }