I need to lock stdout in my logging application to prevent string interleaving in multi-thread applications logging to stdout. Can't figure out how to use move constructor or std::move or sth else to move unique_lock to another object.
I created objects for setting configs and encapsulation and figured out how to lock stdout with static std::mutex to lock from these objects (called shards).
Something like this works for me:
l->log(1, "Test message 1");
While that is fine and could be implemented with templates and variable number of parameters I would like to approach more stream-like possibilities. I am looking for something like this:
*l << "Module id: " << 42 << "value: " << 42 << std::endl;
I dont want to force users to precompute string with concatenation and to_string(42) I just want to find a way to lock stdout.
My approach so far was to create operator << and another object locked stream, as was suggested in other answers. Things is I can't figure how to move mutex to another object. My code:
locked_stream& shard::operator<<(int num)
{
static std::mutex _out_mutex;
std::unique_lock<std::mutex> lock(_out_mutex);
//std::lock_guard<std::mutex> lock (_out_mutex);
std::cout << std::to_string(num) << "(s)";
locked_stream s;
return s;
}
After outputting input to std::cout I woould like to move lock into object stream.
In this case, I would be careful not to use static locks in functions, as you will get a different lock for each stream operator you create.
What you need is to lock some "output lock" when a stream is created, and unlock it when the stream is destroyed. You can piggie back on existing stream operations if you're just wrapping std::ostream. Here's a working implementation:
#include <mutex>
#include <iostream>
class locked_stream
{
static std::mutex s_out_mutex;
std::unique_lock<std::mutex> lock_;
std::ostream* stream_; // can't make this reference so we can move
public:
locked_stream(std::ostream& stream)
: lock_(s_out_mutex)
, stream_(&stream)
{ }
locked_stream(locked_stream&& other)
: lock_(std::move(other.lock_))
, stream_(other.stream_)
{
other.stream_ = nullptr;
}
friend locked_stream&& operator << (locked_stream&& s, std::ostream& (*arg)(std::ostream&))
{
(*s.stream_) << arg;
return std::move(s);
}
template <typename Arg>
friend locked_stream&& operator << (locked_stream&& s, Arg&& arg)
{
(*s.stream_) << std::forward<Arg>(arg);
return std::move(s);
}
};
std::mutex locked_stream::s_out_mutex{};
locked_stream locked_cout()
{
return locked_stream(std::cout);
}
int main (int argc, char * argv[])
{
locked_cout() << "hello world: " << 1 << 3.14 << std::endl;
return 0;
}
Here it is on ideone: https://ideone.com/HezJBD
Also, forgive me, but there will be a mix of spaces and tabs up there because of online editors being awkward.
Related
I have a structure defined in main.cpp file and i want that same structure with value to be visible in other cpp file.
I tried this and this is way out of understanding for me as a beginner. So i re-ask the initial question again but in a simple way.
main.cpp
#include<iostream>
extern struct abc
{
int a;
std::string bla_bla;
};
void display(abc (&)[2]);
int main(void)
{
abc put[2];
put[0] = {10,"Apple"};
put[1] = {20,"Ball"};
display(put);
}
other.cpp
#include <iostream>
extern abc;
void display(abc (&put)[2])
{
std::cout << put[0].a << '\t' << put[0].bla_bla << std::endl;
std::cout << put[1].a << '\t' << put[1].bla_bla << std::endl;
}
it shows error a storage class can only be specified for objects and functions
and i am using c++17
is there any way to make that one structure visible to every cpp?
thanks in advance
EDIT: I got it need to keep the struct in .h file
As far as I know, such use of static storage within lambda is legal. Essentially it counts number of entries into the closure:
#include <vector>
#include <iostream>
#include <algorithm>
#include <iterator>
typedef std::pair<int,int> mypair;
std::ostream &operator<< (std::ostream &os, mypair const &data) {
return os << "(" << data.first << ": " << data.second << ") ";
}
int main()
{
int n;
std::vector<mypair> v;
std::cin >> n;
v.reserve(n);
std::for_each(std::begin(v), std::end(v), [](mypair& x) {
static int i = 0;
std::cin >> x.second;
x.first = i++;
});
std::for_each(std::begin(v), std::end(v), [](mypair& x) {
std::cout << x;
});
return 0;
}
Let assume I have a container 'workers' of threads.
std::vector<std::thread> workers;
for (int i = 0; i < 5; i++) {
workers.push_back(std::thread([]()
{
std::cout << "thread #" << "start\n";
doLengthyOperation();
std::cout << "thread #" << "finish\n";
}));
}
Code in doLengthyOperation() is contained and self-sufficient operation, akin a new process creation.
Provided I join them using for_each and the stored variable in question must count number of active tasks, not just number of entries, what possible implementations for such counter are there, if I want to avoid to rely onto global variables to avoid someone else messing up with it and allowing automatic support for separate "flavors" of threads.
std::for_each(workers.begin(), workers.end(), [](std::thread &t)
{
t.join();
});
Surrounding scope would die quickly after finishing thread starts, may repeat , adding new threads to the container is possible, and that must be global variable, which I want to avoid. More of, the whole operation is a template
The best way to handle this is to capture an instance of std::atomic<int> which provides a thread safe counter. Depending on the lifetime of lambdas and the surrounding scope, you may wish to capture by reference or shared pointer.
To take your example:
std::vector<std::thread> workers;
auto counter = std::make_shared<std::atomic<int>>(0);
for (int i = 0; i < 5; i++) {
workers.push_back(std::thread([counter]()
{
std::cout << "thread #" << "start\n";
(*counter)++;
doLengthyOperation();
(*counter)--;
std::cout << "thread #" << "finish\n";
}));
}
Is there a way to start two (or more) C++11 threads and join() the first one that is finished?
An example scenario:
#include <iostream>
#include <thread>
using namespace std;
void prepare_item1() {std::cout << "Preparing 1" << std::endl;}
void consume_item1() {std::cout << "Consuming 1" << std::endl;}
void prepare_item2() {std::cout << "Preparing 2" << std::endl;}
void consume_item2() {std::cout << "Consuming 2" << std::endl;}
int main()
{
std::thread t1(prepare_item1);
std::thread t2(prepare_item2);
t1.join();
consume_item1();
t2.join();
consume_item2();
return 0;
}
I would have liked to do something like that instead:
int main()
{
std::thread t1(prepare_item1);
std::thread t2(prepare_item2);
finished_id=join_any(t1,t2)
if (finished_id==1)
{
consume_item1();
...
}
else if (finished_id==2)
{
consume_item2();
...
}
return 0;
}
Also, I would like the solution to be blocking, similar to the t.join() function.
Note: The real reason I need this is that I have two different blocking functions from which I receive commands, and whenever any of them is ready I would like to process the first command that arrives and continue to the next one when it is done. (sequential processing of commands from two parallel sources)
Thanks!
Here is a thread-safe multi-producer multi-consumer queue:
template<class T>
struct safe_queue {
std::deque<T> data;
std::atomic<bool> abort_flag = false;
std::mutex guard;
std::condition_variable signal;
template<class...Args>
void send( Args&&...args ) {
{
std::unique_lock<std::mutex> l(guard);
data.emplace_back(std::forward<Args>(args)...);
}
signal.notify_one();
}
void abort() {
abort_flag = true; // 1a
{ std::unique_lock<std::mutex>{guard}; }
signal.notify_all(); // 1b
}
std::experimental::optional<T> get() {
std::unique_lock<std::mutex> l(guard);
signal.wait( l, [this]()->bool{ // 2b
return !data.empty() || abort_flag.load(); // 2c
});
if (abort_flag.load()) return {};
T retval = std::move(data.front());
data.pop_front();
return retval;
}
};
have the threads shove data into the queue, and the main thread do a .get() on it.
If abort() is called, all waiting threads are woken up with an "empty" value from .get().
It uses std::experimental::optional, but you can replace that with something else (throw on abort? Whatever).
Code modified slightly from this other answer. Note that I think the other answer has some errors in it, which I corrected above, and attempts to solve a different problem.
The message you send could be the id of the thread that is ready to be waited upon, for example, or the work it has completed, or whatever.
this is a example from boost library.
int calculate_the_answer_to_life_the_universe_and_everything()
{
return 42;
}
boost::packaged_task<int> pt(calculate_the_answer_to_life_the_universe_and_everything);
boost:: future<int> fi=pt.get_future();
instead of boost::thread task(boost::move(pt)); to launch a task on the thread,
now I want to put the thread into shared_ptr vector and launch a task on the thread.
First i creat a vector.
std::vector<std::shared_ptr<boost::thread>> vecThreads;
And is this the right way to put a thread into vector?
vecThreads.push_back(std::make_shared<boost::thread>(boost::packaged_task<int> &pt));
thank you all for the attention!
Packaged tasks are just that. They don't "have" threads.
They just run on a thread. Any thread.
In fact, it's an anti-pattern to start a thread for each task. But, of course, you can. I'd suggest using a
boost::thead_group tg;
tg.create_thread(std::move(pt));
So you can depend on
tg.join_all();
to await all pending threads completion.
UPDATE
With shared pointers, here's an example:
Live On Coliru
#include <boost/thread.hpp>
#include <boost/make_shared.hpp>
#include <boost/bind.hpp>
using namespace boost;
int ltuae(int factor) {
this_thread::sleep_for(chrono::milliseconds(rand()%1000));
return factor*42;
}
int main() {
std::vector<unique_future<int> > futures;
std::vector<shared_ptr<thread> > threads;
for (int i=0; i<10; ++i)
{
packaged_task<int> pt(bind(ltuae, i));
futures.emplace_back(pt.get_future());
threads.emplace_back(make_shared<thread>(std::move(pt)));
}
for (auto& f : futures)
std::cout << "Return: " << f.get() << "\n";
for (auto& t: threads)
if (t->joinable())
t->join();
}
I'm trying to create a function that initializes all my mouse handlers for every OpenCV window in one place. The code works in the main loop, but not inside my function (Yes, I am passing by reference).
The problem seems to stem from passing a pointer to the string - when it comes out the other side it won't successfully dereference (*). What gives?
Here's a minimalist example of what I'm talking about (It sets the mouse handlers for two identical windows - one window works, the other window doesnt):
// mouse problem.cpp : Defines the entry point for the console application.
#include "stdafx.h"
#include "opencv2/core/core.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <opencv2/highgui/highgui.hpp>
#include <string.h>
#include <iostream> //for cout, cin
using namespace std;
using namespace cv;
void onMouse(int event, int x, int y, int flags, void* param){
string windowname = *((string*)param); //just recasting the void* we passed into the mousehandler to string
if(windowname.empty()){
cout << "ERROR.";
}else{
cout << "SUCCESS for window:" << windowname;
}
cout << " param: "<< param << " windowname: "<< windowname << "\n";
}
void initializer(const string& name){
namedWindow( name, CV_WINDOW_AUTOSIZE );
cout << " initializing mouse handler for " << name << " with string at address :" << &name << "\n";
setMouseCallback(name, onMouse, (void*)&name); //this line is exactly the same as the other setmousecallback line
}
int _tmain(int argc, _TCHAR* argv[]){
string name; Mat src; VideoCapture cap(0); cap >> src; // get a single frame from camera
//this works just fine
name = "frameA";
namedWindow( name, CV_WINDOW_AUTOSIZE );
cout << " initializing mouse handler for " << name << " with string at address :" << &name << "\n";
setMouseCallback(name, onMouse, (void*)&name);
//this fails even though it contains the same code and we pass by reference
initializer("frameB");
imshow("frameA",src); imshow("frameB",src); //display frame - mouseing over them triggers the OnMouse() event
while(true){ //loop forever
waitKey(30);
}
return 0;
}
And here is the result after I mouseover each window once.
What really KILLS me is that, as you can see in the picture, the address of the string is successfully recognized! And no errors on casting it to a string! But when I de-reference it, it says its empty!
Yes, I did try to avoid using Void*. Sadly, I cannot avoid the void. OpenCV requires a void to be the last argument of any mousehandler function :(
The problem has nothing to do with the casts. You are keeping a pointer to a temporary string object, and are trying to dereference that pointer after the object has gone out of scope.
The following:
initializer("frameB");
is equivalent to:
initializer(std::string("frameB"));
In other words, a temporary is created, and the function takes and keeps the address of that temporary. Since the temporary disappears at the end of the statement, you are left with a dangling pointer.