class with Multithreaded member function

1.1k Views Asked by At

I have a class which I am trying to convert some of its member function to run in different threads. While the program complies without problem, but it crashes when it is trying to read from a image buffer(which is updated by a different thread). Seems like the problem is cause by when argument is passed incorrectly in _beginthread.

The following snippet of code should explain more clearly what I am trying to do. Basically what I am trying to accomplish is have member function "fillBuffer" fill a image buffer while rest of program is doing something else including reading the same image buffer at the same time.

Any help with the syntax is greatly appreciated.

 const int MaxImgBufferSize = 5;
        class MyFrame : public wxFrame
        {
        public:
            // constructors
            MyFrame(const wxString& title);   

        private:
            static vector <IplImage*> ImgBuffer;
            void  changeWP(wxCommandEvent&);
            void  fillBuffer();
                void  fillBufferFun();
                static void __cdecl getImgFromBuffer(void *);
                static void __cdecl pushImgBuffer(void *);
        };

    vector<IplImage*> MyFrame::ImgBuffer;

        enter code here

    MyFrame::MyFrame(const wxString& title)
           : wxFrame(...)
    {
       // some stuff here
       InitializeCriticalSection(&Section);
       fillBuffer();

      // some code here calls changeWP(wxCommandEvent&) from time to time
    }

    void MyFrame::fillBuffer()
    {
        while(ImgBuffer.size() <= MaxImgBufferSize)
        {
            fillBufferFun();
        }
    }

void MyFrame::fillBufferFun()
{
   ImgBuffer* img;
   // do something with img
   _beginthread(pushImgBuffer, 0, img);
}

void MyFrame::pushImgBuffer(void *p)
{
    EnterCriticalSection(&Section);
    ImgBuffer.push_back( (IplImage*) p );
    LeaveCriticalSection(&Section);
}

static unsigned int __stdcall getImgFromBuffer(void *);

void MyFrame::changeWP(wxCommandEvent&)
{
    // do someting

    IplImage* img = NULL;// new IplImage;
        _beginthreadex( NULL, 0, MyFrame::getImgFromBuffer, img, 0, NULL );

        // do something with img
        fillBuffer();
}

unsigned int MyFrame::getImgFromBuffer(void *p)
{
    EnterCriticalSection(&Section);
    p = (void *)ImgBuffer[0];
    ImgBuffer.erase(ImgBuffer.begin());
    LeaveCriticalSection(&Section);
    return 0;
}
1

There are 1 best solutions below

2
On

There are a couple of issues here:

  1. Your code is crashing because your getImgFromBuffer function doesn't have the effect you seem to intend for it. It seems, from looking at the body of getImgFromBuffer, that you are trying to copy a pointer value out of the vector (MyFrame::ImgBuffer) and use it overwrite the pointer value passed in from the function that invoked it (i.e., the "img" variable inside MyFrame::changeWP). I say "seems" because of your initialization of the "img" variable inside MyFrame::changeWP (IplImage* img = new IplImage) just before you invoke getImgFromBuffer -- why assign a new object to the pointer just before assigning yet another, different pointer value to it (leading, of course, to a memory leak)? Anyhow, the assignment is currently just overwriting the value of the "p" argument inside the getImgFromBuffer function, which was passed by value and will be lost when the function exits. If you want getImgFromBuffer to overwrite a pointer variable passed in from its caller, then you need to pass a pointer to the pointer variable, like so:
void MyFrame::changeWP(wxCommandEvent&)
{
    IplImage* img = NULL;  // No memory leak, this time.
    _beginthread(MyFrame::getImgFromBuffer, 0, & img);
    //...
}

void MyFrame::getImgFromBuffer(void ** p)
{
    //...
    *p = (void *)ImgBuffer[0];
    //...
}
  1. I don't see how "Section" is defined, but whether it's static or instance, it's at least bad form either way. If it's static, then you're making the mistake of re-initializing it every time you construct. I realize that this a class representing a top-level window, so you probably won't be making more than one of them, but it's still bad form. If Section is an instance variable, then you could have multiple Section objects trying to protect a single (static) resource, with no mutual exclusion between them. Again, there's only the one window, so this probably isn't your actual problem, but still...

There's probably more, but this is enough to start with.