vendredi 20 août 2021

Is this a valid binary mutex implementation?

I'm not really sure if this types of questions are frowned upon here, but it is the first place I come for when I have a question in mind, so, here we go.

I have a std::vector<T> v that I use to store data. In thread t1, there is a data generator and data insertion can happen at any time. On the other hand, in thread t2, at arbitrary times, I need to search v and access and return an element from it. Deletions, swaps etc. are guaranteed to not happen on v until both t1 and t2 join on main thread.

Without any thread-safety measures, code exits with SIGABRT. I first used std::mutex and std::lock_guard and succeeded, however the number of lock/unlocks are in millions and I wish to speed things up a bit. So I tried to implement the following system:

#include <atomic>
#include <cassert>
#include <thread>

// Mutex-like thingy begin
class MyMutex
{
private:
  std::atomic<bool> modifyLockRequest;
  std::atomic<bool> accessLockRequest;
  std::atomic<bool> accessLock;

public:
  MyMutex() :
      modifyLockRequest(false),
      accessLockRequest(false),
      accessLock(false) {}

  void acquireModifyLock() {
    assert(!modifyLockRequest);
    modifyLockRequest = true;
    while( accessLockRequest && accessLock ) {
      std::this_thread::yield();
    }
  }

  void releaseModifyLock() {
    assert(modifyLockRequest);
    modifyLockRequest = false;
  }

  void acquireAccessLock() {
    assert(!accessLockRequest);
    accessLockRequest = true;
    while (modifyLockRequest) {
      std::this_thread::yield();
    }
    accessLock = true;
  }

  void releaseAccessLock() {
    assert(accessLockRequest);
    accessLock = false;
    accessLockRequest = false;
  }
};

MyMutex myMutex;

Then I use this by

myMutex.acquireModifyLock();
// Do insertion/deletion etc. on `v`
myMutex.releaseModifyLock();

and

myMutex.acquireAccessLock();
// Do stuff with `v[i]`
myMutex.releaseAccessLock();

My rationale was to have 2 Boolean flags to alert whichever thread is trying to get a lock, and to have a third flag to break off cases where the two threads try to acquire a lock at the same time.

This code seems to work well in about 1/8th time of std::mutex and std::lock_guard duo, however, my question is, is this solution guaranteed to always work in my case where there is only 2 threads?

Aucun commentaire:

Enregistrer un commentaire