I have a small solution in visual studio 2012. The solution consists of two projects (Scanner and TestApp), Scanner is a dll and TestApp is a small application using the dll.
I would like a function in the dll to run in a thread and to report its result back via a queue to the TestApp.
To test this I wrote a minimal application, but depending on how I launch the thread I get different results and I would like to understand why.
The Scanner.h file looks like this:
#pragma once
#include <iostream>
#include <string>
#include <stdint.h>
#include <atomic>
#include <future>
#include <thread>
#include "version.h"
#include "threadsafe_queue.h"
#include "capture_data.h"
#include "process_data.h"
#ifdef SCANNER_EXPORTS
#define SCANNER_API __declspec(dllexport)
#else
#define SCANNER_API __declspec(dllimport)
#endif
class Scanner
{
public:
static SCANNER_API void run();
static SCANNER_API void stop();
};
Scanner.cpp:
#include "stdafx.h"
#include "Scanner.h"
std::vector<std::future<int>> my_futures;
void Scanner::run()
{
CaptureData capture_data(1234);
auto t = std::async(std::launch::async, &CaptureData::get_data, capture_data);
my_futures.push_back(std::move(t));
}
void Scanner::stop()
{
for(int n=0; n<my_futures.size(); n++) {
auto e = std::move(my_futures.back());
e.get();
my_futures.pop_back();
}
}
The class CaptureData is defined in capture_data.h and capture_data.cpp.
capture_data.h:
#pragma once
#include <atomic>
#include <thread>
#include "iq_data.h"
#include "threadsafe_queue.h"
class CaptureData
{
public:
CaptureData(double freq_start);
void configure();
void get_data();
private:
double m_test;
};
capture_data.cpp
#include "stdafx.h"
#include "capture_data.h"
#include "Scanner.h"
ThreadsafeQueue<int> g_queue_1;
SCANNER_API ThreadsafeQueue<int> g_queue_2;
CaptureData::CaptureData(double test)
: m_test(test) {}
void CaptureData::get_data()
{
cout << "1: " << m_test << std::endl;
Sleep(5000);
cout << "2: " << m_test << std::endl;
g_queue_2.push(3);
cout << "Capture has now pushed data" << std::endl;
}
And finally the TestApp.cpp:
#include "stdafx.h"
#include "tchar.h"
#include <stdint.h>
#include <string>
#include "Scanner.h"
SCANNER_API extern ThreadsafeQueue<int> g_queue_2;
int _tmain(int argc, _TCHAR* argv[])
{
Scanner scanner;
scanner.run();
cout << "TestApp waiting for data..." << std::endl;
int data;
g_queue_2.wait_and_pop(data);
cout << "TestApp got data: " << data << std::endl;
scanner.stop();
return 0;
}
In Scanner.cpp I have tried to launch the thread in two different ways, the first way:
auto t = std::async(std::launch::async, &CaptureData::get_data, capture_data);
Second way is with a reference to the object "capture_data":
auto t = std::async(std::launch::async, &CaptureData::get_data, &capture_data);
The first way seems to work as I intended the application to work and I get the following printouts in my terminal:
TestApp waiting for data...
1: 1234
2: 1234
Capture has now pushed data
TestApp got data: 3
Press any key to continue...
If I use the second way I get:
TestApp waiting for data...
1: 6.95166e-310
2: 6.95166e-310
Capture has now pushed data
TestApp got data: 3
Press any key to continue...
So, what I do not understand is why the variable "m_test" get messed up in the second case.
I would very much appreciate if anyone could shed a light on this.
/M
In the following code:
void Scanner::run()
{
CaptureData capture_data(1234);
auto t = std::async(std::launch::async, &CaptureData::get_data, capture_data);
my_futures.push_back(std::move(t));
}
capture_data is a local variable that goes out of scope and gets destroyed when the function returns. If you pass a pointer to that variable into async that pointer becomes a dangling pointer causing undefined behaviour. That does not happen if you pass it by value, as you do in the above snippet.
You are trying to pass a pointer to a stack allocated object. This object is destructed at the end of the Scanner::run() method. Thus, the pointer is now pointing to invalid memory when the async function runs.
The first method works, because the capture_data variable is move constructed when it is passed to the function, therefore it still retains it's structure.
I recommend using lambda functions than passing the raw member function:
void Scanner::run()
{
CaptureData capture_data(1234);
auto t = std::async(std::launch::async, [capture=std::move(capture_data)]() { capture.get_data(); });
my_futures.emplace_back(t);
}
Even better is to construct the object inside the lambda function:
void Scanner::run()
{
auto t = std::async(std::launch::async, []() {
CaptureData capture_data(1234);
capture_data.get_data();
});
my_futures.emplace_back(t);
}
Related
I have the following code:
main.cpp
#include "Test.h"
int main() {
Create();
}
Test.h
#pragma once
#include <iostream>
#include "Function.h"
class Test {
public:
Test();
};
extern Test* g_pTest;
inline void Create() {
g_pTest = new Test;
std::cout << "On Test.h: " << std::endl;
PrintAddr();
}
Test.cpp
#include "Test.h"
Test* g_pTest = nullptr;
Test::Test() {
std::cout << "On Test.cpp:" << std::endl;
PrintAddr();
}
Function.h
#pragma once
void PrintAddr();
Function.cpp
#include "Function.h"
#include "Test.h"
void PrintAddr() {
std::cout << "g_pTest address is " << g_pTest << std::endl;
}
When I run it, I get the following output:
On Test.cpp:
g_pTest address is 0000000000000000
On Test.h:
g_pTest address is 000002008A5EAE40
I thought that a extern variable was supposed to have the same value anywhere on the code, so why doesn't it? I've tried to run the same code, but instead of the Test class, I just have a function:
Test.h
#pragma once
#include <iostream>
#include "Function.h"
void Test();
extern int* g_pTest;
inline void Create() {
g_pTest = new int;
Test();
std::cout << "On Test.h: " << std::endl;
PrintAddr();
}
Test.cpp
#include "Test.h"
int* g_pTest = nullptr;
void Test() {
std::cout << "On Test.cpp:" << std::endl;
PrintAddr();
}
And it somehow works if it is done this way, I don't understand the logic...
What am I doing wrong here? What can I do in order to use a class and have access to the same extern variable in any code file?
int main() {
Create();
}
main calls Create(), which does this:
g_pTest = new Test;
Test gets newed first. g_pTest gets assigned after Test's constructor finishes and the object is constructed.
Test's constructor calls PrintAddr which prints the value of g_pTest because it is still nullptr:
Test* g_pTest = nullptr;
This remains the case until after Test finishes constructing.
Only after the constructor wraps up its business the pointer to the new object gets assigned to g_pTest, and then the 2nd call to printAddr (from Create) prints the value of the pointer, which is now pointing to the new object.
I am currently learning C++ and found that there are at least two ways using variables defined in other files. However I do not understand really, when to use what method.
For example:
I have writte in "h1.h":
extern int k;
and "a2.cpp" writes:
#include "a2.h"
#include "h1.h"
int k = 42;
int k2 = 43;
Then I can reference k in my main.cpp with:
#include "main.h"
#include "a1.h"
#include "h1.h"
#include <iostream>
Main::Main() {}
int main() {
std::cout << k << std::endl;
}
However if I want to use k2 in main.cpp I could simply write a getter/setter method, thereby I would avoid having to use extern in a common included header file.
I would like to know: What are other ways to access variables from other files? When do you use which method (and why )?
You expose k as a function, or not at all, not as a variable.
"h1.h":
int k();
void k2(int &);
"h1.cpp":
int k() { return 42; }
void k2(int & value) { value = 43; }
"main.cpp"
#include "h1.h"
#include <iostream>
int main () {
std::cout << k() << std::endl;
int any_name;
k2(any_name);
std::cout << any_name << std::endl;
}
I am trying to create a input handler using multi threading with the SDL2 Library; however, when I try to put a thread in a class it won't compile and gives me this error...
error: cannot convert 'inputHandlerClass::getInput' from type 'int (inputHandlerClass::)(void*)' to type 'SDL_ThreadFunction {aka int (*)(void*)}'
I'm pretty sure that its the way I am passing the function name (fn) to the SDL_CreateThread function.
This is the source.cpp file
#include <iostream>
#include <SDL.h>
#include <SDL_image.h>
#include <SDL_ttf.h>
#include <SDL_thread.h>
#include <SDL_mixer.h>
#include "..\include\gameClass.hpp"
#include "..\include\inputHandlerClass.hpp"
int main(int argc, char *argv[]){
inputHandlerClass inputHandler;
inputHandler.startThread();
std::cout << "hello world";
return 0;
}
This is the inputHandlerClass.hpp
#include <SDL_thread.h>
#include <iostream>
class inputHandlerClass{
private:
SDL_Thread *thread;
int threadReturnValue;
public:
inputHandlerClass();
int getInput(void *ptr);
void startThread();
};
//Default Constructor
inputHandlerClass::inputHandlerClass(){
this->thread = SDL_CreateThread(getInput, "inputThread", this);
}
int inputHandlerClass::getInput(void *ptr){
int cnt;
for(cnt= 0; cnt < 10; ++cnt){
std::cout << "counter: " << cnt << std::endl;
SDL_Delay(50);
}
return cnt;
}
void inputHandlerClass::startThread(){
SDL_WaitThread(this->thread, &this->threadReturnValue);
}
SDL_CreateThread expects a pointer to a regular function with int(void *ptr) signature as first parameter, however you are providing a non-static member function (not even a pointer because member functions aren't getting implicitly converted to a pointer). You should redeclare getInput as static. this pointer will be available as ptr.
I think there are many solutions outside for my problem but I dont get it, I'm kind of new to structs - so please help me..
OK my problem is I declare a struct in my header.h file and there is a function also inside that puts a string in one of the struct values and in the header file I can also output the string, but I want that struct and that !!value!! in a different cpp file where I can access to that value - so here is my code
header.h
#include <iostream>
#include <string.h>
#ifndef FUNCTIONS_H
#define FUNCTIONS_H
struct FUNCTIONS
{
std::string f_name;
};
//extern FUNCTIONS globalStruct;
//put in struct variable
void put2struct()
{
struct FUNCTIONS struct1;
struct1.f_name = "FUNCTION";
std::cout << "Functionname: " << struct1.f_name << std::endl;
}
#endif //FUNCTIONS_H
and main.cpp
#include <iostream>
#include <string.h>
#include "header.h"
using namespace std;
int main(int argc, char const *argv[])
{
struct FUNCTIONS globalStruct;
put2struct();
//FUNCTIONS struct1;
std::cout << "Functionname2: " << globalStruct.f_name << std::endl;
return 0;
}
I hope somebody can help me I really dont get it how to do this :/
There is no way to directly access a local variable outside the block where it is defined. Because struct1 is an automatic variable, it is destroyed when put2struct returns, and no longer exists after that.
You can write a function that takes a FUNCTIONS by reference, and modify put2struct to call that function. That way you can access struct1 from a different cpp file:
void foo(FUNCTIONS&);
void put2struct()
{
FUNCTIONS struct1;
// do your thing
foo(struct1);
}
// another file
void foo(FUNCTIONS& object) {
// you have access to the object passed by reference
}
I am getting the above error while running the executable after compiling and running the following file.
#define BOOST_TEST_MAIN
#define BOOST_TEST_DYN_LINK
#include <iostream>
#include <boost/shared_ptr.hpp>
#include <boost/test/unit_test.hpp>
#include <boost/bind.hpp>
#include <boost/test/unit_test_log.hpp>
#include <boost/filesystem/fstream.hpp>
#include "index/DatabaseGroup.hpp"
using namespace boost::unit_test;
namespace indexing {
class ForwardDBTest {
/// A pointer to the database group object.
DatabaseGroup& databaseGroup;
std::string databaseName;
public:
~ForwardDBTest() {
}
;
ForwardDBTest(DatabaseGroup& databaseGroup_, std::string dbName) :
databaseGroup(databaseGroup_), databaseName(dbName) {
}
void boostTestCreateDB() {
databaseGroup.createDatabase(databaseName, databaseName);
}
};
class testSuites: public test_suite {
public:
testSuites() :
test_suite("test_suite") {
std::string db_location = "home/girijag/ripe/ripe_db";
std::cout << "hello" << std::endl;
int concurrency = 0;
std::string db_cache_policy = "AllMem";
boost::shared_ptr<DatabaseGroup> db = boost::shared_ptr<DatabaseGroup>(
new DatabaseGroup(db_location, concurrency, db_cache_policy));
std::string dbName = "DB1";
boost::shared_ptr<ForwardDBTest> instance(
new ForwardDBTest(*db, dbName));
test_case* boostTestCreateDB_test_case = BOOST_CLASS_TEST_CASE(
&ForwardDBTest::boostTestCreateDB, instance);
add(boostTestCreateDB_test_case);
}
~testSuites() {
}
;
};
test_suite* init_unit_test_suite(int argc, char** argv) {
test_suite* suite(BOOST_TEST_SUITE("Master Suite"));
suite->add(new testSuites());
return suite;
}
}'
Please let me know how should i resolve this?
i am getting errors as below:-
Test setup error: memory access violation at address: 0x00000021: no mapping at fault address
I have been struggling from past 2 days to figure out whats my issue
There are a number of disturbing things in the code, and some formatting seems have to been lost when posting the question, otherwise there is no chance it compiles. (For example, }’ ?!)
For starters, you shouldn’t place init_unit_test_suite(int, char**) in the indexing namespace, and subsequently there is no point in defining BOOST_TEST_MAIN - you will end up with multiple definition of the said init_unit_test_suite(int, char**) method.
In your case, the suite should be simply registered in the master test suite, there is no need to return a pointer to it from the method.
Here’s a minimal example that you can work with an extend for your purpose. It follows your structure, but omits non-relevant details:
#include <boost/test/included/unit_test.hpp>
#include <iostream>
using namespace boost::unit_test;
namespace indexing {
class ForwardDBTest {
public:
void boostTestCreateDB() { std::cout << __FUNCTION__ << std::endl; }
};
class TestSuite : public test_suite {
public:
TestSuite() : test_suite("test_suite") {
boost::shared_ptr<ForwardDBTest> instance(new ForwardDBTest);
add(BOOST_CLASS_TEST_CASE(&ForwardDBTest::boostTestCreateDB, instance));
}
};
} // namespace indexing
test_suite* init_unit_test_suite(int, char**) {
framework::master_test_suite().add(new indexing::TestSuite);
return 0;
}
/* Output:
Running 1 test case...
boostTestCreateDB
*** No errors detected
*/