Re: Multi-threaded Text Insertion into a TextView



The fact is that you can't access the GUI from more than one thread, usually the main thread. It's not enough to serialize your code; you should be mutexed with the main thread queue. Search in this list for multithreading, and you'll see the topic discussed in detail.
Regards,

Leandro.

DESCOMBES Thierry wrote:
Hello,

I'm using gtkmm-2.4.2.
I have several POSIX threads trying to insert text into a Textview. So, I use a POSIX mutex to be sure that text is inserted into the TextBuffer one after the other.

Most of time, it works but sometimes, I get some GTK error message :

(TTdaq Application v0.8b:16046): Gtk-WARNING **: Invalid text buffer iterator: either the iterator is uninitialized, or the characters/pixbufs/widgets in the buffer have been modified since the iterator was created.
You must use marks, character numbers, or line numbers to preserve a position across buffer modifications.
You can apply tags and insert marks without invalidating your iterators,
but any mutation that affects 'indexable' buffer contents (contents that can be referred to by character offset)
will invalidate all outstanding iterators

(TTdaq Application v0.8b:16419): Gtk-CRITICAL **: file gtktextlayout.c: line 813 (gtk_text_layout_real_invalidate): assertion `layout->wrap_loop_count == 0' failed

(TTdaq Application v0.8b:18972): Gtk-CRITICAL **: file gtktextlayout.c: line 813 (gtk_text_layout_real_invalidate): assertion `layout->wrap_loop_count == 0' failed

(TTdaq Application v0.8b:18510): Gtk-CRITICAL **: file gtktextbuffer.c: line 1810 (gtk_text_buffer_get_iter_at_mark): assertion `!gtk_text_mark_get_deleted (mark)' failed

And sometimes... it crashes with a "Segmentation Fault".

I have already tried different implementation which doesn't work better ;-) !
One of them was to fill a std::queue and create a Glib thread for re-read it, and insert the messages into the Textview (a kind of producer/consummer)... But it crashes even more often !

Here is extracts of my application:

� enum LogType
� {
��� INFO,
��� WARNING,
��� ERROR
� };

� // This function is used by the different threads !
� void add(LogType l, std::string msg)
� {
��� pthread_mutex_lock(&pmut_log_update);

��� switch(l)
��� {
������ case INFO:
��� globalControlWidget->printInfoLog(msg);
��� break;
������ case WARNING:
��� globalControlWidget->printWarningLog(msg);
��� break;
������ case ERROR:
��� globalControlWidget->printErrorLog(msg);
��� break;
��� }
���
��� pthread_mutex_unlock(&pmut_log_update);�
� }

� ....
� /************************************************************/
� // The class GlobalControlWidget

� class GlobalControlWidget : public Gtk::VBox
� {
Gtk::TextView *logText;
Gtk::ScrolledWindow *logScrolledwindow;
Glib::RefPtr<Gtk::TextBuffer> refTextLogBuffer;
Glib::RefPtr<Gtk::TextBuffer::Tag> refTagError;
Glib::RefPtr<Gtk::TextBuffer::Tag> refTagWarning;
Glib::RefPtr<Gtk::TextBuffer::TagTable> refTagTable;
void scrollLogView();
��� public:
������� GlobalControlWidget(TTdaqMainWindow*);����
������� ~GlobalControlWidget();
void printInfoLog(const std::string &);
void printErrorLog(const std::string &);
void printWarningLog(const std::string &);
void updateStartStopBoutonsSensitivity();
� };



� GlobalControlWidget::GlobalControlWidget()
� {
�� logText = manage(new class Gtk::TextView());
�� logText->set_flags(Gtk::CAN_FOCUS);
�� logText->set_editable(false);
�� //refTextLogBuffer = Gtk::TextBuffer::create();
�� //logText->set_buffer(refTextLogBuffer);
�� refTextLogBuffer=logText->get_buffer();

�� refTextLogBuffer->signal_changed().connect( sigc::mem_fun(*this, &GlobalControlWidget::scrollLogView));

�� //Create a TagTable:
�� refTagTable = refTextLogBuffer->get_tag_table();

�� //Apply color to some text.
�� //Create the tags:
�� refTagWarning = Gtk::TextBuffer::Tag::create("Warning_Message"); //We give it an arbitrary name.
�� refTagWarning->property_background() = "orange";
�� refTagTable->add(refTagWarning);
�� refTagError = Gtk::TextBuffer::Tag::create("Error_Message"); //We give it an arbitrary name.
�� refTagError->property_background() = "red";
�� refTagTable->add(refTagError);
��
�� logScrolledwindow = manage(new class Gtk::ScrolledWindow());
�� logScrolledwindow->set_policy(Gtk::POLICY_NEVER, Gtk::POLICY_ALWAYS);
�� logScrolledwindow->add(*logText);�
�� Gtk::Frame *logFrame = manage(new class Gtk::Frame("Log"));
�� logFrame->set_shadow_type(Gtk::SHADOW_ETCHED_IN);
�� logFrame->set_label_align(0,0);
�� logFrame->add(*logScrolledwindow);
��
�� pack_start(*logFrame, true, true, 5);
�� show_all_children();
�� show();
�� set_redraw_on_allocate(true);
� }

� void GlobalControlWidget::printInfoLog(const std::string &msg)
� {
��� refTextLogBuffer->insert(refTextLogBuffer->end(), msg+"\n");
� }

� void GlobalControlWidget::printErrorLog(const std::string &msg)
� {
��� refTextLogBuffer->insert_with_tag(refTextLogBuffer->end(), msg+"\n", refTagError);
� }

� void GlobalControlWidget::printWarningLog(const std::string &msg)
� {
��� refTextLogBuffer->insert_with_tag(refTextLogBuffer->end(), msg+"\n", refTagWarning);
� }

� void GlobalControlWidget::scrollLogView()
� {
��� logText->scroll_mark_onscreen( refTextLogBuffer->get_insert() );
� }

Pleeaasse heelllpp !!!
Cheers,
DESCOMBES Thierry

_______________________________________________ gtkmm-list mailing list gtkmm-list gnome org http://mail.gnome.org/mailman/listinfo/gtkmm-list


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