const GzipHeaderCodec::ZlibContext* GzipHeaderCodec::getZlibContext( SPDYVersionSettings versionSettings, int compressionLevel) { static folly::ThreadLocal<ZlibContextMap> zlibContexts_; ZlibConfig zlibConfig(versionSettings.version, compressionLevel); auto match = zlibContexts_->find(zlibConfig); if (match != zlibContexts_->end()) { return match->second.get(); } else { // This is the first request for the specified SPDY version and compression // level in this thread, so we need to construct the initial compressor and // decompressor contexts. auto newContext = folly::make_unique<ZlibContext>(); newContext->deflater.zalloc = Z_NULL; newContext->deflater.zfree = Z_NULL; newContext->deflater.opaque = Z_NULL; newContext->deflater.avail_in = 0; newContext->deflater.next_in = Z_NULL; int windowBits = (compressionLevel == Z_NO_COMPRESSION) ? 8 : 11; int r = deflateInit2( &(newContext->deflater), compressionLevel, Z_DEFLATED, // compression method windowBits, // log2 of the compression window size, negative value // means raw deflate output format w/o libz header 1, // memory size for internal compression state, 1-9 Z_DEFAULT_STRATEGY); CHECK(r == Z_OK); if (compressionLevel != Z_NO_COMPRESSION) { r = deflateSetDictionary(&(newContext->deflater), versionSettings.dict, versionSettings.dictSize); CHECK(r == Z_OK); } newContext->inflater.zalloc = Z_NULL; newContext->inflater.zfree = Z_NULL; newContext->inflater.opaque = Z_NULL; newContext->inflater.avail_in = 0; newContext->inflater.next_in = Z_NULL; r = inflateInit(&(newContext->inflater)); CHECK(r == Z_OK); auto result = newContext.get(); zlibContexts_->emplace(zlibConfig, std::move(newContext)); return result; } }
bool SPDYUtil::hasGzipAndDeflate(const std::string& value, bool& hasGzip, bool& hasDeflate) { static folly::ThreadLocal<std::vector<RFC2616::TokenQPair>> output; output->clear(); hasGzip = false; hasDeflate = false; RFC2616::parseQvalues(value, *output); for (const auto& encodingQ: *output) { std::string lower(encodingQ.first.str()); std::transform(lower.begin(), lower.end(), lower.begin(), ::tolower); // RFC says 3 sig figs if (lower == "gzip" && encodingQ.second >= 0.001) { hasGzip = true; } else if (lower == "deflate" && encodingQ.second >= 0.001) { hasDeflate = true; } } return hasGzip && hasDeflate; }
bool parseQvalues(folly::StringPiece value, std::vector<TokenQPair> &output) { bool result = true; static folly::ThreadLocal<std::vector<folly::StringPiece>> tokens; tokens->clear(); folly::split(",", value, *tokens, true /*ignore empty*/); for (auto& token: *tokens) { auto pos = token.find(';'); double qvalue = 1.0; if (pos != std::string::npos) { auto qpos = token.find("q=", pos); if (qpos != std::string::npos) { folly::StringPiece qvalueStr(token.data() + qpos + 2, token.size() - (qpos + 2)); try { qvalue = folly::to<double>(&qvalueStr); } catch (const std::range_error&) { // q=<some garbage> result = false; } // we could validate that the remainder of qvalueStr was all whitespace, // for now we just discard it } else { // ; but no q= result = false; } token.reset(token.start(), pos); } // strip leading whitespace while (token.size() > 0 && isspace(token[0])) { token.reset(token.start() + 1, token.size() - 1); } if (token.size() == 0) { // empty token result = false; } else { output.emplace_back(token, qvalue); } } return result && output.size() > 0; }
void QueuedImmediateExecutor::addStatic(Func callback) { static folly::ThreadLocal<std::queue<Func>> q_; if (q_->empty()) { q_->push(std::move(callback)); while (!q_->empty()) { q_->front()(); q_->pop(); } } else { q_->push(callback); } }
ThreadLocalPRNG::ThreadLocalPRNG() { static folly::ThreadLocal<ThreadLocalPRNG::LocalInstancePRNG> localInstance; local_ = localInstance.get(); }
void useA() { a->use(); }