For example, if I have a bool value v, I want a reference to !v that can change when v changes. An example use will be:
class A {
bool& isOpen;
A(bool& value): isOpen(value) {}
void f() {
if (isOpen) {
doSomething();
}
}
};
class B {
bool& isClosed;
B(bool& value): isClosed(value) {}
void g() {
if (isClosed) {
doSomething();
}
}
};
int main() {
bool isOpen = true;
A a(isOpen);
B b(negattive_reference_of(isOpen));
a.f(); // doSomething()
b.g(); // do nothing
isOpen = false;
a.f(); // do nothing
b.g(); // doSomething()
}
Is there anyway in C++ to acheive a similar effect?
Under the hood reference is equivalent to a constant pointer to some variable (compiler just gives you a syntax sugar of how to work with such pointers so that they are always initialized).
So you wan't to have the same variable and two different pointers to it, one of which will dereference to true and the other to false. That is obviously impossible.
The OOP -way to do it would be to pass not reference to boolean but some interface to your classes and use implementation that uses same boolean variable:
class IIsOpenProvider
{
public:
virtual ~IIsOpenProvider() = 0;
virtual bool GetOpenValue() = 0;
};
class IIsClosedProvider
{
public:
virtual ~IIsClosedProvider() = 0;
virtual bool GetClosedValue() = 0;
};
class ValueProvider : public IIsOpenProvider, public IIsClosedProvider
{
public:
bool GetOpenValue() override { return isOpen; }
bool GetClosedValue() override { return !isOpen; }
private:
bool isOpen;
};
class A {
IIsOpenProvider& isOpen;
A(IIsOpenProvider& value): isOpen(value) {}
void f() {
if (isOpen.GetOpenValue()) {
doSomething();
}
}
};
class B {
IIsClosedProvider& isClosed;
B(IIsClosedProvider& value): isClosed(value) {}
void g() {
if (IIsClosedProvider.GetClosedValue()) {
doSomething();
}
}
};
// usage
ValueProvider val;
A a(val);
B b(val);
Related
I need to create a queue of different class objects (These classes are not related). I found a solution as follows:
Create a base class and use polymorphism.
Here is how I implemented it,
class Task {
public:
virtual void operator()() {
printf("should not be called\n");
}
};
class TaskRPCB : public Task {
private:
int x;
// other varibles
std::function<void(int)> func;
public:
TaskRPCB(std::function<void(int)>&f , int x) {
this->func = f;
this->x = x;
}
void operator()() {
printf("TaskRPCB function is executing...\n");
func(x);
}
};
class TaskECB : public Task {
private:
// other varibles
std::function<void(void)> func;
public:
TaskECB(std::function<void(void)>&f) : func(f) {}
void operator()() {
printf("TaskECB function is executing...\n");
func();
}
};
void F1() { // dummy function for example
cout <<"no x"<<endl;
}
void F2(int x) { // dummy function for example
cout <<"x : "<<x<<endl;
}
int main() {
queue<unique_ptr<Task>> Q;
function<void()> func1 = F1;
function<void(int)> func2 = F2;
TaskECB task1(func1);
TaskRPCB task2(func2,4);
Q.emplace(new TaskECB(func1));
Q.emplace(new TaskRPCB(func2,4));
(*Q.front())();
Q.pop();
(*Q.front())();
Q.pop();
}
The problem is, I can not push the objects directly as shown above. I have to create an object of an inherited class and pass it to another function to do the push action. It is because ( in my case ) the queue is a part of a thread-safe queue and it has separate Push() method.
template<typename T>
void threadSafeQueue<T>::Push(T newData) { /* TODO: size check before pushing */
std::shared_ptr<T> data(std::make_shared<T>(std::move(newData)));
/* construct the object before lock*/
std::lock_guard<std::mutex> lk(mut);
taskQueue.push(data);
dataCond.notify_one();
}
Earlier I did not have multiple tasks to execute ( or push ) into the queue, therefore
threadSafeQueue<TaskRPCB> workQ declaration worked fine for me.
Creating a base Task class like above is not working because of object slicing
Can you suggest other ways to store objects in the queue ( so that I can still use the lock guarded Push() method )
Thanks !
update :
is the correct way of using variant?
typedef std::variant<TaskECB, TaskRPCB> myType;
int main() {
queue<unique_ptr<myType>> Q;
function<void()> func1 = F1;
function<void(int)> func2 = F2;
TaskECB task1(func1);
TaskRPCB task2(func2,4);
myType x = task1;
Q.push(make_unique<myType>(x));
x = task2;
Q.push(make_unique<myType>(x));
if((*Q.front()).index() == 0) {
auto f1 = get<TaskECB>(*Q.front());
f1();
Q.pop();
}
if((*Q.front()).index() == 1) {
auto f1 = get<TaskRPCB>(*Q.front());
f1();
Q.pop();
}
}
update2:
using myVariantType = std::variant<TaskECB, TaskRPCB>;
struct VisitPackage {
void operator()(TaskECB & task) {
task();
}
void operator()(TaskRPCB& task) {
task();
}
};
int main() {
queue<myVariantType> Q;
function<void()> func1 = F1;
function<void(int)> func2 = F2;
TaskECB task1(func1);
TaskRPCB task2(func2,4);
Q.emplace(task1);
Q.emplace(task2);
std::visit(VisitPackage(), Q.front());
Q.pop();
std::visit(VisitPackage(), Q.front());
Q.pop();
}
I have an assignment of creating a Circuit Sim and I'm having issues with NotGate class when I try to use it.
Components is an abstract class.
class Component
{
public:
virtual bool getOutput() = 0;
virtual void prettyPrint(string padding) = 0;
virtual void linearPrint() = 0;
};
Then I have Pin and NotGate, they inherit through dependency of Components.
class Pin {
private:
bool value;
string label;
public:
Pin::Pin(string theLabel) {
label = theLabel;
}
bool Pin::getOutput() {
return value;
}
void Pin::setValue(bool newVal) {
this->value = newVal;
}
};
class NotGate {
private:
shared_ptr<Component> input;
public:
NotGate::NotGate() {
input = make_shared<Component>();
}
bool NotGate::getOutput() {
if (input == 0) {
return true;
} else {
return false;
}
}
void NotGate::setInput(shared_ptr<Component> in) {
this->input = in;
}
};
I created a Pin "c" and a notGate "n1", I want to have "c" as the input for "n1". When I try to do it with the command:
n1->setInput(c);
It tells me that: No viable conversion from 'shared_ptr<Pin>' to 'shared_ptr<Component>s'
I tried creating a new shated_ptr of Components and a bunch of different things that didn't work.
The error message from the compiler is clear. If you want to be able to use a shared_ptr<Pin> when a shared_ptr<Component> is expected, you should make Pin a sub-class of Component. From an abstraction standpoint, it makes sense to me that Pin be a sub-class of Component.
class Pin : public Component
{
...
};
I have a template in C++ like below
template <class TYPE>
bool writeRecordForSet(std::vector<TYPE*> entityPtr){
if(entityPtr.size()== 0) return true;
...
}
I want to use the same template for std::shared_ptr; i.e. I have std::vector<std::shared_ptr>;
How can I use the same template?
I may have misunderstood the question but can't you just remove the * from the tempaltised function? Something like:
class Base {};
template <class Type>
bool writeRecordForSet(std::vector<Type> entityPtr){
if(entityPtr.size()== 0) return true;
//...
}
int main() {
std::vector<std::shared_ptr<Base>> vec_shared;
std::vector<int*> vec_intp;
std::vector<std::unique_ptr<Base>> vec_unique_ptr;
writeRecordForSet(vec_shared);
writeRecordForSet(vec_intp);
writeRecordForSet(vec_unique_ptr);
}
This way you could use both vector<type*> as well as vector<shared_ptr> as arguments to the function. (Or any other pointer type like unique_ptr)
This one does not work
class Base {
public:
int getVal() { return 0; }
};
template <class Type>
bool writeRecordForSet(std::vector<Type> entityPtr) {
if (entityPtr.size() == 0) return true;
//...
for (auto iter = entityPtr.begin(); iter != entityPtr.end(); iter++) {
Type enPtr = *iter;
int myval = enPtr->getVal();
}
return true;
}
int main() {
std::vector<std::shared_ptr<Base>> vec_shared;
std::vector<int*> vec_intp;
std::vector<std::unique_ptr<Base>> vec_unique_ptr;
writeRecordForSet(vec_shared);
writeRecordForSet(vec_intp);
writeRecordForSet(vec_unique_ptr);
}
hope you had all had nice holidays.
This questions is related to my earlier question: std::condition_variable - Wait for several threads to notify observer
I'm trying to implement a threadpool based on my own mutable thread implementation below:
class MutableThread
{
private:
std::thread m_Thread;
std::function<void()> m_Function;
bool m_bRun;
std::mutex m_LockMutex;
std::mutex m_WaitMutex;
std::condition_variable m_CV;
IAsyncTemplateObserver<MutableThread>* m_Observer = nullptr;
private:
void Execute()
{
while (m_bRun)
{
{
std::unique_lock<std::mutex> wait(m_WaitMutex);
m_CV.wait(wait);
}
std::lock_guard<std::mutex> lock(m_LockMutex);
if (m_bRun && m_Function)
{
m_Function();
m_Function = std::function<void()>();
if (m_Observer != nullptr)
{
m_Observer->Signal(this);
}
}
}
}
public:
HDEBUGNAME(TEXT("MutableThread"));
MutableThread(const MutableThread& thread) = delete;
MutableThread(IAsyncTemplateObserver<MutableThread>* _Observer)
{
m_Observer = _Observer;
m_bRun = true;
m_Thread = std::thread(&MutableThread::Execute, this);
}
MutableThread()
{
m_Observer = nullptr;
m_bRun = true;
m_Thread = std::thread(&MutableThread::Execute, this);
}
~MutableThread()
{
m_bRun = false;
m_CV.notify_one();
try
{
if (m_Thread.joinable())
m_Thread.join();
}
catch (std::system_error& ex)
{
HWARNINGD(TEXT("%s"), ex.what());
}
}
inline bool Start(const std::function<void()>& f)
{
std::lock_guard<std::mutex> lock(m_LockMutex);
if (m_Function != nullptr)
return false;
m_Function = f;
m_CV.notify_one();
return true;
}
The IAsyncTemplateObserver simply derives from my IAsyncObserver class posted in the earlier question and adds a virtual function:
template <typename T>
class IAsyncTemplateObserver : public IAsyncObserver
{
public:
virtual void Signal(T* _Obj) = 0;
};
What I want to do is, signal the ThreadPool that the function has finished execution and a new task is assigned to the mutable thread:
class MutableThread;
struct Task
{
std::function<void()> m_Function;
uint32_t m_uPriority;
Task(const std::function<void()>& _Function, uint32_t _uPriority)
{
m_Function = _Function;
m_uPriority = _uPriority;
}
};
inline bool operator<(const Task& lhs, const Task& rhs)
{
return lhs.m_uPriority < rhs.m_uPriority;
}
class ThreadPool : public IAsyncTemplateObserver<MutableThread>
{
private:
std::list<MutableThread* > m_FreeThreads;
std::list<MutableThread* > m_UsedThreads;
std::set<Task> m_Tasks;
std::mutex m_LockMutex;
public:
ThreadPool()
{
//Grow(std::thread::hardware_concurrency() - 1);
}
ThreadPool(size_t n)
{
Grow(n);
}
~ThreadPool()
{
//std::lock_guard<std::mutex> lock(m_Mutex);
for (MutableThread* pUsed : m_UsedThreads)
{
HSAFE_DELETE(pUsed);
}
for (MutableThread* pFree : m_FreeThreads)
{
HSAFE_DELETE(pFree);
}
}
inline void Grow(size_t n)
{
std::lock_guard<std::mutex> lock(m_LockMutex);
for (size_t i = 0; i < n; i++)
{
m_FreeThreads.push_back(new MutableThread(this));
}
}
inline void AddTask(const Task& _Task)
{
{
std::lock_guard<std::mutex> lock(m_LockMutex);
m_Tasks.insert(_Task);
}
AssignThreads();
}
virtual void Signal(MutableThread* _pThread)
{
{
std::lock_guard<std::mutex> lock(m_LockMutex);
m_UsedThreads.remove(_pThread);
m_FreeThreads.push_back(_pThread);
}
AssignThreads();
NotifyOne();
}
inline void WaitForAllThreads()
{
bool bWait = true;
do
{
{
//check if we have to wait
std::lock_guard<std::mutex> lock(m_LockMutex);
bWait = !m_UsedThreads.empty() || !m_Tasks.empty();
}
if (bWait)
{
std::unique_lock<std::mutex> wait(m_ObserverMutex);
m_ObserverCV.wait(wait);
}
} while (bWait);
}
private:
inline void AssignThreads()
{
std::lock_guard<std::mutex> lock(m_LockMutex);
if (m_FreeThreads.empty() || m_Tasks.empty())
return;
//Get free thread
MutableThread* pThread = m_FreeThreads.back();
m_FreeThreads.pop_back();
//park thread in used list
m_UsedThreads.push_back(pThread);
//get task with highest priority
std::set<Task>::iterator it = m_Tasks.end();
--it; //last entry has highest priority
//start the task
pThread->Start(it->m_Function);
//remove the task from the list
m_Tasks.erase(it);
}
The AddTask function is called several times by the same thread, but when a mutable thread signals the threadpool (via m_Observer->Signal(this) ) the application freezes at the lock_guard of the AssignThreads() function. Now the strange thing is unlike a normal deadlock, all callstack-views in Visual Studio are empty as soon is I try to step over the line with the lock_guard.
Can anyone explain this behaviour? Is there any major design flaw or just a simple mix up?
Thanks for your help!
Greetings,
Fabian
Edit: I've added a minimal visual studio solution that reproduces the problem: ThreadPoolTest.zip
Thanks to a friend, I was able to fix the problem by moving the call m_Observer->Signal(this) outside of the lock_guard scope in the MutableThread::Execute() function. Secondly I removed the lock_guard in the AssignThreads() function and moved its call into the scope of the lock_guard in the Signal()/AddTask function. Not really related but still a flaw: all condition_variables.wait() calls are now in a while(m_bNotified == false) loop.
In g++ I could do this:
struct s
{
int a, b;
};
void MyFunction(s) { }
int main()
{
MyFunction((s) { 0, 0 });
return 0;
}
In Visual Studio however, it doesn't work. is there any way to make it work or some alternative syntax without making a variable and initializing it (and without adding a constructor to the struct as it will make it non-aggregate and it wouldn't be able to initialize in aggregates)?
My C is a bit rusty, but didn't you have to use struct s unless you typedef it? Something like this:
struct s
{
int a, b;
};
void MyFunction(struct s) { }
int main()
{
MyFunction((struct s) { 0, 0 });
return 0;
}
or
typedef struct s
{
int a, b;
} s_t;
void MyFunction(s_t) { }
int main()
{
MyFunction((s_t) { 0, 0 });
return 0;
}