CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 8 of 8

Thread: c++ callbacks

  1. #1
    Join Date
    Oct 2003
    Posts
    15

    c++ callbacks

    Hello, someone can to get me samples of callbacks like producer and consumer.
    Thanks in advance.

  2. #2
    Join Date
    Jun 2002
    Location
    Germany
    Posts
    1,557
    dmf,

    Callbacks are a class of functions. There are many kinds of callbacks in all different types of programming. In general, a callback function is used as a delayed reaction to some kind of input or after some result.

    Callback techniques are often used in multi-process or multi-threaded applications in order to provide communication mechanisms among threads and processes.

    The example below might be a little bit tough to understand. But please do take a look. The windows stuff is all standard. It will give you the right ideas. It uses Microsoft compilers in the Win32 API environment. Try to see how the callback works.

    Sincerely, Chris.

    Code:
    #include <iostream>
    #include <Windows.h>
    
    static bool b_done = false;
    
    static void callback_calculation_done(void)
    {
      b_done = true;
    }
    
    // Some calculation in some kind of thread process.
    DWORD WINAPI thread_do_calculation(LPVOID p = NULL)
    {
      double hundred_factorial = 2;
      for(int i = 3; i <= 100; i++)
      {
        hundred_factorial *= static_cast<double>(i);
      }
    
      // Communicate that the calculation is done using the callback.
      callback_calculation_done();
    
      return 0;
    }
    
    int main(int argc, char* argv[])
    {
      SECURITY_ATTRIBUTES sa = { sizeof(SECURITY_ATTRIBUTES), NULL, FALSE };
      DWORD id;
    
      HANDLE h = ::CreateThread(&sa,
                                0,
                                thread_do_calculation,
                                NULL,
                                THREAD_PRIORITY_NORMAL,
                                &id);
    
      if(h)
      {
        while(!b_done)
        {
          ;
        }
      }
    
      ::std::cout << b_done << ::std::endl;
    
      return 0;
    }
    You're gonna go blind staring into that box all day.

  3. #3
    Join Date
    Aug 1999
    Posts
    586
    Originally posted by dude_1967
    Code:
    #include <iostream>
    #include <Windows.h>
    
    static bool b_done = false;
    
    static void callback_calculation_done(void)
    {
      b_done = true;
    }
    
    // Some calculation in some kind of thread process.
    DWORD WINAPI thread_do_calculation(LPVOID p = NULL)
    {
      double hundred_factorial = 2;
      for(int i = 3; i <= 100; i++)
      {
        hundred_factorial *= static_cast<double>(i);
      }
    
      // Communicate that the calculation is done using the callback.
      callback_calculation_done();
    
      return 0;
    }
    
    int main(int argc, char* argv[])
    {
      SECURITY_ATTRIBUTES sa = { sizeof(SECURITY_ATTRIBUTES), NULL, FALSE };
      DWORD id;
    
      HANDLE h = ::CreateThread(&sa,
                                0,
                                thread_do_calculation,
                                NULL,
                                THREAD_PRIORITY_NORMAL,
                                &id);
    
      if(h)
      {
        while(!b_done)
        {
          ;
        }
      }
    
      ::std::cout << b_done << ::std::endl;
    
      return 0;
    }
    "callback_calculation_done()" is not a callback function here. " thread_do_calculation()" qualifies as one though not in the traditional sense. A callback function simply refers to a pointer to a function that you hand off to someone else so the function can later be invoked (called back) when something interesting happens. For instance, take a look at the Windows function "EnumWindows()". The first argument is a callback function that "EnumWindows()" will invoke (call back) once for each top-level window on the system. This is what is normally meant by a "callback". BTW, your use of "b_done" to block the main thread is inefficient. You should rely on methods like passing the thread handle to "WaitForSingleObject()" for instance. More importantly, you're accessing a global (static) variable across two threads without providing synchronization control (which is rather harmless in this trivial example but the technique in general is dangerous).

  4. #4
    Join Date
    Jun 2002
    Location
    Germany
    Posts
    1,557

    oops...oh yeah

    Yeah Sef, dmf,

    I'm sorry. I had forgotten that a central point to the callback function is that a pointer to the callback function is usually passed to some kind of management list for future callback usage.

    My example is a bit poor and faulty.

    Just think: Function pointer to callback --> Management scheme --> Calls the callback later. This is the general callback stuff.

    Sincerely, Chris.

    You're gonna go blind staring into that box all day.

  5. #5
    Join Date
    Apr 1999
    Location
    Altrincham, England
    Posts
    4,470
    In C++, I prefer to use the Observer pattern:
    Code:
    class FooObserver
    {
    public:
        virtual void OnFooStarted() = 0;
        virtual void OnFooDone() = 0;
    };
    
    class Foo
    {
    public:
        void DoIt()
        {
            obs.OnFooStarted();
            // do stuff
            obs.OnFooDone();
        }
    
        Foo(FooObserver& o) : obs(o) {}
    
    private:
        FooObserver& obs;
    };
    
    class Bar : public FooObserver
    {
    public:
        void OnFooStarted() { /* Do something*/ }
        void OnFooDone() { /* Do something */ }
        void Something()
        {
            Foo f(*this);
            f.DoIt();
        }
    };
    This can be extended to allow Foo to have a vector of observers (they'd have to be stored as pointers, not references, though). Also Bar can be an observer of more than one class by inheriting from multiple observer interfaces.
    Correct is better than fast. Simple is better than complex. Clear is better than cute. Safe is better than insecure.
    --
    Sutter and Alexandrescu, C++ Coding Standards

    Programs must be written for people to read, and only incidentally for machines to execute.

    --
    Harold Abelson and Gerald Jay Sussman

    The cheapest, fastest and most reliable components of a computer system are those that aren't there.
    -- Gordon Bell


  6. #6
    Join Date
    Oct 2003
    Posts
    15
    I find this sample of callbacks, and I ask if not exits another way to do this.



    #include <iostream.h>

    class Button;


    class CdPlayer
    {
    public:
    void buttonPushed(Button* pButton_)
    {
    if (pButton_ == _pPlayButton)
    this->playButtonPushed(pButton_);
    else if (pButton_ == _pStopButton)
    this->stopButtonPushed(pButton_);
    }

    void setPlayButton(Button* pButton_) {_pPlayButton = pButton_;}
    void setStopButton(Button* pButton_) {_pStopButton = pButton_;}
    void playButtonPushed(Button*) {cout << "PLAY" << endl;}
    void stopButtonPushed(Button*) {cout << "STOP" << endl;}

    private:
    Button* _pPlayButton;
    Button* _pStopButton;
    };



    //----------------------------------------
    class Button
    {
    public:
    Button(CdPlayer* pCdPlayer_): _pCdPlayer(pCdPlayer_){}
    void push() {_pCdPlayer->buttonPushed(this);}
    private:
    CdPlayer* _pCdPlayer;
    };
    //----------------------------------------
    main()
    {
    CdPlayer aCdPlayer;
    Button playButton(&aCdPlayer);
    Button stopButton(&aCdPlayer);
    aCdPlayer.setPlayButton(&playButton);
    aCdPlayer.setStopButton(&stopButton);

    playButton.push();
    stopButton.push();

    return 0;
    }
    Last edited by dmf9000; October 30th, 2003 at 07:11 AM.

  7. #7
    Join Date
    Aug 2002
    Posts
    78
    I don' t know where you found this, but it's a terrible example of anything.

    The use of _ to distinguish variables of buttons (preceeding AND trailing) is abysmal and will lead to bugs almost certainly.


    Secondly, it's not an example of callbacks. It's a strange example of how to pass an object into another object, and then that other object using it. Nothing unusual at all.

    By the way, I program radios that drive CD mechanisms for a living. This is not the way you want to go about this sort of thing. It's almost reminiscent of the Microsoft tuner APIs built into Apollo, sorry, AutoPC, sorry, Windows CE for Automotive.


    I suggest looking into good ol' qsort to see what a callback function is all about.


    I'm mad because I missed Charlie Brown Halloween this year.

  8. #8
    Join Date
    Aug 2002
    Posts
    78
    FYI, when passing in a new value or object to take the place of an old one, try giving them meaningful names, then there won't be a conflict that appending or prepending _ gets around.

    e.g.
    Code:
    CMyRadio::hereIsANewButtonForYa(CMyButton &theNewMyButton)
    {
         mMyButton = theNewMyButton
    }

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured