Initializing and managing many references in multithreaded control application












0












$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.










share|improve this question







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$

















    0












    $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.










    share|improve this question







    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$















      0












      0








      0





      $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.










      share|improve this question







      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






      share|improve this question







      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.











      share|improve this question







      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.









      share|improve this question




      share|improve this question






      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.






















          0






          active

          oldest

          votes












          Your Answer





          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.










          draft saved

          draft discarded


















          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.










          draft saved

          draft discarded


















          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.




          draft saved


          draft discarded














          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





















































          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







          Popular posts from this blog

          How to make a Squid Proxy server?

          第一次世界大戦

          Touch on Surface Book