Re: [gtkmm] ANNOUNCE: glibmm 2.3.0



second and last example in glibmm/examples/thread that didn't compile
fixed...


On mié, 2003-10-01 at 03:06, Murray Cumming wrote:
> On Wed, 2003-10-01 at 01:43, J Abelardo Gutierrez wrote:
> > This is great news, I use glib for all my my non gui C apps and now I
> > will use glimm for all my c++ ones.
> 
> Yes, libxml++ will also use it in future.
> 
> > If there is some work I could contribute with ...
> 
> There are 1 or 2 examples in glibmm 2.4 that don't build because they
> use gtkmm. For instance, examples/thread. I'd really like someone to
> remove the GUI from them.
> 
> And we need to find out whether any API has been added to glib 2.3 in
> CVS, or will be added.
-- 
Lic. J. Abelardo Gutierrez
Linux Counter # 80026

-----BEGIN GEEK CODE BLOCK-----
Version: 3.1
GCS/MU dx s-:++>-: a C+++ UL+++$ P++>+++ L+++>++++ E-- W+ N o K- w---(+)$
O+>- M? V? PS+ PE- Y+ PGP>+ t 5 X+ R+ tv+ b++ DI(+) D++
G e++ h r+++ y+++
------END GEEK CODE BLOCK------
/*
* original Glib::Dispatcher example -- cross thread signalling
* by Daniel Elstner  <daniel elstner gmx net>
* 
* Modified by Stephan Puchegger <stephan puchegger ap univie ac at>
* to contain 2 mainloops in 2 different threads, that communicate 
* via cross thread signalling in both directions. The timer thread
* sends the UI thread a cross thread signal every second, which in turn
* updates the label stating how many seconds have passed since the start
* of the program.
*
* Modified by J. Abelardo Gutierrez <jabelardo cantv net>
* to cast all gtkmm out and make it glimm only
*
* Note:  This example is special stuff that's seldomly needed by the
* vast majority of applications.  Don't bother working out what this
* code does unless you know for sure you need 2 main loops running in
* 2 distinct main contexts.
*
* Copyright (c) 2002-2003  Free Software Foundation
*/

#include <sigc++/class_slot.h>
#include <glibmm.h>
#include <sstream>
#include <iostream>


namespace
{
   Glib::RefPtr<Glib::MainLoop> main_loop;

   class ThreadTimer : public SigC::Object
   {
      public:
         ThreadTimer();
         ~ThreadTimer();

         void launch();
         void signal_finished_emit();
         void print() const;
         static SigC::Signal0< void >& signal_end();

      private:
         guint time_;
         Glib::Dispatcher signal_increment_;
         Glib::Dispatcher* signal_finished_ptr_;

         Glib::Mutex startup_mutex_;
         Glib::Cond startup_cond_;
         static SigC::Signal0< void > signal_end_;
         Glib::Thread* thread_;

         void timer_increment();
         bool timeout_handler();
         static void finished_handler( Glib::RefPtr<Glib::MainLoop> mainloop );
         void thread_function();
   };

   class Dispatcher : public SigC::Object
   {
      public:
         Dispatcher();

         void launch_thread();
         void end();

      private:
         ThreadTimer* timer_;
   };

   ThreadTimer::ThreadTimer()
         :
         time_( 0 ),
         // Create a new dispatcher that is attached to the default main context,
         signal_increment_(),
         // This pointer will be initialized later by the 2nd thread.
         signal_finished_ptr_( NULL )

   {
      // Connect the cross-thread signal.
      signal_increment_.connect( SigC::slot( *this, &ThreadTimer::timer_increment ) );
   }

   ThreadTimer::~ThreadTimer()
   {}

   void ThreadTimer::launch()
   {
      // Unfortunately, the thread creation has to be fully synchronized in
      // order to access the Dispatcher object instantiated by the 2nd thread.
      // So, let's do some kind of hand-shake using a mutex and a condition
      // variable.
      Glib::Mutex::Lock lock( startup_mutex_ );

      // Create a joinable thread -- it needs to be joined, otherwise it's a memory leak.
      thread_ = Glib::Thread::create(
                   SigC::slot_class( *this, &ThreadTimer::thread_function ), true );

      // Wait for the 2nd thread's startup notification.
      while ( signal_finished_ptr_ == NULL )
      {
         startup_cond_.wait( startup_mutex_ );
      }
   }

   void ThreadTimer::signal_finished_emit()
   {
      // Cause the 2nd thread's main loop to quit.
      signal_finished_ptr_->emit();

      // wait for the thread to join
		if ( thread_ != NULL )
		{
      	thread_->join();
		}

      signal_finished_ptr_ = NULL;
   }

   void ThreadTimer::print() const
   {
      std::cout << time_ << " seconds since start" << std::endl;
   }

   SigC::Signal0< void >& ThreadTimer::signal_end()
   {
      return signal_end_;
   }

   void ThreadTimer::timer_increment()
   {
      // another second has passed since the start of the program
      ++time_;
      print();

      if ( time_ >= 10 )
      {
         signal_finished_emit();
      }
   }

   // static
   void ThreadTimer::finished_handler( Glib::RefPtr<Glib::MainLoop> mainloop )
   {
      // quit the timer thread mainloop
      mainloop->quit();
      std::cout << "timer thread mainloop finished" << std::endl;
      ThreadTimer::signal_end().emit();
   }

   bool ThreadTimer::timeout_handler()
   {
      // inform the printing thread that another second has passed
      signal_increment_();

      // this timer should stay alive
      return true;
   }

   void ThreadTimer::thread_function()
   {
      // create a new Main Context
      Glib::RefPtr<Glib::MainContext> context = Glib::MainContext::create();
      // create a new Main Loop
      Glib::RefPtr<Glib::MainLoop> mainloop = Glib::MainLoop::create( context, true );

      // attach a timeout handler, that is called every second, to the
      // newly created MainContext
      context->signal_timeout().connect( SigC::slot( *this, &ThreadTimer::timeout_handler ), 1000 );

      // We need to lock while creating the Dispatcher instance,
      // in order to ensure memory visibility.
      Glib::Mutex::Lock lock ( startup_mutex_ )
         ;

      // create a new dispatcher, that is connected to the newly
      // created MainContext
      Glib::Dispatcher signal_finished ( context );
      signal_finished.connect( SigC::bind( SigC::slot( &ThreadTimer::finished_handler ), mainloop ) );

      signal_finished_ptr_ = &signal_finished;

      // Tell the launcher thread that everything is in place now.
      startup_cond_.signal();
      lock.release();

      // start the mainloop
      mainloop->run();
   }

   // static
   SigC::Signal0< void > ThreadTimer::signal_end_;

   Dispatcher::Dispatcher()
         :
         timer_ ( NULL )
   {
      std::cout << "Thread Dispatcher Example #2" << std::endl;

      timer_ = new ThreadTimer();
      timer_->signal_end().connect( SigC::slot( *this, &Dispatcher::end ) );
      timer_->print();
   }

   void Dispatcher::launch_thread()
   {
      // launch the timer thread
      timer_->launch();
   }

   void Dispatcher::end()
   {
      // quit the main  mainloop
      main_loop->quit();
   }

} // anonymous namespace


int main( gint argc, gchar** argv )
{
   Glib::thread_init();
   main_loop = Glib::MainLoop::create();

   Dispatcher dispatcher;

   // Install a one-shot idle handler to launch the threads
   Glib::signal_idle().connect(
      SigC::bind_return( SigC::slot( dispatcher, &Dispatcher::launch_thread ), false ) );

   main_loop->run();

   return 0;
}

Attachment: signature.asc
Description: This is a digitally signed message part



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]