Skip to content

Instantly share code, notes, and snippets.

@fairlight1337
Last active August 14, 2019 16:34
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fairlight1337/a93262d3f56817b804ff47585f32b718 to your computer and use it in GitHub Desktop.
Save fairlight1337/a93262d3f56817b804ff47585f32b718 to your computer and use it in GitHub Desktop.
Simple synchronization class for allowing the same thread to enter a function over and over again, but shutting out others while it is in use
#include <iostream>
#include <condition_variable>
#include <mutex>
#include <thread>
#include <string>
class Synchronizer {
private:
std::condition_variable m_cvCondition;
std::mutex m_mtxAccess;
std::thread::id m_tiHolder;
bool m_bFirst;
public:
Synchronizer() : m_bFirst(true) {
}
~Synchronizer() {
}
void enter() {
std::unique_lock<std::mutex> ulLock(m_mtxAccess);
std::thread::id tiCurrent = std::this_thread::get_id();
if(tiCurrent != m_tiHolder && !m_bFirst) {
m_cvCondition.wait(ulLock);
}
m_tiHolder = tiCurrent;
m_bFirst = false;
}
void exit() {
m_cvCondition.notify_one();
}
};
void worker(std::string me, int count) {
static Synchronizer s;
s.enter();
std::cout << __FUNCTION__ << " / " << me << ": " << count << std::endl;
if(count > 0) {
worker(me, count - 1);
}
s.exit();
}
int main() {
std::thread tA(worker, "A", 3);
std::thread tB(worker, "B", 3);
tA.join();
tB.join();
}
@fairlight1337
Copy link
Author

The above class is a very basic implementation of a synchronization mechanism as described in the title. It suffers from the fact that it can block access when

  • m_bFirst was set to false: So only any enter after the first one, by an instance other than the first one, can inadvertently block.
  • A thread begins wait when the former owner has already passed exit (and, thus notify_one): The second thread waits forever.

I think the former is actually because of the latter. Besides these, the basic example given above works just fine. Either thread A or B get to work on worker and are allows to re-enter it (based in their thread-id), but the other one is shut out until the work is done.

This can definitely be improved, but serves as a working example of how condition_variable can be used.

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