1

I'm trying to perform two operations at once, a loop in the program's main method that prints out Tick from main and another loop in a class that prints out Tick from ConnectionManager.

This specific piece of code I'm running here is taken from one of the questions asked here.

The main.cpp file:

#include <Windows.h> // printf, Sleep
#include <thread> // thread

// Include Connection Manager
#include "ConnectionManager.h"

int main() {
    ConnectionManager _CM;

    while (1) {
        printf("Tick from main");
        Sleep(1500);
    }
}

ConnectionManager.h

#pragma once
class ConnectionManager
{
private:
    void LoopForData();
public:
    ConnectionManager();
};

ConnectionManager.cpp

#include "ConnectionManager.h"

#pragma once
#include <Windows.h>
#include <thread>

void ConnectionManager::LoopForData() {
    while (1) {
        printf("Tick from connection manager\n");
        Sleep(1500);
    }
}

ConnectionManager::ConnectionManager()
{
    std::thread tobj(&ConnectionManager::LoopForData, this);
}

The expected behaviour is that both loops run simultaneously, however the output I'm getting on the console is only from LoopForData function, and I get this error screen: https://i.stack.imgur.com/BCQRn.jpg

What could I be missing?

Brini
  • 47
  • 1
  • 5
  • because printf is not reentrant, you should have a look to https://stackoverflow.com/q/3941271/2477299 – P. PICARD May 20 '19 at 13:53
  • 2
    What happens, when `ConnectionManager()` function exits? – vahancho May 20 '19 at 14:00
  • @vahancho As the constructor method finishes executing the LoopForData() get called every 1500ms, the error shows up and the while loop in the main function doesn't get executed. – Brini May 20 '19 at 14:06
  • I believe printf has a lock which prevents simultaneous access across multiple threads. Only one thread can access printf at a time. – Irelia May 20 '19 at 14:06
  • Can you name a printf alternative? @Nina – Brini May 20 '19 at 14:07
  • 1
    For C++, you should prefer cout. – 2785528 May 20 '19 at 14:07
  • @Brini Also what happens to your thread object tobj when the constructor goes out of scope? Can you declare it as an instance variable? – Irelia May 20 '19 at 14:08
  • @Brini, ok, but what about `tobj` object? Don't you think, it's destroyed too? – vahancho May 20 '19 at 14:08
  • in addition use std::this_thread::sleep_for( ) instead of Sleep when you are anyway using – AndersK May 20 '19 at 14:13
  • @Nina - Remains untouched, it shouldn't get destroyed. I'll try having it as an instance variable. – Brini May 20 '19 at 14:13
  • @Brini I provided and answer. See if that works for you. – Irelia May 20 '19 at 14:17
  • Your issue does come from the fact that your thread object goes out of scope when the constructor terminates. This will call the destructor of your thread object which is joinable. If a destructor of a joinable thread is called it call std::terminate(). So you must detach it. en.cppreference.com/w/cpp/thread/thread/~thread – Minee May 20 '19 at 15:46

1 Answers1

3

This should work fine.

#include <iostream>
#include <thread>
#include <chrono>

//ConnectionManager.h
class ConnectionManager
{
private:
    std::thread tobj;
public:

    ConnectionManager();
    ~ConnectionManager();
private:
    void LoopForData();
};
//ConnectionManager.cpp
#include "ConnectionManager.h"

void ConnectionManager::LoopForData(){
    while (1) {
        std::cout << "Tick from connection manager" << std::endl;
        std::this_thread::sleep_for (std::chrono::milliseconds(1500));
    }
}
ConnectionManager::~ConnectionManager(){
    if(tobj.joinable()){
        tobj.join();
    }
}
ConnectionManager::ConnectionManager() : tobj(&ConnectionManager::LoopForData, this){

}
//main.cpp

#include "ConnectionManager.h"
int main() {
    ConnectionManager _CM;

    while (1) {
        std::cout << "Tick from main" << std::endl;
        std::this_thread::sleep_for (std::chrono::seconds(1));
    }
}

I think your main issue had to do with tobj going out of scope when the constructor exits. Also you can use the c++ standard sleep instead of Sleep from Windows.

Irelia
  • 3,407
  • 2
  • 10
  • 31