I have just written the source code below to dispatch events properly by using std::unique_ptr and std::deque, but I am not sure how accurate it is. I know it is not a good question but could someone evaluate it, is there any weird issue? In addition, I don't have any performance concern.
Thanks in advance.
- Volkan
#include <iostream>
#include <deque>
#include <mutex>
#include <memory>
#include <chrono>
#include <thread>
using namespace std;
class Event {
public:
Event(int a) : m_a(a)
{ }
void print()
{
cout << m_a << endl;
}
private:
int m_a;
};
class EventQueue {
public:
unique_ptr<Event> pop()
{
lock_guard<mutex> lock(m_Mutex);
unique_ptr<Event> p = nullptr;
if (!m_Queue.empty()) {
p = move(m_Queue.back());
m_Queue.pop_back();
}
return p;
}
void push(unique_ptr<Event> p)
{
lock_guard<mutex> lock(m_Mutex);
m_Queue.push_front(move(p));
}
private:
deque<unique_ptr<Event>> m_Queue;
mutex m_Mutex;
};
EventQueue evq;
void EventHandler()
{
while (true) {
unique_ptr<Event> p = evq.pop();
if (p)
p->print();
else
this_thread::sleep_for(chrono::seconds(10));
}
}
int main()
{
std::thread first (EventHandler);
while (true) {
int a;
cin >> a;
unique_ptr<Event> ev(new Event(a));
evq.push(move(ev));
}
first.join();
return 0;
}
Related
This program will crash cause the threads are tangled... One could be pushing while the other is trying to erase.
How can I make this work?
#include <thread>
#include <vector>
using namespace std;
vector<int> v_test;
void push()
{
v_test.push_back(0);
}
void erase()
{
if (v_test.size() > 0)
{
v_test.erase(v_test.begin());
}
}
int main()
{
thread w0(push);
thread w1(erase);
while (true) { Sleep(1000); }
return 0;
}
You need to synchronize the threads so they coordinate their access to the vector. For example, by using a std::mutex, eg:
#include <thread>
#include <mutex>
#include <vector>
using namespace std;
vector<int> v_test;
mutex m_sync;
void push()
{
lock_guard<mutex> lock(m_sync);
v_test.push_back(0);
}
void erase()
{
lock_guard<mutex> lock(m_sync);
if (v_test.size() > 0)
{
v_test.erase(v_test.begin());
}
}
int main()
{
thread w0(push);
thread w1(erase);
while(true) {Sleep(1000);}
return 0;
}
I am getting attempting to reference a deleted function error which I feel is because of inter dependency between classes.
Location.h
#ifndef A_LOCATION_H
#define A_LOCATION_H
struct location {
double lat;
double lon;
double alt;
};
#endif //A_LOCATION_H
P.h
#ifndef A_P_H
#define A_P_H
#include <vector>
#include <mutex>
#include <memory>
#include "Location.h"
class C;
class P {
std::vector<std::shared_ptr<C>> C_List;
struct location loc {};
public:
P() = default;
~P() = default;
std::mutex mut;
void add_child(const std::string& th_name);
void del();
void set_data(double lat, double lon, double alt);
struct location get_data();
};
#endif //A_P_H
P.cpp
#include <iostream>
#include "C.h"
#include "P.h"
void P::add_child(const std::string& th_name) {
std::lock_guard<std::mutex> lg(mut);
auto& ref = C_List.emplace_back(std::make_shared<C>());
ref->set_name(th_name);
ref->set_P(this);
ref->start();
}
void P::del() {
std::lock_guard<std::mutex> lg(mut);
for (auto& c : C_List)
c->terminate = true;
for (auto& c : C_List)
c->wait();
C_List.clear();
}
struct location P::get_data() {
std::lock_guard<std::mutex> lg(mut);
return loc;
}
void P::set_data(double lat, double lon, double alt) {
std::lock_guard<std::mutex> lg(mut);
loc.lat = lat;
loc.lon = lon;
loc.alt = alt;
}
C.h
#ifndef A_C_H
#define A_C_H
#include <string>
#include <thread>
#include <chrono>
#include <atomic>
class P;
class C {
P *p {};
std::string name {};
std::thread th {};
struct location loc {};
void run();
public:
C() = default;
~C() = default;
void set_P(P* p);
void set_name(const std::string& name);
void start();
void wait();
std::atomic<bool> terminate {false};
};
#endif //A_C_H
C.cpp
#include <iostream>
#include "P.h"
#include "C.h"
void C::run() {
while (!terminate) {
std::cout << name << std::endl;
{
auto loc = p->get_data();
// perform calculation based on P's object location, and it's current location
}
using namespace std::chrono_literals;
std::this_thread::sleep_for(1s);
}
}
void C::set_P(P* p) {
this->p = p;
}
void C::set_name(const std::string& name) {
this->name = name;
}
void C::start() {
th = std::thread(&C::run, this);
}
void C::wait() {
th.join();
}
Main.cpp
#include <iostream>
#include "P.h"
int main() {
P p = P();
p.add_child("C1");
p.add_child("C2");
p.add_child("C3");
char input;
std::cin >> input;
p.del();
}
Also there exists a kind of deadlock that will happen when del function of P's object gets called. I am not getting how to resolve this issue?
This is the short description of the error I'm getting
C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.26.28801\include\xmemory(671): error C2280: 'C::C(const C &)': attempting to reference a deleted function
C:\Users\HARSHA\Desktop\LC\2022\A\C.h(33): note: compiler has generated 'C::C' here
C:\Users\HARSHA\Desktop\LC\2022\A\C.h(33): note: 'C::C(const C &)': function was implicitly deleted because a data member invokes a deleted or inaccessible function 'std::thread::thread(const std::thread &)'
C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.26.28801\include\thread(93): note: 'std::thread::thread(const std::thread &)': function was explicitly deleted
std::thread, std::atomic, std::mutex types are not copyable, so the compiler cannot produce the default copy-constructors and copy-asignments.
You must write your own copy constructors for C and P classes.
P(P const& arg){ ... do stuff ... }
I have this class:
boer.h
#pragma once
#include <functional>
#include <iostream>
class boer
{
private:
std::function<void(int id_)> someFun;
public:
boer();
~boer();
void setSomeFun(std::function<void(int id_)> someFun_);
void getSomeFun();
};
boer.cpp
#include "boer.h"
boer::boer() { }
boer::~boer() { }
void boer::setSomeFun(std::function<void(int id_)> someFun_)
{
someFun = someFun_;
}
void boer::getSomeFun()
{
someFun(12345);
}
And this class:
aircraft.h
#pragma once
#include <functional>
#include <iostream>
#include "boer.h"
class aircraft
{
private:
boer Boer;
public:
aircraft();
~aircraft();
void source_forSomeFun(int id_);
};
aircraft.cpp
#include "aircraft.h"
aircraft::aircraft() { }
aircraft::~aircraft() { }
void aircraft::source_forSomeFun(int lol_)
{
std::cout << "AMAZING!!!" << std::endl;
}
And I need to connect void source_forSomeFun(int id_); in aicraft with std::function<void(int id_)> someFun; in boer. How can I do this? Maybe there is another way, but i think this method is the most preferable.
int main()
{
aircraft Aircraft;
boer Boer;
Boer.setSomeFun(???); // here
Boer.getSomeFun();
int i;
std::cin >> i;
return 0;
}
Boer.setSomeFun([&](int v){aircraft.source_forSomeFun(v);});
Use a lambda.
I am trying to use boost::function with instance methods using the following example
class someclass
{
public:
int DoIt(float f, std::string s1)
{
return 0;
}
int test(boost::function<int(float, std::string)> funct)
{
//Funct should be pointing to DoIt method here
funct(12,"SomeStringToPass");
}
void caller()
{
test(DoIt); //Error : 'someclass::DoIt': function call missing argument list; use '&someclass::DoIt' to create a pointer to member
}
};
Any suggestion on how I could resolve this issue ?
You should use boost::bind:
#include <boost/function.hpp>
#include <boost/bind.hpp>
#include <string>
#include <iostream>
using namespace std;
class someclass
{
public:
int DoIt(float f, std::string s1)
{
return 0;
}
int test(boost::function<int(float, std::string)> funct)
{
return funct(5.0, "hello");
}
void caller()
{
cout << test(boost::bind(&someclass::DoIt, this, _1, _2)) << endl;
}
};
int main() {
someclass s;
s.caller();
}
This was my original code
#include "stdafx.h"
#include <string>
#include <list>
#include <algorithm>
using namespace std;
class testing
{
public:
int value;
testing(int v)
{
value = v;
}
int getval()
{
return(value);
}
};
void func(testing& ob)
{
printf("The value is %d\n", ob.value);
}
int _tmain(int argc, _TCHAR* argv[])
{
std::list<testing> testvar[3];
testing t1(0);
testing t2(1);
testing t3(3);
testvar[0].push_back(t1);
testvar[0].push_back(t2);
testvar[0].push_back(t3);
std::for_each(testvar[0].begin(), testvar[0].end(), func);
printf("Reached End");
getchar();
return 0;
}
I modified it to make func a member function and got weird compile errors, I searched online and someone had told use bind1st, bind2nd
#include "stdafx.h"
#include <string>
#include <list>
#include <algorithm>
using namespace std;
class testing
{
public:
int value;
testing(int v)
{
value = v;
}
int getval()
{
return(value);
}
};
class testing2
{
public:
std::list<testing> testvar[3];
void func(testing& ob)
{
printf("The value is %d\n", ob.value);
}
void driver()
{
std::for_each(testvar[0].begin(), testvar[0].end(), func);
}
};
int _tmain(int argc, _TCHAR* argv[])
{
testing2 testob;
testob.driver();
printf("Reached End");
getchar();
return 0;
}
So I modified the driver function to this
void driver()
{
std::for_each(testvar[0].begin(), testvar[0].end(), std::bind1st(std::mem_fun(&testing2::func), this));
}
I still get some weird compile erros, could someone please expain why we need to call a member function is such weird way..? and how does bind1st help..?
Use std::bind
std::for_each(testvar[0].begin(), testvar[0].end(), std::bind(&testing2::func, this, std::placeholders::_1));
Or use std::bind/lambdas
std::for_each(testvar[0].begin(), testvar[0].end(), [this](testing& ob) { func(ob); });
Full:
#include <string>
#include <list>
#include <algorithm>
using namespace std;
struct testing {
int value;
testing(int v) { value = v; }
int getval() { return(value); }
};
struct testing2 {
std::list<testing> testvar[3];
void func(testing& ob) {
printf("The value is %d\n", ob.value);
}
void driver() {
auto f = std::bind(&testing2::func, this, std::placeholders::_1);
std::for_each(testvar[0].begin(), testvar[0].end(), f);
std::for_each(testvar[0].begin(), testvar[0].end(), [this](testing& ob) { func(ob); });
}
};
int main() {
testing2 testob;
testob.driver();
printf("Reached End");
}
You can also use std::mem_fn for cleaner syntax like this:
std::for_each(testvar[0].begin(), testvar[0].end(), std::mem_fn(&testing::func));
Complete code:
#include <stdio.h>
#include <bits/stdc++.h>
class testing
{
public:
testing(int v) : value(v) {}
int getval() {
return(value);
}
void func()
{
printf("The value is %d\n", value);
}
private:
int value;
};
int main() {
std::list<testing> testvar[3];
testing t1(0);
testing t2(1);
testing t3(3);
testvar[0].push_back(t1);
testvar[0].push_back(t2);
testvar[0].push_back(t3);
std::for_each(testvar[0].begin(), testvar[0].end(), std::mem_fn(&testing::func));
return 0;
}