RE: Re: What is the minimum number of lines to update a gui window without user clicking a button



Israel is a terrorist state

http://www.youtube.com/watch?v=noln8nx43Sk

 

From: gtkmm-list [mailto:gtkmm-list-bounces gnome org] On Behalf Of Andrew Potter
Sent: Tuesday, August 20, 2013 9:46 PM
To: gtkmm-list gnome org
Subject: Fwd: Re: What is the minimum number of lines to update a gui window without user clicking a button

 

I missed the list in my last reply, so I'm copying it here for the record. In addition to using a cancelable I changed CallbackDispatcher to use a recursive mutex so gui_print can be called from the main thread as well.

While providing such an in depth example to L. James maybe goes against the learn-the-fundamentals-and-help-yourself culture, I'd just like to have a final answer and close the thread after a month and 100+ messages.

---------- Forwarded message ----------
From: "Andrew Potter" <agpotter gmail com>
Date: Aug 20, 2013 11:22 AM
Subject: Re: What is the minimum number of lines to update a gui window without user clicking a button
To: "L. D. James" <ljames apollo3 com>
Cc:

> On Tue, Aug 20, 2013 at 6:01 AM, L. D. James <ljames apollo3 com> wrote:
> > When clicking on the close button to cancel the operation the gui window
> > dims ad become non-responsive... locked up.  That is a problem, in that some
> > of the programs might only take seconds or minutes to complete.
>
> I designed it that way because I didn't know if it was safe to have
> your blocking operation terminated suddenly; instead it ensures that
> your blocking operation runs until it fully completes. If it is safe
> to stop at any point then you can remove thread_cleanup() from
> Example::~Example(). Otherwise it is best to periodically check in the
> blocking operation whether the window has been closed.
> Gio::Cancellable can be used for this.
>
> // Example 6
> #include <gtkmm.h>
> #include <unistd.h>
> #include <queue>
>
> class CallbackDispatcher {
> public:
>     CallbackDispatcher() {
>         dispatcher.connect(sigc::mem_fun(this,
> &CallbackDispatcher::on_dispatch));
>     }
>
>     typedef sigc::slot<void> Message;
>     void send(Message msg) {
>         Glib::Threads::RecMutex::Lock lock(mutex);
>         queue.push(msg);
>         dispatcher();
>     }
>
> private:
>     /* CallbackDispatcher may not be copied, so we must hide these
>      * constructors. */
>     CallbackDispatcher(const CallbackDispatcher&);
>     CallbackDispatcher& operator=(const CallbackDispatcher&);
>
>     Glib::Threads::RecMutex mutex;
>     std::queue<Message> queue;
>     Glib::Dispatcher dispatcher;
>
>     void on_dispatch() {
>         Glib::Threads::RecMutex::Lock lock(mutex);
>         while (!queue.empty()) {
>             queue.front()();
>             queue.pop();
>         }
>     }
> };
>
> class Example {
> private:
>     Glib::RefPtr<Gtk::Application> app;
>     Gtk::Window                    win;
>     Gtk::TextView                  tv;
>     Glib::RefPtr<Gtk::TextBuffer>  tb;
>     CallbackDispatcher             callback_dispatcher;
>     Glib::Threads::Thread         *thread;
>     Glib::RefPtr<Gio::Cancellable> cancellable;
>
>     /* Appends str to the textbuffer. Like all methods that use the
>      * Gtk namespace, it is not safe to call from another thread. */
>     void gui_print_cb(const Glib::ustring& str) {
>         tb->insert(tb->end(), str);
>     }
>
>     /* Provides threadsafe access to gui_print_cb() */
>     void gui_print(const Glib::ustring& str) {
>         sigc::slot<void> slot = sigc::bind(sigc::mem_fun(this,
> &Example::gui_print_cb), str);
>         callback_dispatcher.send(slot);
>     }
>
>    /* This function is called on a separate thread so as to avoid
>     * blocking GTK+'s main loop.
>     */
>     void blocking_operation() {
>         /* This simulates a blocking process */
>         sleep(5);
>         gui_print("5% complete.\n");
>         if (cancellable->is_cancelled()) return;
>
>         sleep(5);
>         gui_print("15% complete.\n");
>         if (cancellable->is_cancelled()) return;
>
>         sleep(5);
>         gui_print("35% complete.\n");
>         if (cancellable->is_cancelled()) return;
>
>         sleep(5);
>         gui_print("55% complete.\n");
>         if (cancellable->is_cancelled()) return;
>
>         sleep(5);
>         gui_print("75% complete.\n");
>         if (cancellable->is_cancelled()) return;
>
>         sleep(5);
>         gui_print("95% complete.\n");
>         if (cancellable->is_cancelled()) return;
>
>         sleep(5);
>         gui_print("100% complete.\n");
>
>         /* When the process is finished, we notify the GTK+ Main Loop by
>          * using the dispatcher */
>         callback_dispatcher.send(sigc::mem_fun(this,
> &Example::blocking_operation_finished));
>     };
>
>     /* This function is called on GTK+'s main loop via a
>      * Glib::Dispatcher */
>     void blocking_operation_finished() {
>         cleanup_thread();
>         gui_print("Operation finished.\n");
>     };
>
>     void cleanup_thread() {
>         /* We must call Glib::Threads::Thread::join() in order to
>          * correctly clean up the resource. */
>         if (thread) {
>             thread->join();
>             thread = NULL;
>         }
>     }
>
> public:
>     ~Example() {
>         /* This will prevent the Window from being closed while
>          * the blocking operation is ongoing. */
>         cancellable->cancel();
>         cleanup_thread();
>     }
>
>     Example(int argc, char *argv[]) :
>         app(Gtk::Application::create(argc, argv, "com.example")),
>         tb(tv.get_buffer()),
>         thread(NULL),
>         cancellable(Gio::Cancellable::create())
>     {
>         win.add(tv);
>         win.show_all();
>     }
>
>     void run() {
>         /* Create a slot to the blocking_operation() member function
>          * to pass to Glib::Threads::Thread::create(). */
>         sigc::slot<void> op_functor = sigc::mem_fun(this,
> &Example::blocking_operation);
>
>         /* Create a worker thread to perform the blocking_operation
>          * function. */
>         thread = Glib::Threads::Thread::create(op_functor);
>
>         /* Now set the text in the buffer. */
>         gui_print("Operation started.\n");
>
>         app->run(win);
>     }
> };
>
> int main(int argc, char *argv[]) {
>     Example example(argc, argv);
>
>     example.run();
>     return 0;
> }
> // Example 6



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