Synchronize object - c++

Having object that has extensive API list.
What is the best way to synchronize this object, i.e. the object already exists in legacy code and used in hundreds of lines of code.
The naive way is to wrap each API call to object with std::mutex. Is there an easier or elegant way to do it?
I have tried below code, however would like to get opinion on it or alternative solutions .
Below is template wrapper class that lock the object during the usage , in an automatic way. i.e. locks the object on creation and unlocks upon destruction.
This pattern is very similar to scope lock, however it's useful only for static objects/singletons, it wouldn't work for different instances of a given object
template <typename T> class Synced
{
static std::mutex _lock;
T& _value;
public:
Synced(T& val) : _value(val)
{
std::cout << "lock" << endl;
_lock.lock();
}
virtual ~Synced()
{
std::cout << "unlock" << endl;
_lock.unlock();
}
T& operator()()
{
return _value;
}
};
template <class T> std::mutex Synced<T>::_lock;
example class to be used with Synced template class
this could be example of a class mentioned above with tens of API's
class Board
{
public:
virtual ~Board() { cout << "Test dtor " << endl; }
void read() { cout << "read" << endl; }
void write() { cout << "write" << endl; }
void capture() { cout << "capture" << endl; }
};
example of usage , basic calls , the Synced object isn't bounded to scope , thus the destructor is called immediately after semicolon
int main(int argc, char* argv[])
{
Board b;
Synced<Board>(t)().read();
cout <<" " << endl;
Synced<Board>(t)().write();
cout << " " << endl;
Synced<Board>(t)().capture();
cout << " " << endl;
return 1;
}
Here below is output of above example run :
lock
read
unlock
lock
write
unlock
lock
capture
unlock
Test dtor

I only use mutexes for very small critical sections, a few lines of code maybe, and only if I control all possible error conditions. For a complex API you may end up with the / a mutex in an unexpected state. I tend to tackle this sort of thing with the reactor pattern. Whether or not that is practical depends on whether or not you can reasonably use serialization / deserialization for this object. If you have to write serialization yourself then consider things like API stability and complexity. I personally prefer zeromq for this sort of thing when using it is practical, your mileage may vary.

Related

Scoped lock_guard Not Releasing Mutex in Static Method

Platform Debian 9 | ARM
I have a class that is used to store thread IDs on a std::list and then print the list as part of the shutdown procedure. There are two static methods: AddId() and PrintIds(). Since the static methods are used by several threads, the list access is protected with a std::mutex. I have come across two issues that have me baffled and they may be related. I hope one of you can help explain what I am missing.
Note I first used scoped std::lock_guard<std::mutex>s and have temporarily settled on the std::unique_lock<std::mutex>s that are shown in the code for the reasons explained herein.
Issue 1 When the program starts, all threads call ThreadMgr::AddId(), which adds the thread id to the list along with a string name. That seems to work fine. However, when ThreadMgr::PrintIds() is called during the shutdown procedure, the std::mutex is still locked and the std::lock_guard blocks. While testing, I unlocked the std::mutex in the line preceding the std::lock_guard--which is undefined behavior if it wasn't locked by the calling thread--and then it worked as expected. The only place the std::mutex is used is in these two methods, and with the std::lock_guard being scoped, the std::mutex should have been unlocked with every method call. I went through several iterations of locking and unlocking the std::mutex directly, using std::unique_locks, etc. I eventually found a somewhat workable solution using the std::unique_locks that are in the code provided here. However, that too has me baffled.
The std::unique_locks work if I use std::adopt_lock, but only in ThreadMgr::PrintIds(). If I use std::adopt_lock in ThreadMgr::AddId(), then I get a segmentation fault whenever ThreadMgr::PrintIds() is called.
Issue 2 As previously stated, ThreadMgr::AddId() runs fine with either std::lock_guard or std::unique_lock when all threads call it on startup. However, there are UI sessions where each session spawns a thread. When ThreadMgr::AddId() is called from one of these session threads, both std::lock_guard and std::unique_lock block like the std::mutex is already locked. So, ThreadMgr::AddId() works perfectly fine for every other thread, but not for the session threads that are started later.
If there is any other information I can provide to help get to a solution, let me know.
class ThreadMgr {
public:
ThreadMgr();
~ThreadMgr();
static void AddId(std::string);
static void PrintIds();
private:
static std::list<ThreadId> t_list;
static std::mutex list_mtx;
};
/*Definition*/
ThreadMgr::ThreadMgr() {}
ThreadMgr::~ThreadMgr() {}
/*Static Members*/
void ThreadMgr::AddId(std::string name) {
ThreadId t_id = getThreadId(name);
{
std::unique_lock<std::mutex> lock(list_mtx);
t_list.push_front(t_id);
}
std::lock_guard<std::mutex> lk(cout_mtx);
std::cout << "---Added id: " << t_id.tid << " for the " << name << " thread." << std::endl;
return;
}
void ThreadMgr::PrintIds() {
std::ostringstream oss;
oss << "\n**************************Thread Ids**************************\n";
{
std::unique_lock<std::mutex> lock(list_mtx, std::adopt_lock);
for (std::list<ThreadId>::iterator t = t_list.begin(); t != t_list.end(); t++) {
oss << "---" << t->name << " : " << t->tid << '\n';
}
}
oss << "************************End Thread Ids************************" << '\n';
std::lock_guard<std::mutex> lk(cout_mtx);
std::cout << oss.str() << std::endl;
return;
}
std::mutex ThreadMgr::list_mtx;
std::list<ThreadId> ThreadMgr::t_list;
int Main(){
ThreadMgr::AddId("Main");
std::thread MbServerT(MbServer);
std::thread UiServerT(UiServer);
while(run){
//do stuff
}
ThreadMgr::PrintIds();
if(MbServerT.joinable())
MbServerT.join();
if(UiServerT.joinable())
UiServerT.join();
return 0;
}

How to flush a log message and unlock a mutex automatically in C++?

I wrote this logger. It works fine, but there is something I have not been able to do.
uLOG(warning) << "Test log message " << 123 << uLOGE;
uLOG locks a C++11 mutex and starts writing on a file stream.
uLOGE flushes the stream and unlocks the mutex.
I would like to get the same result with this syntax:
uLOG(warning) << "Test log message " << 123;
so I would like the flush and the unlock to be called automatically at the end of the line.
Which is a possible way to do it?
I tried setting the ios::unitbuf flag, but this forces a flush for every << operator, not ideal for an SSD wearing. And it does not unlock the mutex.
I tried defining a temporary object in uLOG whose destructor would flush and unlock, but that forces to put the log line in its own code block: { uLOG(warning) << 123; }
Reference
You need to redesign your logging framework, so that uLOG is a class that you instantiate, and whose destructor does the work of your uLOGE macro.
Very simple example:
struct uLOG
{
uLOG(std::string const& type)
{
std::cout << "Log: " << type << " - ";
}
template<typename T>
uLOG& operator<<(T const& output)
{
std::cout << output;
return *this;
}
~uLOG()
{
std::cout << " (end of log)" << std::endl;
}
};
// ...
uLOG("warning") << "log message" << 123;
The above, in a suitable program, should print
Log: warning - log message123 (end of log)
This solution should not require the use of braces, so could be used in a single-statement un-braced if or loop.
Your second approach is correct, if implemented correctly it does not require braces. Did you do it with macros? They are not needed here.
uLOG should be a function that returns a temporary object of a Log writer class. As you outlined, it should lock in ctor and flush and unlock in dtor and also have templated operator<< for all types, that just forwards the call to actual log destination.

Atomic data member calling from a thread

Can someone please help me understand what i am doing wrong here?
When i make the data members of the class non atomic it is working fine.
class AtomicTest
{
atomic<int> A{ 0 };
atomic<int> B{ 0 };
public :
AtomicTest() { }
void func1()
{
A = 1;
cout << "func1 " << A << endl;;
}
void func2()
{
cout << "func2 " << A << endl;
A = A + 1;
cout << A << endl;
}
};
int main()
{
AtomicTest a;
thread t1(&AtomicTest::func1, std::ref(a)); // I tried to move as well, i know ref would share data between two threads but i can use mutex to protect data if its needed but i cannot even call the func1
//thread t2(&AtomicTest::func2, std::ref(a));
t1.join();
//t2.join();
return 0;
}
Due to concurrency without additional synchronization in this case it's impossible to predict program behavior:
A = A + 1;
This simple line consists of 1 atomic load and 1 atomic store operations. Even default memory order (std::memory_order_seq_cst) wont give you any guarantees about mixed simultaneous execution of these two threads. Standard says such case has an undefined behavior -- there is data race for your variable (it doesn't matter is it atomic or not).
Try to add some lock primitives (such as std::mutex) or change the logic to use special atomic functions (such as fetch_add, exchange etc.). See more at the cpp-reference.

How to organize a pool of non thread-safe resources in Cilk Plus (one resource per worker)?

I have a serial code that I would like to parallelize using Cilk Plus; the main loop calls a processing function repeatedly on different sets of data, so the iterations are independent of each other, except for the use of a non thread-safe resource, which is encapsulated into a class (say, nts) provided by an external library which takes a filename and does I/O on it.
If I were using OpenMP, I would create a pool of resources that contains as much resources as I have threads, and access these resources according to the thread ID:
std::vector<nts> nts_pool;
for (std::size_t i{0}; i < omp_get_num_threads(); ++i)
nts_pool.push_back(nts{});
nts_pool[omp_get_thread_num()].do_stuff(); // from inside the task
Using Cilk Plus, I could do as much using the __cilkrts_get_nworkers() and __cilkrts_get_worker_number() APIs, but from multiple posts on Intel forums, I gathered that this is considered to be a wrong solution to the problem, and the right solution would be to use a holder hyperobject.
Now, the holder solution looks nice indeed, except that I really want to have only as much views created as I have worker threads. That is, for 3 worker threads, I would like to have 3 objects and not more. The justification is that as I say, the resource is provided by a third-party library, is very expensive to construct, and I will have to deal with resulting files afterwards, so the fewer the better.
Unfortunately, I have found out that instead of making a view per worker and keeping it until a sync, holders somehow create and destroy views according to the logic that I don't understand, and there doesn't seem to be a way to influence this behavior.
Is it possible to make holders behave the way I want, and if not, what would be an idiomatic Cilk Plus solution to my problem?
Here is the program I used to investigate holders, note that it creates up to 50 views on my test machine during one run, that are allocated and destroyed seemingly at random:
#include <iostream>
#include <atomic>
#include <cilk/cilk.h>
#include <cilk/holder.h>
#include <cilk/reducer_ostream.h>
#include <cilk/cilk_api.h>
cilk::reducer_ostream *hyper_cout;
class nts {
public:
nts() : tag_{std::to_string(++id_)} {
*hyper_cout << "NTS constructor: " << tag_ << std::endl;
}
~nts() {
*hyper_cout << "NTS destructor: " << tag_ << std::endl;
}
void print_tag() {
*hyper_cout << "NTS tag: " << tag_ << std::endl;
}
static void is_lock_free() {
*hyper_cout << "Atomic is lockfree: " << id_.is_lock_free() << std::endl;
}
private:
const std::string tag_;
static std::atomic_size_t id_;
};
std::atomic_size_t nts::id_{0};
class nts_holder {
public:
void print_tag() { nts_().print_tag(); }
private:
cilk::holder<nts> nts_;
};
int main() {
__cilkrts_set_param("nworkers", "4");
cilk::reducer_ostream cout{std::cout};
hyper_cout = &cout;
*hyper_cout << "Workers: " << __cilkrts_get_nworkers() << std::endl;
nts::is_lock_free();
nts_holder ntsh;
ntsh.print_tag();
for (std::size_t i{0}; i < 1000; ++i) {
cilk_spawn [&] () {
ntsh.print_tag();
} ();
}
cilk_sync;
return 0;
}
You are correct that holders are a tempting but inefficient solution to this particular problem. If your program is correct using the array of slots with one slot per worker, there is really nothing wrong with using the __cilkrts_get_nworkers() and __cilkrts_get_worker_number() APIs in this case. We do discourage their use in general; preferring to write Cilk Plus code that is oblivious to the number workers because it usually scales better that way. However, there are cases, including this one, where creating a slot per worker is the best strategy.

How to make sure a chained logging statement is atomic?

I have a logging class which has operator<< overloaded. So I can do things like this:
oLogger << "Log this" << " and this" << " and " << 10 << endl;
oLogger`<< "Something else" << endl;
The logger does this without any problems. But, I want the logger object to be shared among threads. Then, I don't want it printing out something like this:
//LogFILE
Log this and this Something else
and 10
So, I need to lock a whole chain of operator<<s. I am guessing this can be done with RAII, I haven't given it much thought yet. In the meantime, is there any traditional way of getting this done? (Except ending input with a manipulator?)
Slight alternative to Nim's answer:
Create
class LockedLog {
static MutEx mutex; // global mutex for logging
ScopedLock lock; // some scoped locker to hold the mutex
Logger &oLogger; // reference to the log writer itself
public:
LockedLog(Logger &oLogger) : oLogger(oLogger), lock(mutex) {}
template <typename T>
LockedLog &operator<<(const T &value) { oLogger << value; return *this; }
};
And either just do:
LockedLog(oLogger) << "Log this" << " and this " << " and " << 10 << endl;
Or change Logger::operator<< to normal method, call this method in LockedLog::operator<<, add cast-operator to Logger:
operator LockedLog() { return LockedLog(*this); }
and that should add locking to your current code.
Update: That locks across all the calls to operator<< and may even lock around evaluation of their arguments (depends on whether compiler will evaluate left or right argument first and it may choose). To reduce that, one could:
class LockedLog {
static MutEx mutex; // global mutex for logging
std::stringstream buffer; // temporary formatting buffer;
Logger &oLogger; // reference to the log writer itself
public:
LockedLog(Logger &oLogger) : oLogger(oLogger), lock(mutex) {}
template <typename T>
LockedLog &operator<<(const T &value) { buffer << value; return *this; }
~LockedLog() { ScopedLock lock(mutex); oLogger << buffer.str() << std::flush; }
};
But the stringstream adds another overhead.
One approach is to use a macro, i.e.
#define LOG(x) \
{\
<acquire scoped lock> \
oLogger << x; \
}
then
LOG("Log this" << " and this" << " and " << 10 << endl);
I've also done it using the manipulator approach that you mention above, however the problem is that you need to have operator<< implemented for all the types (i.e. can't use the standard operators that exist)
EDIT: to reduce the time the lock is held, consider something like this:
#define LOG(x) \
{\
std::ostringstream str; \
str << x; \ // the streaming happens in local scope, no need for lock
oLogger.write(str.str()); \ // ensure the write method acquires a lock
}
I've found that the best solution is to write a class buffer so that
buffer(oLogger) << "Log this" << " and this" << " and " << 10 << endl;
creates a temporary buffer object, captures and formats the output and writes it to oLogger in its destructor. This is trivially done by wrapping a stringstream. Because every thread has its own buffers, formatting is independent.
For extra fanciness, buffer::~buffer can use several different mechanisms to prevent thread-unsafe access of oLogger. You assumed that operator<< calls from multiple threads might be interleaved. In fact, it's worse; they can be concurrent. You could get "LSoogm ethhiinsg else". Makeing sure that only one buffer flushes to oLogger at a time prevents this.
I would probably use expression templates here.
The main idea is that it's bloody stupid to acquire the lock during the formatting phase, especially since there might be function calls during this formatting.
You need to use two different phases:
format the log
atomically post the log
This can be accomplished with expression templates:
First call to Logger::operator<< yields a LoggerBuffer that embeds a reference to Logger.
Subsequent calls are performed on LoggerBuffer which deals with all the formatting mess
Upon destruction of LoggerBuffer (at the end of the statement), it locks Logger, pass the formatted string, and unlocks (unless you've got a lock-free queue or something)
As I have to internationalize logs, I prefer things like :
oLogger << myAutosprintf(_("My wonderful %s ! I have %d apples"), name, nbApple);
It is way better for translation :) And it will solve your problem. _() is a shortcut for the translation stuff.
You can use gnu::autosprintf, boost.format (thanks to Jan Huec), or write your own.
my2c
NB: Edited after good remarks (was too fast, thank you for the comments). I have erased the wrong "first part" statement