Last active
August 14, 2019 16:34
-
-
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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 tofalse
: So only anyenter
after the first one, by an instance other than the first one, can inadvertently block.wait
when the former owner has already passedexit
(and, thusnotify_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
orB
get to work onworker
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.