Skip to content

Instantly share code, notes, and snippets.

@facontidavide
Last active June 6, 2023 22:22
Show Gist options
  • Save facontidavide/95f20c28df8ec91729f9d8ab01e7d2df to your computer and use it in GitHub Desktop.
Save facontidavide/95f20c28df8ec91729f9d8ab01e7d2df to your computer and use it in GitHub Desktop.
Use std::string_view to find() an element in std::unordered_map<string,T>, avoiding potential memory allocations
#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;
}
@facontidavide
Copy link
Author

unordered_map itself is not thread safe ;)

@kolomenkin
Copy link

kolomenkin commented Apr 30, 2022

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.

@Vizepi
Copy link

Vizepi commented Jun 4, 2023

@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.

@kolomenkin
Copy link

kolomenkin commented Jun 6, 2023

@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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment