-
-
Save facontidavide/95f20c28df8ec91729f9d8ab01e7d2df to your computer and use it in GitHub Desktop.
#include <iostream> | |
#include <cstring> | |
#include <unordered_map> | |
// https://github.com/martinmoene/string-view-lite | |
#include "string_view.hpp" | |
template <typename Value> | |
class StringMap: public std::unordered_map<std::string, Value> | |
{ | |
public: | |
typename std::unordered_map<string,Value>::iterator find(const nonstd::string_view& v ) | |
{ | |
tmp_.reserve( v.size() ); | |
tmp_.assign( v.data(), v.size() ); | |
return std::unordered_map<string, Value>::find(tmp_); | |
} | |
typename std::unordered_map<std::string,Value>::iterator find(const std::string& v ) | |
{ | |
return std::unordered_map<std::string, Value>::find(v); | |
} | |
typename std::unordered_map<std::string,Value>::iterator find(const char* v ) | |
{ | |
tmp_.assign(v); | |
return std::unordered_map<std::string, Value>::find(v); | |
} | |
private: | |
thread_local static std::string tmp_; | |
}; | |
template <typename T> thread_local std::string StringMap<T>::tmp_ = {}; | |
int main() | |
{ | |
std::string key_A("Hello"); | |
nonstd::string_view key_B("Hello"); | |
nonstd::string_view key_C(key_A); | |
StringMap<std::string> smap; | |
smap["Hello"] = "World"; | |
for (auto& it: smap) | |
{ | |
std::cout << it.first << ":" << it.second << std::endl; | |
} | |
std::cout << smap.find(key_A)->second << std::endl; | |
std::cout << smap.find(key_B)->second << std::endl; | |
std::cout << smap.find(key_C)->second << std::endl; | |
std::cout << smap.find("Hello")->second << std::endl; | |
return 0; | |
} |
unordered_map itself is not thread safe ;)
std::unordered_map::find is originally thread safe against itself and other readonly methods. But your solution is not.
If I implement shared_mutex pattern with multiple simultaneous readers your implementation may corrupt memory.
I'm writing here to notify others since this code is easily found via google, I saw people citing this solution in stackOverflow. But this solution is broken and may corrupt memory in multi threaded environment.
@kolomenkin Are you confusing hardware threads and execution threads?
If the OS schedules another execution thread on the hardware thread the previous code was running on, the thread_local variable will not be the same.
@Vizepi , you are right. It was a silly mistake on my side.
@facontidavide , your solution does not have the problems I mentioned above. It is thread safe for reading.
As for me the solution does not look thread safe.
Find
function may be interrupted in the middle by OS and another thread may be scheduled in the same thread executing the same code and reusing the same std::string buffer.