Home > Enterprise >  c generic threadsafe container
c generic threadsafe container

Time:01-11

Because c does not provide thread-safe container out-of-the-box, I am trying to create a generic thread-safe container.

In a multithreaded environment, many threads may modify my list (or any other container). I want to ensure that my list is thread-safe and only a single thread can modify my list at any given time.

My code is below. I'd like to know if it would work in a

template<typename T>
class ThreadSafeContainer {
    public:
      ThreadSafeContainer(): lck{mtx}{};
      T getContainer(){
          return container;
      }
    private:
      T container;
      std::lock_guard<std::mutex> lck;
      std::mutex mtx;
};

int main(){
    ThreadSafeContainer<std::list<int>> list;
    std::list<int> my_list = list.getContainer();
    
     // multiple threads can access my_list in a thread-safe way

    return 0;
}

CodePudding user response:

No, it won't work. Once the container is created, it is created with a mutex and that mutex is immediately locked and stays locked until the container is destroyed. No one checks that mutex. There is no locking mechanism at all. Every thread trying to access it, will access it.

You need to redefine all the access operations and lock the mutex when accessing the container.

CodePudding user response:

The standard library doesn't provide a generic thread-safe container because it doesn't make sense. Say you take a reference to one of the elements. How could the container ensure that you don't hold on to the reference?

On the other hand, if you have a specific goal, like multiple threads appending elements at the same time. Or a synchronized hash table where the elements are immutable. These can be done. The details of how would depend a lot on the task at hand.

That is to say, threading is hard and there is no silver bullet to make your code correct. Try to minimize shared state and carefully synchronize whatever is left.

CodePudding user response:

Instead of making a datatype threadsafe you can also make the calls to it threadsafe. For example (very basic approach, executors that serialize calls to either a safe section or a seperate thread are better).

#include <mutex>
#include <type_traits>
#include <vector>

template<typename Fn>
auto call_ts(Fn fn) -> decltype(fn())
{
    static std::mutex mtx;
    std::unique_lock<std::mutex> lock(mtx);

    if constexpr (std::is_same_v<void, decltype(fn())>)
    {
        fn();
        return;
    }
    else
    {
        return fn();
    }
}

int main()
{
    std::vector<int> values;

    call_ts([&] {values.push_back(1); });
    call_ts([&] {values.push_back(2); });
    auto size = call_ts([&] { return values.size(); });
    return 0;
}
  •  Tags:  
  • Related