| 189 | } |
| 190 | |
| 191 | Status CodeGenCache::Store(const CodeGenCacheKey& cache_key, LlvmCodeGen* codegen, |
| 192 | TCodeGenCacheMode::type mode, TCodeGenOptLevel::type opt_level) { |
| 193 | DCHECK(!is_closed_); |
| 194 | DCHECK(cache_ != nullptr); |
| 195 | DCHECK(codegen != nullptr); |
| 196 | Status status = Status::OK(); |
| 197 | pair<unordered_set<CodeGenCacheKey::HashCode>::iterator, bool> key_to_insert_it; |
| 198 | { |
| 199 | // The Cache::Insert() suggests the caller to avoid multiple handles for the same |
| 200 | // key to insert because it can be inefficient to keep the entry from being evicted. |
| 201 | // So use the keys_to_insert_ set to reduce the chance of multiple insertion of the |
| 202 | // same cache entry. |
| 203 | // Before insertion, we will try to insert the hash code of the key to the set, if |
| 204 | // succeeds, the thread is allowed to do the insertion, and is responsible to erase |
| 205 | // the hash code in the set when insertion finishes. |
| 206 | // Otherwise, if the thread fails to insert the hash code, that means one other thread |
| 207 | // is doing the insertion on the same key, in that case, the current thread would give |
| 208 | // up the task and return with an okay status, because we assume the other thread |
| 209 | // would get the cache entry in. Even that thread fails, the system won't hurt without |
| 210 | // only one cache entry, and the cache entry can be inserted again next time. |
| 211 | lock_guard<mutex> lock(to_insert_set_lock_); |
| 212 | key_to_insert_it = keys_to_insert_.insert(cache_key.hash_code()); |
| 213 | // If hash code exists, return an okay immediately. |
| 214 | if (!key_to_insert_it.second) return status; |
| 215 | } |
| 216 | status = StoreInternal(cache_key, codegen, mode, opt_level); |
| 217 | // Remove the hash code of the key from the to_insert_keys set. |
| 218 | lock_guard<mutex> lock(to_insert_set_lock_); |
| 219 | keys_to_insert_.erase(key_to_insert_it.first); |
| 220 | return status; |
| 221 | } |
| 222 | |
| 223 | void CodeGenCache::StoreEngine(LlvmCodeGen* codegen) { |
| 224 | DCHECK(codegen != nullptr); |