Re: Sending slots to main thread (implemented)



En/na Joaquim Duran ha escrit:

> 
> Continuing with the discussion: I've downloaded the glibmm source code.
> I've seen that the Thread Pool implements the SlotList, but privately.
> 
> IMO, I think that the SlotList object should be made public mainly for
> two reasons:
> 
> - It could help to implement the command patern in Glibmm: an action
> could be seen as a list of slots to be excecuted. Even, the object that
> fills the list of slots, could be different that the object which will
> execute them.
> 
> - This is pretty easy to create an object to send arbitrary slots to
> main thread (like thread pool). Pseudocode:
> 
> class dispatchslots:
> 
> ListStot __list;
> Dispatcher __dispt;
> 
> void push(slot)  // Executed by working thread
> {
>    __list.push(slot);
>    __dispt.emit();
> }
> 
> void run_slot()  // Exceuted by main thread (connected to dispatcher)
> {
>    slot = __list.top();
>    __list.pop();
>    slot.execute();
> }
> 
> 
> 
> What do you think about that?
> 
> Thanks and Best Regards,
> Joaquim Duran
> _______________________________________________
> gtkmm-list mailing list
> gtkmm-list gnome org
> http://mail.gnome.org/mailman/listinfo/gtkmm-list
> 
> 

I've done the implementation and it works fine: I'm able to send a slot
created at runtime to main thread.

I've attached the source code to this e-mail to check it. I think that
implement a class like this one in glibmm will simplify the task of
thread programming.

One problem: to link the object file with the libraries, I've used the
following command in the makefile:

 g++ -Wall `pkg-config --libs gtkmm-2.4` `pkg-config --libs gthread-2.0`
-o slots $(OBJECTS)

Why the libraries for thread management are placed in a different .pc
file? is this a bug?

Joaquim Duran
Thanks and Best Regards,
#include <gtkmm/window.h>
#include <gtkmm/main.h>
#include <gtkmm/box.h>
#include <gtkmm/button.h>
#include <gtkmm/label.h>

#include <glibmm/dispatcher.h>
#include <glibmm/threadpool.h>
#include <glibmm/thread.h>

#include <iostream>
#include <sstream>
#include <queue>
#include <deque>


// SLOT DISPATCHER

class SlotDispatcher
{
public:
  typedef std::queue<sigc::slot<void> > QueueSlot;

  SlotDispatcher();
  ~SlotDispatcher();

  void push(const sigc::slot<void>& slot);

protected:
  sigc::slot<void> pop();
  void run();

private:
  Glib::Mutex mutex;
  Glib::Dispatcher dispatch;
  QueueSlot qslot;
};

SlotDispatcher::SlotDispatcher():
  mutex(), dispatch(), qslot()
{
  dispatch.connect(sigc::mem_fun(*this, &SlotDispatcher::run));
}

SlotDispatcher::~SlotDispatcher()
{
}

void SlotDispatcher::push(const sigc::slot<void>& slot)
{
  {
    Glib::Mutex::Lock lock (this->mutex);
    qslot.push(slot);
  }
  dispatch.emit();
}


sigc::slot<void> SlotDispatcher::pop()
{
  sigc::slot<void> slot;
  Glib::Mutex::Lock lock (this->mutex);

  slot = qslot.front();
  qslot.pop();

  return slot;
}


void SlotDispatcher::run()
{
  sigc::slot<void> slot = pop();
  slot();
}


// THREAD_WINDOW
class ThreadWindow : public Gtk::Window
{
public:
  ThreadWindow();
  virtual ~ThreadWindow();

protected:
  void timer_work();
  void pool_work(long int value);
  void main_work(long int value);

private:
  Gtk::VBox vbox;
  Gtk::Button button;
  Gtk::Label label;

  sigc::connection conn;
  Glib::ThreadPool pool;
  SlotDispatcher slotDispt;
  Glib::Mutex screen;
};


ThreadWindow::ThreadWindow():
  Gtk::Window(), vbox(), label(),
  conn(), pool(3, true), slotDispt(), screen()
{
  // Windows
    add(vbox);
    vbox.add(button);
    vbox.add(label);

    button.set_label("Quit");
    button.signal_clicked().connect( sigc::mem_fun(*this,
              &ThreadWindow::hide));

    show_all_children();

  // Threads
    conn = Glib::signal_timeout().connect(
         sigc::bind_return(
              sigc::mem_fun(*this, &ThreadWindow::timer_work),
              true), 3000);
}


ThreadWindow::~ThreadWindow()
{
      conn.disconnect();
}


void ThreadWindow::timer_work()
{
  int value = random();
  
  sigc::slot<void> slot = sigc::bind(
	      sigc::mem_fun(*this, &ThreadWindow::pool_work), value);

  {
    Glib::Mutex::Lock lock(this->screen);
    std::cout << "Timer_work" << std::endl;
    std::cout << "\tValue: " << value << std::endl;
  }

  pool.push(slot);
}

void ThreadWindow::pool_work(long int value)
{
  {
  Glib::Mutex::Lock lock(this->screen);
  std::cout << "Pool work" << std::endl;
  std::cout << "\tValue: " << value << std::endl;
  }

  slotDispt.push(sigc::bind(
	    sigc::mem_fun(*this, &ThreadWindow::main_work), value));
}


void ThreadWindow::main_work(long int value)
{
  {
  Glib::Mutex::Lock lock(this->screen);
  std::cout << "Main work" << std::endl;
  std::cout << "\tValue: " << value << std::endl;
  }

  std::stringstream strm;
  strm << value;
  label.set_label(strm.str());
}


// MAIN
int main(int argc, char *argv[])
{
   Glib::thread_init();
   Gtk::Main kit(argc, argv);

   ThreadWindow mainWin;
   Gtk::Main::run(mainWin);

   return 0;
}


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