Initializing and managing many references in multithreaded control application
$begingroup$
I have a large multi-window GUI program (implemented with MFC) that controls a variety of physics experiment apparatus. When the user starts the main function of the program (the "experiment" run), a large worker thread starts which needs references various singleton objects (generally one per piece of apparatus) to do it's work - in particular programming a variety of machines. These objects are in general managed by the windows which contain the GUI elements relative to those objects, and because they are tied to the GUI windows, they will always exist as long as the program is running. I'm struggling to figure out the best way to handle the references to these objects. What I've done in the past is just use raw pointers to these objects, but this seems like bad style so I'm looking at improvements.
My current scheme is having class structures like this:
#include "RF_Generator.h"
#include "AnalogOutputs.h"
struct MasterThreadInput
{
MasterThreadInput(RfWindow& rfWin, AnalogOutputWindow& aoWin) :
objA(winA.getObjA()),
objB(winB.getObjB())
{ }
RfGenerator& rfSys;
AnalogOutputs& aoSys;
}
class RfWindow : public CDialog
{
public:
RfGenerator& getRfSys();
private:
RfGenerator rfSys;
}
class AnalogOutputWindow : public CDialog
{
public:
AnalogOutputs& getAoSys();
private:
AnalogOutputs aoSys;
}
This then gets filled and used like this:
void startThread(RfWindow& rfWin, AnalogOutputWindow& aoWin)
{
MasterThreadInput* input = new MasterThreadInput(rfWin, aoWin);
// other checks on the input
_beginthreadex( NULL, NULL, &MainExperimentThreadProcedure, input, NULL, NULL );
}
unsigned int __stdcall MainExperimentThreadProcedure( void* voidInput )
{
MasterThreadInput* input = (MasterThreadInput*)voidInput;
try
{
// And then do work.
input->rfSys.programRfGeneration();
input->aoSys.programAnalogOutputs();
// etc.
}
catch (...)
{
// handle errors
}
delete input;
return 0;
}
This example code should be very representative of the real thing, except that in the real thing there are 5 windows, many more objects to fill (about 15 in total), and a much more complicated thread procedure - it's a big worker thread. I thought about using smart pointers instead of references considering the seemingly awkward constructor needed to initialize the references, and since I was using raw pointers before these references. However, considering that I don't actually need the worker thread to manage the memory for these objects (the objects will exist as long as the windows do, and the windows will exist for the entire program), it seems that I should just try to avoid pointers all-together. Does this code follow best practices regarding managing memory and shared access in multitheaded c++ applications? Are there ways to improve on this organization? It's a very important part of the control system, so I'd like to get it right.
c++ multithreading memory-management
New contributor
aquirdturtle is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
$endgroup$
add a comment |
$begingroup$
I have a large multi-window GUI program (implemented with MFC) that controls a variety of physics experiment apparatus. When the user starts the main function of the program (the "experiment" run), a large worker thread starts which needs references various singleton objects (generally one per piece of apparatus) to do it's work - in particular programming a variety of machines. These objects are in general managed by the windows which contain the GUI elements relative to those objects, and because they are tied to the GUI windows, they will always exist as long as the program is running. I'm struggling to figure out the best way to handle the references to these objects. What I've done in the past is just use raw pointers to these objects, but this seems like bad style so I'm looking at improvements.
My current scheme is having class structures like this:
#include "RF_Generator.h"
#include "AnalogOutputs.h"
struct MasterThreadInput
{
MasterThreadInput(RfWindow& rfWin, AnalogOutputWindow& aoWin) :
objA(winA.getObjA()),
objB(winB.getObjB())
{ }
RfGenerator& rfSys;
AnalogOutputs& aoSys;
}
class RfWindow : public CDialog
{
public:
RfGenerator& getRfSys();
private:
RfGenerator rfSys;
}
class AnalogOutputWindow : public CDialog
{
public:
AnalogOutputs& getAoSys();
private:
AnalogOutputs aoSys;
}
This then gets filled and used like this:
void startThread(RfWindow& rfWin, AnalogOutputWindow& aoWin)
{
MasterThreadInput* input = new MasterThreadInput(rfWin, aoWin);
// other checks on the input
_beginthreadex( NULL, NULL, &MainExperimentThreadProcedure, input, NULL, NULL );
}
unsigned int __stdcall MainExperimentThreadProcedure( void* voidInput )
{
MasterThreadInput* input = (MasterThreadInput*)voidInput;
try
{
// And then do work.
input->rfSys.programRfGeneration();
input->aoSys.programAnalogOutputs();
// etc.
}
catch (...)
{
// handle errors
}
delete input;
return 0;
}
This example code should be very representative of the real thing, except that in the real thing there are 5 windows, many more objects to fill (about 15 in total), and a much more complicated thread procedure - it's a big worker thread. I thought about using smart pointers instead of references considering the seemingly awkward constructor needed to initialize the references, and since I was using raw pointers before these references. However, considering that I don't actually need the worker thread to manage the memory for these objects (the objects will exist as long as the windows do, and the windows will exist for the entire program), it seems that I should just try to avoid pointers all-together. Does this code follow best practices regarding managing memory and shared access in multitheaded c++ applications? Are there ways to improve on this organization? It's a very important part of the control system, so I'd like to get it right.
c++ multithreading memory-management
New contributor
aquirdturtle is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
$endgroup$
add a comment |
$begingroup$
I have a large multi-window GUI program (implemented with MFC) that controls a variety of physics experiment apparatus. When the user starts the main function of the program (the "experiment" run), a large worker thread starts which needs references various singleton objects (generally one per piece of apparatus) to do it's work - in particular programming a variety of machines. These objects are in general managed by the windows which contain the GUI elements relative to those objects, and because they are tied to the GUI windows, they will always exist as long as the program is running. I'm struggling to figure out the best way to handle the references to these objects. What I've done in the past is just use raw pointers to these objects, but this seems like bad style so I'm looking at improvements.
My current scheme is having class structures like this:
#include "RF_Generator.h"
#include "AnalogOutputs.h"
struct MasterThreadInput
{
MasterThreadInput(RfWindow& rfWin, AnalogOutputWindow& aoWin) :
objA(winA.getObjA()),
objB(winB.getObjB())
{ }
RfGenerator& rfSys;
AnalogOutputs& aoSys;
}
class RfWindow : public CDialog
{
public:
RfGenerator& getRfSys();
private:
RfGenerator rfSys;
}
class AnalogOutputWindow : public CDialog
{
public:
AnalogOutputs& getAoSys();
private:
AnalogOutputs aoSys;
}
This then gets filled and used like this:
void startThread(RfWindow& rfWin, AnalogOutputWindow& aoWin)
{
MasterThreadInput* input = new MasterThreadInput(rfWin, aoWin);
// other checks on the input
_beginthreadex( NULL, NULL, &MainExperimentThreadProcedure, input, NULL, NULL );
}
unsigned int __stdcall MainExperimentThreadProcedure( void* voidInput )
{
MasterThreadInput* input = (MasterThreadInput*)voidInput;
try
{
// And then do work.
input->rfSys.programRfGeneration();
input->aoSys.programAnalogOutputs();
// etc.
}
catch (...)
{
// handle errors
}
delete input;
return 0;
}
This example code should be very representative of the real thing, except that in the real thing there are 5 windows, many more objects to fill (about 15 in total), and a much more complicated thread procedure - it's a big worker thread. I thought about using smart pointers instead of references considering the seemingly awkward constructor needed to initialize the references, and since I was using raw pointers before these references. However, considering that I don't actually need the worker thread to manage the memory for these objects (the objects will exist as long as the windows do, and the windows will exist for the entire program), it seems that I should just try to avoid pointers all-together. Does this code follow best practices regarding managing memory and shared access in multitheaded c++ applications? Are there ways to improve on this organization? It's a very important part of the control system, so I'd like to get it right.
c++ multithreading memory-management
New contributor
aquirdturtle is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
$endgroup$
I have a large multi-window GUI program (implemented with MFC) that controls a variety of physics experiment apparatus. When the user starts the main function of the program (the "experiment" run), a large worker thread starts which needs references various singleton objects (generally one per piece of apparatus) to do it's work - in particular programming a variety of machines. These objects are in general managed by the windows which contain the GUI elements relative to those objects, and because they are tied to the GUI windows, they will always exist as long as the program is running. I'm struggling to figure out the best way to handle the references to these objects. What I've done in the past is just use raw pointers to these objects, but this seems like bad style so I'm looking at improvements.
My current scheme is having class structures like this:
#include "RF_Generator.h"
#include "AnalogOutputs.h"
struct MasterThreadInput
{
MasterThreadInput(RfWindow& rfWin, AnalogOutputWindow& aoWin) :
objA(winA.getObjA()),
objB(winB.getObjB())
{ }
RfGenerator& rfSys;
AnalogOutputs& aoSys;
}
class RfWindow : public CDialog
{
public:
RfGenerator& getRfSys();
private:
RfGenerator rfSys;
}
class AnalogOutputWindow : public CDialog
{
public:
AnalogOutputs& getAoSys();
private:
AnalogOutputs aoSys;
}
This then gets filled and used like this:
void startThread(RfWindow& rfWin, AnalogOutputWindow& aoWin)
{
MasterThreadInput* input = new MasterThreadInput(rfWin, aoWin);
// other checks on the input
_beginthreadex( NULL, NULL, &MainExperimentThreadProcedure, input, NULL, NULL );
}
unsigned int __stdcall MainExperimentThreadProcedure( void* voidInput )
{
MasterThreadInput* input = (MasterThreadInput*)voidInput;
try
{
// And then do work.
input->rfSys.programRfGeneration();
input->aoSys.programAnalogOutputs();
// etc.
}
catch (...)
{
// handle errors
}
delete input;
return 0;
}
This example code should be very representative of the real thing, except that in the real thing there are 5 windows, many more objects to fill (about 15 in total), and a much more complicated thread procedure - it's a big worker thread. I thought about using smart pointers instead of references considering the seemingly awkward constructor needed to initialize the references, and since I was using raw pointers before these references. However, considering that I don't actually need the worker thread to manage the memory for these objects (the objects will exist as long as the windows do, and the windows will exist for the entire program), it seems that I should just try to avoid pointers all-together. Does this code follow best practices regarding managing memory and shared access in multitheaded c++ applications? Are there ways to improve on this organization? It's a very important part of the control system, so I'd like to get it right.
c++ multithreading memory-management
c++ multithreading memory-management
New contributor
aquirdturtle is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
New contributor
aquirdturtle is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
New contributor
aquirdturtle is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
asked 6 hours ago
aquirdturtleaquirdturtle
101
101
New contributor
aquirdturtle is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
New contributor
aquirdturtle is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
aquirdturtle is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
add a comment |
add a comment |
0
active
oldest
votes
StackExchange.ifUsing("editor", function () {
return StackExchange.using("mathjaxEditing", function () {
StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
});
});
}, "mathjax-editing");
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "196"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
aquirdturtle is a new contributor. Be nice, and check out our Code of Conduct.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f216678%2finitializing-and-managing-many-references-in-multithreaded-control-application%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
0
active
oldest
votes
0
active
oldest
votes
active
oldest
votes
active
oldest
votes
aquirdturtle is a new contributor. Be nice, and check out our Code of Conduct.
aquirdturtle is a new contributor. Be nice, and check out our Code of Conduct.
aquirdturtle is a new contributor. Be nice, and check out our Code of Conduct.
aquirdturtle is a new contributor. Be nice, and check out our Code of Conduct.
Thanks for contributing an answer to Code Review Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
Use MathJax to format equations. MathJax reference.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f216678%2finitializing-and-managing-many-references-in-multithreaded-control-application%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
