Emitting signals from threads

classic Classic list List threaded Threaded
37 messages Options
12
Reply | Threaded
Open this post in threaded view
|

Emitting signals from threads

Gtk+ - General mailing list
Hi,

In my application, I want to be able to update a treeview from a separate thread. Each treeview row was a column that is a progress bar. The progress to be displayed is generated by a separate thread as to not block the UI.

Since GTK is not thread-safe, the way the application is written is that the thread, when it needs to emit a signal, will prepare the signal data and then call g_main_context_invoke_full(NULL, cb, data, ...) in order to be able to call g_singal_emit() in the global default context thread. The signal handler updates the tree model, which in turn updates the tree view.

For the most part this works with one big, ugly exception - the same treeview has a column, which is supposed to open the item's Edit dialog when clicked. So, naturally, I have a button-press handler connected to the treeview, which launches the Edit dialog when the button press occurs in the correct column.

However, when an update is running and the thread is continuously emitting signals, clicking on *any* column of *any* of the other items opens the Edit dialog. The treeview behaves as if the items in it have only one column.

Every example or document that I have seen in relation to signals from threads says to emit the signal from a g_idle_add() handler. However, g_main_context_invoke_full(NULL, ...) should be the same as calling g_idle_add().

Can someone shed some light into what might be happening?

Thank you.



_______________________________________________
gtk-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtk-list
Reply | Threaded
Open this post in threaded view
|

Re: Emitting signals from threads

Gtk+ - General mailing list
Hi Mitko! Can you post here the code for the button-press event handler?
It should more or less follow the code here: http://scentric.net/tutorial/sec-misc-get-renderer-from-click.html

Luca

Il giorno lun 17 dic 2018 alle ore 20:28 Mitko Haralanov via gtk-list <[hidden email]> ha scritto:
Hi,

In my application, I want to be able to update a treeview from a separate thread. Each treeview row was a column that is a progress bar. The progress to be displayed is generated by a separate thread as to not block the UI.

Since GTK is not thread-safe, the way the application is written is that the thread, when it needs to emit a signal, will prepare the signal data and then call g_main_context_invoke_full(NULL, cb, data, ...) in order to be able to call g_singal_emit() in the global default context thread. The signal handler updates the tree model, which in turn updates the tree view.

For the most part this works with one big, ugly exception - the same treeview has a column, which is supposed to open the item's Edit dialog when clicked. So, naturally, I have a button-press handler connected to the treeview, which launches the Edit dialog when the button press occurs in the correct column.

However, when an update is running and the thread is continuously emitting signals, clicking on *any* column of *any* of the other items opens the Edit dialog. The treeview behaves as if the items in it have only one column.

Every example or document that I have seen in relation to signals from threads says to emit the signal from a g_idle_add() handler. However, g_main_context_invoke_full(NULL, ...) should be the same as calling g_idle_add().

Can someone shed some light into what might be happening?

Thank you.


_______________________________________________
gtk-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtk-list

_______________________________________________
gtk-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtk-list
Reply | Threaded
Open this post in threaded view
|

Fwd: Emitting signals from threads

Gtk+ - General mailing list
I mistakenly replied only to Luca!! Forwarding to the list.

(Sorry, Luca, my bad)
- Mitko

---------- Forwarded message ---------
From: Mitko Haralanov <[hidden email]>
Date: Tue, Dec 18, 2018 at 9:37 AM
Subject: Re: Emitting signals from threads
To: Luca Bacci <[hidden email]>


I found something that is different between the two cases - button click with signals and without.

Using the code from the link that Luca posted, I decided to print the size of each column when a button press is received. As it turns out, the width of the columns is different in the two cases:

Without thread signals:
column[0](193) = 0 -> 193
cell[0] = min->109, natural->109
column[1](66) = 193 -> 259
cell[0] = min->20, natural->20
cell[1] = min->16, natural->16
cell[2] = min->35, natural->35
column[2](36) = 259 -> 295
cell[0] = min->16, natural->16
x = 105.872116, y = 259.547516

(x and y are the coordinates of the button press event)

With thread signals:
column[0](0) = 0 -> 0
cell[0] = min->135, natural->135
column[1](66) = 0 -> 66
cell[0] = min->20, natural->20
cell[1] = min->16, natural->16
cell[2] = min->35, natural->35
column[2](36) = 66 -> 102
cell[0] = min->16, natural->16
x = 113.528488, y = 158.563782

As you can see, the width of the first column is 0 when the signals are being emitted. As expected, if I were to click very close to the left border of the widget, the edit dialog does not get triggered as the x coordinate falls within column 1:

column[0](0) = 0 -> 0
cell[0] = min->135, natural->135
column[1](66) = 0 -> 66
cell[0] = min->20, natural->20
cell[1] = min->16, natural->16
cell[2] = min->35, natural->35
column[2](36) = 66 -> 102
cell[0] = min->16, natural->16
x = 21.247330, y = 181.310333

I could use the cell renderer width if the column width is 0 but that seems unreliable since the cell renderer width is not the same as the column and it's also not static.

On Tue, Dec 18, 2018 at 8:23 AM Mitko Haralanov <[hidden email]> wrote:
I am not posting the complete function because there is a lot of irrelevant code. I am also not interested in the specific cell renderer but rather the row on which the click occurred.

tatic gboolean on_button_press_event(GtkWidget *widget,
      GdkEvent *event,
      gpointer data)
{
GtkTreeView *treeview = GTK_TREE_VIEW(widget);
GdkEventButton *button = (GdkEventButton *)event;
GtkTreeModel *model;
GtkTreePath *path;
GtkTreeIter iter;
GtkTreeViewColumn *column;
GtkScopeProjectEditDialog *dialog;
GtkScopeProjectEditData *pdata, fill;
GtkScopeProject *project;
guint response, index;
gboolean ret = FALSE;

if (button->type != GDK_BUTTON_PRESS ||
    !gtk_tree_view_get_path_at_pos(treeview, button->x, button->y,
   &path, &column, NULL, NULL))
return FALSE;

index = GPOINTER_TO_UINT(g_object_get_data(G_OBJECT(column), "index"));
if (index != TREEVIEW_COLUMN_EDIT)
goto done;
model = gtk_tree_view_get_model(treeview);
if (!gtk_tree_model_get_iter(model, &iter, path))
goto done;
gtk_tree_model_get(model, &iter, PROJECT_COLUMN_OBJ, &project, -1);
        ...

The issue is that the column which is returned by gtk_tree_view_get_path_at_pos() is different depending on whether thread signals are being emitted vs not. I have verified that the button press coordinates are the same (button->x and button->y have the same values in both cases).


On Tue, Dec 18, 2018 at 5:24 AM Luca Bacci <[hidden email]> wrote:
Hi Mitko! Can you post here the code for the button-press event handler?
It should more or less follow the code here: http://scentric.net/tutorial/sec-misc-get-renderer-from-click.html

Luca

Il giorno lun 17 dic 2018 alle ore 20:28 Mitko Haralanov via gtk-list <[hidden email]> ha scritto:
Hi,

In my application, I want to be able to update a treeview from a separate thread. Each treeview row was a column that is a progress bar. The progress to be displayed is generated by a separate thread as to not block the UI.

Since GTK is not thread-safe, the way the application is written is that the thread, when it needs to emit a signal, will prepare the signal data and then call g_main_context_invoke_full(NULL, cb, data, ...) in order to be able to call g_singal_emit() in the global default context thread. The signal handler updates the tree model, which in turn updates the tree view.

For the most part this works with one big, ugly exception - the same treeview has a column, which is supposed to open the item's Edit dialog when clicked. So, naturally, I have a button-press handler connected to the treeview, which launches the Edit dialog when the button press occurs in the correct column.

However, when an update is running and the thread is continuously emitting signals, clicking on *any* column of *any* of the other items opens the Edit dialog. The treeview behaves as if the items in it have only one column.

Every example or document that I have seen in relation to signals from threads says to emit the signal from a g_idle_add() handler. However, g_main_context_invoke_full(NULL, ...) should be the same as calling g_idle_add().

Can someone shed some light into what might be happening?

Thank you.


_______________________________________________
gtk-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtk-list

_______________________________________________
gtk-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtk-list
Reply | Threaded
Open this post in threaded view
|

Re: Emitting signals from threads

Gtk+ - General mailing list
Is it Gtk2 or Gtk3, which version exactly?


Il giorno mar 18 dic 2018 alle ore 18:47 Mitko Haralanov via gtk-list <[hidden email]> ha scritto:
I mistakenly replied only to Luca!! Forwarding to the list.

(Sorry, Luca, my bad)
- Mitko

---------- Forwarded message ---------
From: Mitko Haralanov <[hidden email]>
Date: Tue, Dec 18, 2018 at 9:37 AM
Subject: Re: Emitting signals from threads
To: Luca Bacci <[hidden email]>


I found something that is different between the two cases - button click with signals and without.

Using the code from the link that Luca posted, I decided to print the size of each column when a button press is received. As it turns out, the width of the columns is different in the two cases:

Without thread signals:
column[0](193) = 0 -> 193
cell[0] = min->109, natural->109
column[1](66) = 193 -> 259
cell[0] = min->20, natural->20
cell[1] = min->16, natural->16
cell[2] = min->35, natural->35
column[2](36) = 259 -> 295
cell[0] = min->16, natural->16
x = 105.872116, y = 259.547516

(x and y are the coordinates of the button press event)

With thread signals:
column[0](0) = 0 -> 0
cell[0] = min->135, natural->135
column[1](66) = 0 -> 66
cell[0] = min->20, natural->20
cell[1] = min->16, natural->16
cell[2] = min->35, natural->35
column[2](36) = 66 -> 102
cell[0] = min->16, natural->16
x = 113.528488, y = 158.563782

As you can see, the width of the first column is 0 when the signals are being emitted. As expected, if I were to click very close to the left border of the widget, the edit dialog does not get triggered as the x coordinate falls within column 1:

column[0](0) = 0 -> 0
cell[0] = min->135, natural->135
column[1](66) = 0 -> 66
cell[0] = min->20, natural->20
cell[1] = min->16, natural->16
cell[2] = min->35, natural->35
column[2](36) = 66 -> 102
cell[0] = min->16, natural->16
x = 21.247330, y = 181.310333

I could use the cell renderer width if the column width is 0 but that seems unreliable since the cell renderer width is not the same as the column and it's also not static.

On Tue, Dec 18, 2018 at 8:23 AM Mitko Haralanov <[hidden email]> wrote:
I am not posting the complete function because there is a lot of irrelevant code. I am also not interested in the specific cell renderer but rather the row on which the click occurred.

tatic gboolean on_button_press_event(GtkWidget *widget,
      GdkEvent *event,
      gpointer data)
{
GtkTreeView *treeview = GTK_TREE_VIEW(widget);
GdkEventButton *button = (GdkEventButton *)event;
GtkTreeModel *model;
GtkTreePath *path;
GtkTreeIter iter;
GtkTreeViewColumn *column;
GtkScopeProjectEditDialog *dialog;
GtkScopeProjectEditData *pdata, fill;
GtkScopeProject *project;
guint response, index;
gboolean ret = FALSE;

if (button->type != GDK_BUTTON_PRESS ||
    !gtk_tree_view_get_path_at_pos(treeview, button->x, button->y,
   &path, &column, NULL, NULL))
return FALSE;

index = GPOINTER_TO_UINT(g_object_get_data(G_OBJECT(column), "index"));
if (index != TREEVIEW_COLUMN_EDIT)
goto done;
model = gtk_tree_view_get_model(treeview);
if (!gtk_tree_model_get_iter(model, &iter, path))
goto done;
gtk_tree_model_get(model, &iter, PROJECT_COLUMN_OBJ, &project, -1);
        ...

The issue is that the column which is returned by gtk_tree_view_get_path_at_pos() is different depending on whether thread signals are being emitted vs not. I have verified that the button press coordinates are the same (button->x and button->y have the same values in both cases).


On Tue, Dec 18, 2018 at 5:24 AM Luca Bacci <[hidden email]> wrote:
Hi Mitko! Can you post here the code for the button-press event handler?
It should more or less follow the code here: http://scentric.net/tutorial/sec-misc-get-renderer-from-click.html

Luca

Il giorno lun 17 dic 2018 alle ore 20:28 Mitko Haralanov via gtk-list <[hidden email]> ha scritto:
Hi,

In my application, I want to be able to update a treeview from a separate thread. Each treeview row was a column that is a progress bar. The progress to be displayed is generated by a separate thread as to not block the UI.

Since GTK is not thread-safe, the way the application is written is that the thread, when it needs to emit a signal, will prepare the signal data and then call g_main_context_invoke_full(NULL, cb, data, ...) in order to be able to call g_singal_emit() in the global default context thread. The signal handler updates the tree model, which in turn updates the tree view.

For the most part this works with one big, ugly exception - the same treeview has a column, which is supposed to open the item's Edit dialog when clicked. So, naturally, I have a button-press handler connected to the treeview, which launches the Edit dialog when the button press occurs in the correct column.

However, when an update is running and the thread is continuously emitting signals, clicking on *any* column of *any* of the other items opens the Edit dialog. The treeview behaves as if the items in it have only one column.

Every example or document that I have seen in relation to signals from threads says to emit the signal from a g_idle_add() handler. However, g_main_context_invoke_full(NULL, ...) should be the same as calling g_idle_add().

Can someone shed some light into what might be happening?

Thank you.


_______________________________________________
gtk-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtk-list
_______________________________________________
gtk-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtk-list

_______________________________________________
gtk-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtk-list
Reply | Threaded
Open this post in threaded view
|

Re: Emitting signals from threads

Gtk+ - General mailing list
This is Gtk3:
gtk3-3.22.26-2.fc27.x86_64

On Tue, Dec 18, 2018 at 1:14 PM Luca Bacci via gtk-list <[hidden email]> wrote:
Is it Gtk2 or Gtk3, which version exactly?


Il giorno mar 18 dic 2018 alle ore 18:47 Mitko Haralanov via gtk-list <[hidden email]> ha scritto:
I mistakenly replied only to Luca!! Forwarding to the list.

(Sorry, Luca, my bad)
- Mitko

---------- Forwarded message ---------
From: Mitko Haralanov <[hidden email]>
Date: Tue, Dec 18, 2018 at 9:37 AM
Subject: Re: Emitting signals from threads
To: Luca Bacci <[hidden email]>


I found something that is different between the two cases - button click with signals and without.

Using the code from the link that Luca posted, I decided to print the size of each column when a button press is received. As it turns out, the width of the columns is different in the two cases:

Without thread signals:
column[0](193) = 0 -> 193
cell[0] = min->109, natural->109
column[1](66) = 193 -> 259
cell[0] = min->20, natural->20
cell[1] = min->16, natural->16
cell[2] = min->35, natural->35
column[2](36) = 259 -> 295
cell[0] = min->16, natural->16
x = 105.872116, y = 259.547516

(x and y are the coordinates of the button press event)

With thread signals:
column[0](0) = 0 -> 0
cell[0] = min->135, natural->135
column[1](66) = 0 -> 66
cell[0] = min->20, natural->20
cell[1] = min->16, natural->16
cell[2] = min->35, natural->35
column[2](36) = 66 -> 102
cell[0] = min->16, natural->16
x = 113.528488, y = 158.563782

As you can see, the width of the first column is 0 when the signals are being emitted. As expected, if I were to click very close to the left border of the widget, the edit dialog does not get triggered as the x coordinate falls within column 1:

column[0](0) = 0 -> 0
cell[0] = min->135, natural->135
column[1](66) = 0 -> 66
cell[0] = min->20, natural->20
cell[1] = min->16, natural->16
cell[2] = min->35, natural->35
column[2](36) = 66 -> 102
cell[0] = min->16, natural->16
x = 21.247330, y = 181.310333

I could use the cell renderer width if the column width is 0 but that seems unreliable since the cell renderer width is not the same as the column and it's also not static.

On Tue, Dec 18, 2018 at 8:23 AM Mitko Haralanov <[hidden email]> wrote:
I am not posting the complete function because there is a lot of irrelevant code. I am also not interested in the specific cell renderer but rather the row on which the click occurred.

tatic gboolean on_button_press_event(GtkWidget *widget,
      GdkEvent *event,
      gpointer data)
{
GtkTreeView *treeview = GTK_TREE_VIEW(widget);
GdkEventButton *button = (GdkEventButton *)event;
GtkTreeModel *model;
GtkTreePath *path;
GtkTreeIter iter;
GtkTreeViewColumn *column;
GtkScopeProjectEditDialog *dialog;
GtkScopeProjectEditData *pdata, fill;
GtkScopeProject *project;
guint response, index;
gboolean ret = FALSE;

if (button->type != GDK_BUTTON_PRESS ||
    !gtk_tree_view_get_path_at_pos(treeview, button->x, button->y,
   &path, &column, NULL, NULL))
return FALSE;

index = GPOINTER_TO_UINT(g_object_get_data(G_OBJECT(column), "index"));
if (index != TREEVIEW_COLUMN_EDIT)
goto done;
model = gtk_tree_view_get_model(treeview);
if (!gtk_tree_model_get_iter(model, &iter, path))
goto done;
gtk_tree_model_get(model, &iter, PROJECT_COLUMN_OBJ, &project, -1);
        ...

The issue is that the column which is returned by gtk_tree_view_get_path_at_pos() is different depending on whether thread signals are being emitted vs not. I have verified that the button press coordinates are the same (button->x and button->y have the same values in both cases).


On Tue, Dec 18, 2018 at 5:24 AM Luca Bacci <[hidden email]> wrote:
Hi Mitko! Can you post here the code for the button-press event handler?
It should more or less follow the code here: http://scentric.net/tutorial/sec-misc-get-renderer-from-click.html

Luca

Il giorno lun 17 dic 2018 alle ore 20:28 Mitko Haralanov via gtk-list <[hidden email]> ha scritto:
Hi,

In my application, I want to be able to update a treeview from a separate thread. Each treeview row was a column that is a progress bar. The progress to be displayed is generated by a separate thread as to not block the UI.

Since GTK is not thread-safe, the way the application is written is that the thread, when it needs to emit a signal, will prepare the signal data and then call g_main_context_invoke_full(NULL, cb, data, ...) in order to be able to call g_singal_emit() in the global default context thread. The signal handler updates the tree model, which in turn updates the tree view.

For the most part this works with one big, ugly exception - the same treeview has a column, which is supposed to open the item's Edit dialog when clicked. So, naturally, I have a button-press handler connected to the treeview, which launches the Edit dialog when the button press occurs in the correct column.

However, when an update is running and the thread is continuously emitting signals, clicking on *any* column of *any* of the other items opens the Edit dialog. The treeview behaves as if the items in it have only one column.

Every example or document that I have seen in relation to signals from threads says to emit the signal from a g_idle_add() handler. However, g_main_context_invoke_full(NULL, ...) should be the same as calling g_idle_add().

Can someone shed some light into what might be happening?

Thank you.


_______________________________________________
gtk-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtk-list
_______________________________________________
gtk-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtk-list
_______________________________________________
gtk-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtk-list

_______________________________________________
gtk-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtk-list
Reply | Threaded
Open this post in threaded view
|

Re: Emitting signals from threads

Gtk+ - General mailing list
Anyone have any ideas? I still can't figure out why the column sizes go to 0.

Thank you.

On Tue, Dec 18, 2018, 13:40 Mitko Haralanov <[hidden email] wrote:
This is Gtk3:
gtk3-3.22.26-2.fc27.x86_64

On Tue, Dec 18, 2018 at 1:14 PM Luca Bacci via gtk-list <[hidden email]> wrote:
Is it Gtk2 or Gtk3, which version exactly?


Il giorno mar 18 dic 2018 alle ore 18:47 Mitko Haralanov via gtk-list <[hidden email]> ha scritto:
I mistakenly replied only to Luca!! Forwarding to the list.

(Sorry, Luca, my bad)
- Mitko

---------- Forwarded message ---------
From: Mitko Haralanov <[hidden email]>
Date: Tue, Dec 18, 2018 at 9:37 AM
Subject: Re: Emitting signals from threads
To: Luca Bacci <[hidden email]>


I found something that is different between the two cases - button click with signals and without.

Using the code from the link that Luca posted, I decided to print the size of each column when a button press is received. As it turns out, the width of the columns is different in the two cases:

Without thread signals:
column[0](193) = 0 -> 193
cell[0] = min->109, natural->109
column[1](66) = 193 -> 259
cell[0] = min->20, natural->20
cell[1] = min->16, natural->16
cell[2] = min->35, natural->35
column[2](36) = 259 -> 295
cell[0] = min->16, natural->16
x = 105.872116, y = 259.547516

(x and y are the coordinates of the button press event)

With thread signals:
column[0](0) = 0 -> 0
cell[0] = min->135, natural->135
column[1](66) = 0 -> 66
cell[0] = min->20, natural->20
cell[1] = min->16, natural->16
cell[2] = min->35, natural->35
column[2](36) = 66 -> 102
cell[0] = min->16, natural->16
x = 113.528488, y = 158.563782

As you can see, the width of the first column is 0 when the signals are being emitted. As expected, if I were to click very close to the left border of the widget, the edit dialog does not get triggered as the x coordinate falls within column 1:

column[0](0) = 0 -> 0
cell[0] = min->135, natural->135
column[1](66) = 0 -> 66
cell[0] = min->20, natural->20
cell[1] = min->16, natural->16
cell[2] = min->35, natural->35
column[2](36) = 66 -> 102
cell[0] = min->16, natural->16
x = 21.247330, y = 181.310333

I could use the cell renderer width if the column width is 0 but that seems unreliable since the cell renderer width is not the same as the column and it's also not static.

On Tue, Dec 18, 2018 at 8:23 AM Mitko Haralanov <[hidden email]> wrote:
I am not posting the complete function because there is a lot of irrelevant code. I am also not interested in the specific cell renderer but rather the row on which the click occurred.

tatic gboolean on_button_press_event(GtkWidget *widget,
      GdkEvent *event,
      gpointer data)
{
GtkTreeView *treeview = GTK_TREE_VIEW(widget);
GdkEventButton *button = (GdkEventButton *)event;
GtkTreeModel *model;
GtkTreePath *path;
GtkTreeIter iter;
GtkTreeViewColumn *column;
GtkScopeProjectEditDialog *dialog;
GtkScopeProjectEditData *pdata, fill;
GtkScopeProject *project;
guint response, index;
gboolean ret = FALSE;

if (button->type != GDK_BUTTON_PRESS ||
    !gtk_tree_view_get_path_at_pos(treeview, button->x, button->y,
   &path, &column, NULL, NULL))
return FALSE;

index = GPOINTER_TO_UINT(g_object_get_data(G_OBJECT(column), "index"));
if (index != TREEVIEW_COLUMN_EDIT)
goto done;
model = gtk_tree_view_get_model(treeview);
if (!gtk_tree_model_get_iter(model, &iter, path))
goto done;
gtk_tree_model_get(model, &iter, PROJECT_COLUMN_OBJ, &project, -1);
        ...

The issue is that the column which is returned by gtk_tree_view_get_path_at_pos() is different depending on whether thread signals are being emitted vs not. I have verified that the button press coordinates are the same (button->x and button->y have the same values in both cases).


On Tue, Dec 18, 2018 at 5:24 AM Luca Bacci <[hidden email]> wrote:
Hi Mitko! Can you post here the code for the button-press event handler?
It should more or less follow the code here: http://scentric.net/tutorial/sec-misc-get-renderer-from-click.html

Luca

Il giorno lun 17 dic 2018 alle ore 20:28 Mitko Haralanov via gtk-list <[hidden email]> ha scritto:
Hi,

In my application, I want to be able to update a treeview from a separate thread. Each treeview row was a column that is a progress bar. The progress to be displayed is generated by a separate thread as to not block the UI.

Since GTK is not thread-safe, the way the application is written is that the thread, when it needs to emit a signal, will prepare the signal data and then call g_main_context_invoke_full(NULL, cb, data, ...) in order to be able to call g_singal_emit() in the global default context thread. The signal handler updates the tree model, which in turn updates the tree view.

For the most part this works with one big, ugly exception - the same treeview has a column, which is supposed to open the item's Edit dialog when clicked. So, naturally, I have a button-press handler connected to the treeview, which launches the Edit dialog when the button press occurs in the correct column.

However, when an update is running and the thread is continuously emitting signals, clicking on *any* column of *any* of the other items opens the Edit dialog. The treeview behaves as if the items in it have only one column.

Every example or document that I have seen in relation to signals from threads says to emit the signal from a g_idle_add() handler. However, g_main_context_invoke_full(NULL, ...) should be the same as calling g_idle_add().

Can someone shed some light into what might be happening?

Thank you.


_______________________________________________
gtk-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtk-list
_______________________________________________
gtk-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtk-list
_______________________________________________
gtk-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtk-list

_______________________________________________
gtk-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtk-list
Reply | Threaded
Open this post in threaded view
|

Re: Emitting signals from threads

ente
Hi,


I am not sure with my answer. Treat it as unreliable.

There seems to be a difference between g_idle_add
and g_main_context_invoke_full. While the documentation of idle_add
says:
"Adds a function to be called [...] to the default main loop." (i.e.
main thread / the only gtk-thread) g_main_context_invoke_full does not
mention the main loop - although it mentions a "context" which I have
no experience with and which may be related to the main loop. So maybe
you must retrieve the correct context using g_main_context_default or
g_main_context_acquire. Keep in mind: glib is thread safe, gtk is not.
g_main_context_invoke_full may support glib multi threading while
g_idle_add clearly sends your function call to the gtk thread.

The effect you are describing makes sense to me. The effects you
observe sound very much like race conditions in the treeview event
handler.

Why aren't you using g_idle_add in the first place? In my experience
this works like a charm. Be careful with one thing tho: The main loop
has a "todo-list". Each time you call "g_idle_add" it adds an item to
that todo-list and schedules a call to your function. If your function
doesn't return false, it won't even be taken down from the todo-list.
Each click event ends on that todo-list. Each column resize adds
multiple items to that todo-list (depending on your column resize
policy and the number of rows). As soon as you add more items to that
list, your UI becomes unresponsive. It seems advisable to build your
own shadow todo-list for the update process, i.e.:
* setup a function "update_progress"
* on the first threaded update event, call idle_add for the function
and put the new progress and the row number in your own data structure
* while the function is still "planned in for idle_add", just add new
events to your own data structure
* process 1 to 10 (maybe some more) events on each of the calls
* the function returns true as long as there is still some events in
your own list; it returns false otherwise
* apply mutex checks on your data structure (not sure if i should
mention, I am sure you had this in your mind already)

Each time you update a progress bar in your treeview, several (at least
one) events are added to the gtk-todo list (repaint!, re-order? and
maybe some more). Doing multiple progress events at once may lower the
amount of events, gtk has to process (a re-order affects all rows -
doing an update on multiple rows does not change anything here).

That's my 5 cents. I hope it helped a bit.


regards,


ente


On Mon, 2019-01-07 at 08:28 -0800, Mitko Haralanov via gtk-list wrote:

> Anyone have any ideas? I still can't figure out why the column sizes
> go to
> 0.
>
> Thank you.
>
> On Tue, Dec 18, 2018, 13:40 Mitko Haralanov <
> [hidden email]
>  wrote:
>
> > This is Gtk3:
> > gtk3-3.22.26-2.fc27.x86_64
> >
> > On Tue, Dec 18, 2018 at 1:14 PM Luca Bacci via gtk-list <
> > [hidden email]
> > > wrote:
> >
> > > Is it Gtk2 or Gtk3, which version exactly?
> > >
> > >
> > > Il giorno mar 18 dic 2018 alle ore 18:47 Mitko Haralanov via gtk-
> > > list <
> > > [hidden email]
> > > > ha scritto:
> > >
> > > > I mistakenly replied only to Luca!! Forwarding to the list.
> > > >
> > > > (Sorry, Luca, my bad)
> > > > - Mitko
> > > >
> > > > ---------- Forwarded message ---------
> > > > From: Mitko Haralanov <
> > > > [hidden email]
> > > > >
> > > > Date: Tue, Dec 18, 2018 at 9:37 AM
> > > > Subject: Re: Emitting signals from threads
> > > > To: Luca Bacci <
> > > > [hidden email]
> > > > >
> > > >
> > > >
> > > > I found something that is different between the two cases -
> > > > button click
> > > > with signals and without.
> > > >
> > > > Using the code from the link that Luca posted, I decided to
> > > > print the
> > > > size of each column when a button press is received. As it
> > > > turns out, the
> > > > width of the columns is different in the two cases:
> > > >
> > > > Without thread signals:
> > > > column[0](193) = 0 -> 193
> > > > cell[0] = min->109, natural->109
> > > > column[1](66) = 193 -> 259
> > > > cell[0] = min->20, natural->20
> > > > cell[1] = min->16, natural->16
> > > > cell[2] = min->35, natural->35
> > > > column[2](36) = 259 -> 295
> > > > cell[0] = min->16, natural->16
> > > > x = 105.872116, y = 259.547516
> > > >
> > > > (x and y are the coordinates of the button press event)
> > > >
> > > > With thread signals:
> > > > column[0](0) = 0 -> 0
> > > > cell[0] = min->135, natural->135
> > > > column[1](66) = 0 -> 66
> > > > cell[0] = min->20, natural->20
> > > > cell[1] = min->16, natural->16
> > > > cell[2] = min->35, natural->35
> > > > column[2](36) = 66 -> 102
> > > > cell[0] = min->16, natural->16
> > > > x = 113.528488, y = 158.563782
> > > >
> > > > As you can see, the width of the first column is 0 when the
> > > > signals are
> > > > being emitted. As expected, if I were to click very close to
> > > > the left
> > > > border of the widget, the edit dialog does not get triggered as
> > > > the x
> > > > coordinate falls within column 1:
> > > >
> > > > column[0](0) = 0 -> 0
> > > > cell[0] = min->135, natural->135
> > > > column[1](66) = 0 -> 66
> > > > cell[0] = min->20, natural->20
> > > > cell[1] = min->16, natural->16
> > > > cell[2] = min->35, natural->35
> > > > column[2](36) = 66 -> 102
> > > > cell[0] = min->16, natural->16
> > > > x = 21.247330, y = 181.310333
> > > >
> > > > I could use the cell renderer width if the column width is 0
> > > > but that
> > > > seems unreliable since the cell renderer width is not the same
> > > > as the
> > > > column and it's also not static.
> > > >
> > > > On Tue, Dec 18, 2018 at 8:23 AM Mitko Haralanov <
> > > > [hidden email]
> > > > >
> > > > wrote:
> > > >
> > > > > I am not posting the complete function because there is a lot
> > > > > of
> > > > > irrelevant code. I am also not interested in the specific
> > > > > cell renderer but
> > > > > rather the row on which the click occurred.
> > > > >
> > > > > tatic gboolean on_button_press_event(GtkWidget *widget,
> > > > >       GdkEvent *event,
> > > > >       gpointer data)
> > > > > {
> > > > > GtkTreeView *treeview = GTK_TREE_VIEW(widget);
> > > > > GdkEventButton *button = (GdkEventButton *)event;
> > > > > GtkTreeModel *model;
> > > > > GtkTreePath *path;
> > > > > GtkTreeIter iter;
> > > > > GtkTreeViewColumn *column;
> > > > > GtkScopeProjectEditDialog *dialog;
> > > > > GtkScopeProjectEditData *pdata, fill;
> > > > > GtkScopeProject *project;
> > > > > guint response, index;
> > > > > gboolean ret = FALSE;
> > > > >
> > > > > if (button->type != GDK_BUTTON_PRESS ||
> > > > >     !gtk_tree_view_get_path_at_pos(treeview, button->x,
> > > > > button->y,
> > > > >    &path, &column, NULL, NULL))
> > > > > return FALSE;
> > > > >
> > > > > index = GPOINTER_TO_UINT(g_object_get_data(G_OBJECT(column),
> > > > > "index"));
> > > > > if (index != TREEVIEW_COLUMN_EDIT)
> > > > > goto done;
> > > > > model = gtk_tree_view_get_model(treeview);
> > > > > if (!gtk_tree_model_get_iter(model, &iter, path))
> > > > > goto done;
> > > > > gtk_tree_model_get(model, &iter, PROJECT_COLUMN_OBJ,
> > > > > &project, -1);
> > > > >         ...
> > > > >
> > > > > The issue is that the column which is returned by
> > > > > gtk_tree_view_get_path_at_pos() is different depending on
> > > > > whether thread
> > > > > signals are being emitted vs not. I have verified that the
> > > > > button press
> > > > > coordinates are the same (button->x and button->y have the
> > > > > same values in
> > > > > both cases).
> > > > >
> > > > >
> > > > > On Tue, Dec 18, 2018 at 5:24 AM Luca Bacci <
> > > > > [hidden email]
> > > > > >
> > > > > wrote:
> > > > >
> > > > > > Hi Mitko! Can you post here the code for the button-press
> > > > > > event
> > > > > > handler?
> > > > > > It should more or less follow the code here:
> > > > > > http://scentric.net/tutorial/sec-misc-get-renderer-from-click.html
> > > > > >
> > > > > >
> > > > > > Luca
> > > > > >
> > > > > > Il giorno lun 17 dic 2018 alle ore 20:28 Mitko Haralanov
> > > > > > via gtk-list <
> > > > > > [hidden email]
> > > > > > > ha scritto:
> > > > > >
> > > > > > > Hi,
> > > > > > >
> > > > > > > In my application, I want to be able to update a treeview
> > > > > > > from a
> > > > > > > separate thread. Each treeview row was a column that is a
> > > > > > > progress bar. The
> > > > > > > progress to be displayed is generated by a separate
> > > > > > > thread as to not block
> > > > > > > the UI.
> > > > > > >
> > > > > > > Since GTK is not thread-safe, the way the application is
> > > > > > > written is
> > > > > > > that the thread, when it needs to emit a signal, will
> > > > > > > prepare the signal
> > > > > > > data and then call g_main_context_invoke_full(NULL, cb,
> > > > > > > data, ...) in order
> > > > > > > to be able to call g_singal_emit() in the global default
> > > > > > > context thread.
> > > > > > > The signal handler updates the tree model, which in turn
> > > > > > > updates the tree
> > > > > > > view.
> > > > > > >
> > > > > > > For the most part this works with one big, ugly exception
> > > > > > > - the same
> > > > > > > treeview has a column, which is supposed to open the
> > > > > > > item's Edit dialog
> > > > > > > when clicked. So, naturally, I have a button-press
> > > > > > > handler connected to the
> > > > > > > treeview, which launches the Edit dialog when the button
> > > > > > > press occurs in
> > > > > > > the correct column.
> > > > > > >
> > > > > > > However, when an update is running and the thread is
> > > > > > > continuously
> > > > > > > emitting signals, clicking on *any* column of *any* of
> > > > > > > the other items
> > > > > > > opens the Edit dialog. The treeview behaves as if the
> > > > > > > items in it have only
> > > > > > > one column.
> > > > > > >
> > > > > > > Every example or document that I have seen in relation to
> > > > > > > signals
> > > > > > > from threads says to emit the signal from a g_idle_add()
> > > > > > > handler. However,
> > > > > > > g_main_context_invoke_full(NULL, ...) should be the same
> > > > > > > as calling
> > > > > > > g_idle_add().
> > > > > > >
> > > > > > > Can someone shed some light into what might be happening?
> > > > > > >
> > > > > > > Thank you.
> > > > > > >
> > > > > > >
> > > > > > > _______________________________________________
> > > > > > > gtk-list mailing list
> > > > > > > [hidden email]
> > > > > > >
> > > > > > > https://mail.gnome.org/mailman/listinfo/gtk-list
> > > > > > >
> > > > > > >
> > > > > >
> > > > > > _______________________________________________
> > > >
> > > > gtk-list mailing list
> > > > [hidden email]
> > > >
> > > > https://mail.gnome.org/mailman/listinfo/gtk-list
> > > >
> > > >
> > >
> > > _______________________________________________
> > > gtk-list mailing list
> > > [hidden email]
> > >
> > > https://mail.gnome.org/mailman/listinfo/gtk-list
> > >
> > >
>
> _______________________________________________
> gtk-list mailing list
> [hidden email]
>
> https://mail.gnome.org/mailman/listinfo/gtk-list
>



_______________________________________________
gtk-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtk-list
Reply | Threaded
Open this post in threaded view
|

Re: Emitting signals from threads

Gtk+ - General mailing list
Thanks for the reply.

When calling g_main_context_invoke_full(), I am using NULL as the
context pointer. According to the documentation of
g_main_context_invoke():

        "If context is NULL then the global default main context — as
returned by g_main_context_default() — is used."

So, the code should be using the correct context.

One of the main reasons why I am not using g_idle_add() is the timing
of the callback. I don't want to defer the processing of the callback
to the "idle" time since this is signal handling related. Another
advantage of g_main_context_invoke[_full]() is that it will check the
"context" of the caller and, if possible, will call the callback
directly:

       "If context is owned by the current thread, function is called
directly. Otherwise, if context is the thread-default main context of
the current thread and g_main_context_acquire()
       succeeds, then function is called and g_main_context_release()
is called afterwards.
       In any other case, an idle source is created to call function
and that source is attached to context (presumably to be run in
another thread). The idle source is attached with
       G_PRIORITY_DEFAULT priority. If you want a different priority,
use g_main_context_invoke_full()."

Your suggested implementation is basically the GLib's async queues.
Or, may be, a custom event source. However, it seems that
g_main_context_invoke_full() should be doing exactly that. With all
due respect, I also don't see how it would solve the issue. If the
current implementation has an problem with locking/race conditions,
would your suggested implementation suffer from the same issue since
it's using the same or similar mechanism for calling the callback?

Thank you,

Mitko


On Mon, Jan 7, 2019 at 3:54 PM ente <[hidden email]> wrote:

>
> Hi,
>
>
> I am not sure with my answer. Treat it as unreliable.
>
> There seems to be a difference between g_idle_add
> and g_main_context_invoke_full. While the documentation of idle_add
> says:
> "Adds a function to be called [...] to the default main loop." (i.e.
> main thread / the only gtk-thread) g_main_context_invoke_full does not
> mention the main loop - although it mentions a "context" which I have
> no experience with and which may be related to the main loop. So maybe
> you must retrieve the correct context using g_main_context_default or
> g_main_context_acquire. Keep in mind: glib is thread safe, gtk is not.
> g_main_context_invoke_full may support glib multi threading while
> g_idle_add clearly sends your function call to the gtk thread.
>
> The effect you are describing makes sense to me. The effects you
> observe sound very much like race conditions in the treeview event
> handler.
>
> Why aren't you using g_idle_add in the first place? In my experience
> this works like a charm. Be careful with one thing tho: The main loop
> has a "todo-list". Each time you call "g_idle_add" it adds an item to
> that todo-list and schedules a call to your function. If your function
> doesn't return false, it won't even be taken down from the todo-list.
> Each click event ends on that todo-list. Each column resize adds
> multiple items to that todo-list (depending on your column resize
> policy and the number of rows). As soon as you add more items to that
> list, your UI becomes unresponsive. It seems advisable to build your
> own shadow todo-list for the update process, i.e.:
> * setup a function "update_progress"
> * on the first threaded update event, call idle_add for the function
> and put the new progress and the row number in your own data structure
> * while the function is still "planned in for idle_add", just add new
> events to your own data structure
> * process 1 to 10 (maybe some more) events on each of the calls
> * the function returns true as long as there is still some events in
> your own list; it returns false otherwise
> * apply mutex checks on your data structure (not sure if i should
> mention, I am sure you had this in your mind already)
>
> Each time you update a progress bar in your treeview, several (at least
> one) events are added to the gtk-todo list (repaint!, re-order? and
> maybe some more). Doing multiple progress events at once may lower the
> amount of events, gtk has to process (a re-order affects all rows -
> doing an update on multiple rows does not change anything here).
>
> That's my 5 cents. I hope it helped a bit.
>
>
> regards,
>
>
> ente
>
>
> On Mon, 2019-01-07 at 08:28 -0800, Mitko Haralanov via gtk-list wrote:
> > Anyone have any ideas? I still can't figure out why the column sizes
> > go to
> > 0.
> >
> > Thank you.
> >
> > On Tue, Dec 18, 2018, 13:40 Mitko Haralanov <
> > [hidden email]
> >  wrote:
> >
> > > This is Gtk3:
> > > gtk3-3.22.26-2.fc27.x86_64
> > >
> > > On Tue, Dec 18, 2018 at 1:14 PM Luca Bacci via gtk-list <
> > > [hidden email]
> > > > wrote:
> > >
> > > > Is it Gtk2 or Gtk3, which version exactly?
> > > >
> > > >
> > > > Il giorno mar 18 dic 2018 alle ore 18:47 Mitko Haralanov via gtk-
> > > > list <
> > > > [hidden email]
> > > > > ha scritto:
> > > >
> > > > > I mistakenly replied only to Luca!! Forwarding to the list.
> > > > >
> > > > > (Sorry, Luca, my bad)
> > > > > - Mitko
> > > > >
> > > > > ---------- Forwarded message ---------
> > > > > From: Mitko Haralanov <
> > > > > [hidden email]
> > > > > >
> > > > > Date: Tue, Dec 18, 2018 at 9:37 AM
> > > > > Subject: Re: Emitting signals from threads
> > > > > To: Luca Bacci <
> > > > > [hidden email]
> > > > > >
> > > > >
> > > > >
> > > > > I found something that is different between the two cases -
> > > > > button click
> > > > > with signals and without.
> > > > >
> > > > > Using the code from the link that Luca posted, I decided to
> > > > > print the
> > > > > size of each column when a button press is received. As it
> > > > > turns out, the
> > > > > width of the columns is different in the two cases:
> > > > >
> > > > > Without thread signals:
> > > > > column[0](193) = 0 -> 193
> > > > > cell[0] = min->109, natural->109
> > > > > column[1](66) = 193 -> 259
> > > > > cell[0] = min->20, natural->20
> > > > > cell[1] = min->16, natural->16
> > > > > cell[2] = min->35, natural->35
> > > > > column[2](36) = 259 -> 295
> > > > > cell[0] = min->16, natural->16
> > > > > x = 105.872116, y = 259.547516
> > > > >
> > > > > (x and y are the coordinates of the button press event)
> > > > >
> > > > > With thread signals:
> > > > > column[0](0) = 0 -> 0
> > > > > cell[0] = min->135, natural->135
> > > > > column[1](66) = 0 -> 66
> > > > > cell[0] = min->20, natural->20
> > > > > cell[1] = min->16, natural->16
> > > > > cell[2] = min->35, natural->35
> > > > > column[2](36) = 66 -> 102
> > > > > cell[0] = min->16, natural->16
> > > > > x = 113.528488, y = 158.563782
> > > > >
> > > > > As you can see, the width of the first column is 0 when the
> > > > > signals are
> > > > > being emitted. As expected, if I were to click very close to
> > > > > the left
> > > > > border of the widget, the edit dialog does not get triggered as
> > > > > the x
> > > > > coordinate falls within column 1:
> > > > >
> > > > > column[0](0) = 0 -> 0
> > > > > cell[0] = min->135, natural->135
> > > > > column[1](66) = 0 -> 66
> > > > > cell[0] = min->20, natural->20
> > > > > cell[1] = min->16, natural->16
> > > > > cell[2] = min->35, natural->35
> > > > > column[2](36) = 66 -> 102
> > > > > cell[0] = min->16, natural->16
> > > > > x = 21.247330, y = 181.310333
> > > > >
> > > > > I could use the cell renderer width if the column width is 0
> > > > > but that
> > > > > seems unreliable since the cell renderer width is not the same
> > > > > as the
> > > > > column and it's also not static.
> > > > >
> > > > > On Tue, Dec 18, 2018 at 8:23 AM Mitko Haralanov <
> > > > > [hidden email]
> > > > > >
> > > > > wrote:
> > > > >
> > > > > > I am not posting the complete function because there is a lot
> > > > > > of
> > > > > > irrelevant code. I am also not interested in the specific
> > > > > > cell renderer but
> > > > > > rather the row on which the click occurred.
> > > > > >
> > > > > > tatic gboolean on_button_press_event(GtkWidget *widget,
> > > > > >       GdkEvent *event,
> > > > > >       gpointer data)
> > > > > > {
> > > > > > GtkTreeView *treeview = GTK_TREE_VIEW(widget);
> > > > > > GdkEventButton *button = (GdkEventButton *)event;
> > > > > > GtkTreeModel *model;
> > > > > > GtkTreePath *path;
> > > > > > GtkTreeIter iter;
> > > > > > GtkTreeViewColumn *column;
> > > > > > GtkScopeProjectEditDialog *dialog;
> > > > > > GtkScopeProjectEditData *pdata, fill;
> > > > > > GtkScopeProject *project;
> > > > > > guint response, index;
> > > > > > gboolean ret = FALSE;
> > > > > >
> > > > > > if (button->type != GDK_BUTTON_PRESS ||
> > > > > >     !gtk_tree_view_get_path_at_pos(treeview, button->x,
> > > > > > button->y,
> > > > > >    &path, &column, NULL, NULL))
> > > > > > return FALSE;
> > > > > >
> > > > > > index = GPOINTER_TO_UINT(g_object_get_data(G_OBJECT(column),
> > > > > > "index"));
> > > > > > if (index != TREEVIEW_COLUMN_EDIT)
> > > > > > goto done;
> > > > > > model = gtk_tree_view_get_model(treeview);
> > > > > > if (!gtk_tree_model_get_iter(model, &iter, path))
> > > > > > goto done;
> > > > > > gtk_tree_model_get(model, &iter, PROJECT_COLUMN_OBJ,
> > > > > > &project, -1);
> > > > > >         ...
> > > > > >
> > > > > > The issue is that the column which is returned by
> > > > > > gtk_tree_view_get_path_at_pos() is different depending on
> > > > > > whether thread
> > > > > > signals are being emitted vs not. I have verified that the
> > > > > > button press
> > > > > > coordinates are the same (button->x and button->y have the
> > > > > > same values in
> > > > > > both cases).
> > > > > >
> > > > > >
> > > > > > On Tue, Dec 18, 2018 at 5:24 AM Luca Bacci <
> > > > > > [hidden email]
> > > > > > >
> > > > > > wrote:
> > > > > >
> > > > > > > Hi Mitko! Can you post here the code for the button-press
> > > > > > > event
> > > > > > > handler?
> > > > > > > It should more or less follow the code here:
> > > > > > > http://scentric.net/tutorial/sec-misc-get-renderer-from-click.html
> > > > > > >
> > > > > > >
> > > > > > > Luca
> > > > > > >
> > > > > > > Il giorno lun 17 dic 2018 alle ore 20:28 Mitko Haralanov
> > > > > > > via gtk-list <
> > > > > > > [hidden email]
> > > > > > > > ha scritto:
> > > > > > >
> > > > > > > > Hi,
> > > > > > > >
> > > > > > > > In my application, I want to be able to update a treeview
> > > > > > > > from a
> > > > > > > > separate thread. Each treeview row was a column that is a
> > > > > > > > progress bar. The
> > > > > > > > progress to be displayed is generated by a separate
> > > > > > > > thread as to not block
> > > > > > > > the UI.
> > > > > > > >
> > > > > > > > Since GTK is not thread-safe, the way the application is
> > > > > > > > written is
> > > > > > > > that the thread, when it needs to emit a signal, will
> > > > > > > > prepare the signal
> > > > > > > > data and then call g_main_context_invoke_full(NULL, cb,
> > > > > > > > data, ...) in order
> > > > > > > > to be able to call g_singal_emit() in the global default
> > > > > > > > context thread.
> > > > > > > > The signal handler updates the tree model, which in turn
> > > > > > > > updates the tree
> > > > > > > > view.
> > > > > > > >
> > > > > > > > For the most part this works with one big, ugly exception
> > > > > > > > - the same
> > > > > > > > treeview has a column, which is supposed to open the
> > > > > > > > item's Edit dialog
> > > > > > > > when clicked. So, naturally, I have a button-press
> > > > > > > > handler connected to the
> > > > > > > > treeview, which launches the Edit dialog when the button
> > > > > > > > press occurs in
> > > > > > > > the correct column.
> > > > > > > >
> > > > > > > > However, when an update is running and the thread is
> > > > > > > > continuously
> > > > > > > > emitting signals, clicking on *any* column of *any* of
> > > > > > > > the other items
> > > > > > > > opens the Edit dialog. The treeview behaves as if the
> > > > > > > > items in it have only
> > > > > > > > one column.
> > > > > > > >
> > > > > > > > Every example or document that I have seen in relation to
> > > > > > > > signals
> > > > > > > > from threads says to emit the signal from a g_idle_add()
> > > > > > > > handler. However,
> > > > > > > > g_main_context_invoke_full(NULL, ...) should be the same
> > > > > > > > as calling
> > > > > > > > g_idle_add().
> > > > > > > >
> > > > > > > > Can someone shed some light into what might be happening?
> > > > > > > >
> > > > > > > > Thank you.
> > > > > > > >
> > > > > > > >
> > > > > > > > _______________________________________________
> > > > > > > > gtk-list mailing list
> > > > > > > > [hidden email]
> > > > > > > >
> > > > > > > > https://mail.gnome.org/mailman/listinfo/gtk-list
> > > > > > > >
> > > > > > > >
> > > > > > >
> > > > > > > _______________________________________________
> > > > >
> > > > > gtk-list mailing list
> > > > > [hidden email]
> > > > >
> > > > > https://mail.gnome.org/mailman/listinfo/gtk-list
> > > > >
> > > > >
> > > >
> > > > _______________________________________________
> > > > gtk-list mailing list
> > > > [hidden email]
> > > >
> > > > https://mail.gnome.org/mailman/listinfo/gtk-list
> > > >
> > > >
> >
> > _______________________________________________
> > gtk-list mailing list
> > [hidden email]
> >
> > https://mail.gnome.org/mailman/listinfo/gtk-list
> >
>
>
>
_______________________________________________
gtk-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtk-list
Reply | Threaded
Open this post in threaded view
|

Re: Emitting signals from threads

Gtk+ - General mailing list
On Tue, 8 Jan 2019 10:02:58 -0800
Mitko Haralanov via gtk-list <[hidden email]> wrote:

> Thanks for the reply.
>
> When calling g_main_context_invoke_full(), I am using NULL as the
> context pointer. According to the documentation of
> g_main_context_invoke():
>
>         "If context is NULL then the global default main context — as
> returned by g_main_context_default() — is used."
>
> So, the code should be using the correct context.
>
> One of the main reasons why I am not using g_idle_add() is the timing
> of the callback. I don't want to defer the processing of the callback
> to the "idle" time since this is signal handling related. Another
> advantage of g_main_context_invoke[_full]() is that it will check the
> "context" of the caller and, if possible, will call the callback
> directly:
>
>        "If context is owned by the current thread, function is called
> directly. Otherwise, if context is the thread-default main context of
> the current thread and g_main_context_acquire()
>        succeeds, then function is called and g_main_context_release()
> is called afterwards.
>        In any other case, an idle source is created to call function
> and that source is attached to context (presumably to be run in
> another thread). The idle source is attached with
>        G_PRIORITY_DEFAULT priority. If you want a different priority,
> use g_main_context_invoke_full()."
>
> Your suggested implementation is basically the GLib's async queues.
> Or, may be, a custom event source. However, it seems that
> g_main_context_invoke_full() should be doing exactly that. With all
> due respect, I also don't see how it would solve the issue. If the
> current implementation has an problem with locking/race conditions,
> would your suggested implementation suffer from the same issue since
> it's using the same or similar mechanism for calling the callback?

"With all due respect" this is fine, but I am not sure what more your
interlocutor can say.  If your code works with g_idle_add() but not
with g_main_context_invoke_full() then you have a timing issue in your
code caused by the fact that the callbacks for the default main loop via
g_main_context_invoke_full() may be executed before the callbacks for
earlier invocations of g_idle_add().

If it doesn't work with either of them then you have some other issue.
It is possible you have found a bug in glib but more likely you have
found a bug in your code.
_______________________________________________
gtk-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtk-list
Reply | Threaded
Open this post in threaded view
|

Re: Emitting signals from threads

Gtk+ - General mailing list
In reply to this post by Gtk+ - General mailing list
After some offline discussion, I decided to experiment with
g_idle_add_full() since that function seems to work for other people.

Unfortunately, it doesn't in my case. The width of the first column is
still 0 and bad behavior is reproducible:

column[0](0) = 0 -> 0
    cell[0] = min->102, natural->102, text->98
column[1](66) = 98 -> 164
    cell[0] = min->20, natural->20
    cell[1] = min->16, natural->16
    cell[2] = min->35, natural->35
column[2](36) = 164 -> 200
    cell[0] = min->16, natural->16
x = 138.000000, y = 274.000000

Looking at the code for g_main_context_invoke_full() and
g_idle_add_full(), as expected, the portion of
g_main_context_invoke_full() that deals with the idle source is
virtually identical to g_idle_add_full(). So, the issue is somewhere
deeper.

Are there any GLib or Gtk+ developers on this list that can offer any help?

On Tue, Jan 8, 2019 at 4:35 PM Lex Trotman <[hidden email]> wrote:

>
> "calling gtk functions from a thread would be possible only through
> g_idle_add()." thats my understanding from
> https://developer.gnome.org/gdk3/stable/gdk3-Threads.html and thats
> what our app does.  It never seems to be a  performance problem, the
> main thread continuously chews its way through the idle queue.
>
> Cheers
> Lex
>
> On Wed, 9 Jan 2019 at 10:17, Mitko Haralanov <[hidden email]> wrote:
> >
> > I havent looked at the actual code but I am willing to bet that the "idle source" is just using g_idle_add(). If so, g_main_context_invoke_full() is essentially the same.
> >
> > If not the case, calling gtk functions from a thread would be possible only through g_idle_add(). I would think that if that were the case, it would have been mentioned in the docs.
> >
> > Thank you,
> > Mitko
> >
> > On Tue, Jan 8, 2019, 16:11 Lex Trotman <[hidden email] wrote:
> >>
> >> Hi Mitko,
> >>
> >> Same problem, from g_main_context_invoke() "In any other case, an idle
> >> source is created to call function and that source is attached to
> >> context (presumably to be run in another thread)."
> >>
> >> Cheers
> >> Lex
> >>
> >> On Wed, 9 Jan 2019 at 09:55, Mitko Haralanov <[hidden email]> wrote:
> >> >
> >> > Hi Lex,
> >> >
> >> > That is for the "notify" callback, which only deals with free/release
> >> > of the "data" pointer. The "function" callback is different and should
> >> > be called from the context default thread (as the documentation
> >> > describes.)
> >> >
> >> > Thank you,
> >> > Mitko
> >> >
> >> > On Tue, Jan 8, 2019 at 3:44 PM Lex Trotman <[hidden email]> wrote:
> >> > >
> >> > > Mito,
> >> > >
> >> > > It seems to me that since the g_main_context_invoke_full() docs say
> >> > > "notify should not assume that it is called from any particular
> >> > > thread" that notify cannot call GTK functions since GTK is not thread
> >> > > safe.
> >> > >
> >> > > Cheers
> >> > > Lex
> >> > >
> >> > > PS I'm not on gtk-list and am not gonna join for one line, feel free to forward
> >> > >
> >> > > On Wed, 9 Jan 2019 at 04:03, Mitko Haralanov via gtk-list
> >> > > <[hidden email]> wrote:
> >> > > >
> >> > > > Thanks for the reply.
> >> > > >
> >> > > > When calling g_main_context_invoke_full(), I am using NULL as the
> >> > > > context pointer. According to the documentation of
> >> > > > g_main_context_invoke():
> >> > > >
> >> > > >         "If context is NULL then the global default main context — as
> >> > > > returned by g_main_context_default() — is used."
> >> > > >
> >> > > > So, the code should be using the correct context.
> >> > > >
> >> > > > One of the main reasons why I am not using g_idle_add() is the timing
> >> > > > of the callback. I don't want to defer the processing of the callback
> >> > > > to the "idle" time since this is signal handling related. Another
> >> > > > advantage of g_main_context_invoke[_full]() is that it will check the
> >> > > > "context" of the caller and, if possible, will call the callback
> >> > > > directly:
> >> > > >
> >> > > >        "If context is owned by the current thread, function is called
> >> > > > directly. Otherwise, if context is the thread-default main context of
> >> > > > the current thread and g_main_context_acquire()
> >> > > >        succeeds, then function is called and g_main_context_release()
> >> > > > is called afterwards.
> >> > > >        In any other case, an idle source is created to call function
> >> > > > and that source is attached to context (presumably to be run in
> >> > > > another thread). The idle source is attached with
> >> > > >        G_PRIORITY_DEFAULT priority. If you want a different priority,
> >> > > > use g_main_context_invoke_full()."
> >> > > >
> >> > > > Your suggested implementation is basically the GLib's async queues.
> >> > > > Or, may be, a custom event source. However, it seems that
> >> > > > g_main_context_invoke_full() should be doing exactly that. With all
> >> > > > due respect, I also don't see how it would solve the issue. If the
> >> > > > current implementation has an problem with locking/race conditions,
> >> > > > would your suggested implementation suffer from the same issue since
> >> > > > it's using the same or similar mechanism for calling the callback?
> >> > > >
> >> > > > Thank you,
> >> > > >
> >> > > > Mitko
> >> > > >
> >> > > >
> >> > > > On Mon, Jan 7, 2019 at 3:54 PM ente <[hidden email]> wrote:
> >> > > > >
> >> > > > > Hi,
> >> > > > >
> >> > > > >
> >> > > > > I am not sure with my answer. Treat it as unreliable.
> >> > > > >
> >> > > > > There seems to be a difference between g_idle_add
> >> > > > > and g_main_context_invoke_full. While the documentation of idle_add
> >> > > > > says:
> >> > > > > "Adds a function to be called [...] to the default main loop." (i.e.
> >> > > > > main thread / the only gtk-thread) g_main_context_invoke_full does not
> >> > > > > mention the main loop - although it mentions a "context" which I have
> >> > > > > no experience with and which may be related to the main loop. So maybe
> >> > > > > you must retrieve the correct context using g_main_context_default or
> >> > > > > g_main_context_acquire. Keep in mind: glib is thread safe, gtk is not.
> >> > > > > g_main_context_invoke_full may support glib multi threading while
> >> > > > > g_idle_add clearly sends your function call to the gtk thread.
> >> > > > >
> >> > > > > The effect you are describing makes sense to me. The effects you
> >> > > > > observe sound very much like race conditions in the treeview event
> >> > > > > handler.
> >> > > > >
> >> > > > > Why aren't you using g_idle_add in the first place? In my experience
> >> > > > > this works like a charm. Be careful with one thing tho: The main loop
> >> > > > > has a "todo-list". Each time you call "g_idle_add" it adds an item to
> >> > > > > that todo-list and schedules a call to your function. If your function
> >> > > > > doesn't return false, it won't even be taken down from the todo-list.
> >> > > > > Each click event ends on that todo-list. Each column resize adds
> >> > > > > multiple items to that todo-list (depending on your column resize
> >> > > > > policy and the number of rows). As soon as you add more items to that
> >> > > > > list, your UI becomes unresponsive. It seems advisable to build your
> >> > > > > own shadow todo-list for the update process, i.e.:
> >> > > > > * setup a function "update_progress"
> >> > > > > * on the first threaded update event, call idle_add for the function
> >> > > > > and put the new progress and the row number in your own data structure
> >> > > > > * while the function is still "planned in for idle_add", just add new
> >> > > > > events to your own data structure
> >> > > > > * process 1 to 10 (maybe some more) events on each of the calls
> >> > > > > * the function returns true as long as there is still some events in
> >> > > > > your own list; it returns false otherwise
> >> > > > > * apply mutex checks on your data structure (not sure if i should
> >> > > > > mention, I am sure you had this in your mind already)
> >> > > > >
> >> > > > > Each time you update a progress bar in your treeview, several (at least
> >> > > > > one) events are added to the gtk-todo list (repaint!, re-order? and
> >> > > > > maybe some more). Doing multiple progress events at once may lower the
> >> > > > > amount of events, gtk has to process (a re-order affects all rows -
> >> > > > > doing an update on multiple rows does not change anything here).
> >> > > > >
> >> > > > > That's my 5 cents. I hope it helped a bit.
> >> > > > >
> >> > > > >
> >> > > > > regards,
> >> > > > >
> >> > > > >
> >> > > > > ente
> >> > > > >
> >> > > > >
> >> > > > > On Mon, 2019-01-07 at 08:28 -0800, Mitko Haralanov via gtk-list wrote:
> >> > > > > > Anyone have any ideas? I still can't figure out why the column sizes
> >> > > > > > go to
> >> > > > > > 0.
> >> > > > > >
> >> > > > > > Thank you.
> >> > > > > >
> >> > > > > > On Tue, Dec 18, 2018, 13:40 Mitko Haralanov <
> >> > > > > > [hidden email]
> >> > > > > >  wrote:
> >> > > > > >
> >> > > > > > > This is Gtk3:
> >> > > > > > > gtk3-3.22.26-2.fc27.x86_64
> >> > > > > > >
> >> > > > > > > On Tue, Dec 18, 2018 at 1:14 PM Luca Bacci via gtk-list <
> >> > > > > > > [hidden email]
> >> > > > > > > > wrote:
> >> > > > > > >
> >> > > > > > > > Is it Gtk2 or Gtk3, which version exactly?
> >> > > > > > > >
> >> > > > > > > >
> >> > > > > > > > Il giorno mar 18 dic 2018 alle ore 18:47 Mitko Haralanov via gtk-
> >> > > > > > > > list <
> >> > > > > > > > [hidden email]
> >> > > > > > > > > ha scritto:
> >> > > > > > > >
> >> > > > > > > > > I mistakenly replied only to Luca!! Forwarding to the list.
> >> > > > > > > > >
> >> > > > > > > > > (Sorry, Luca, my bad)
> >> > > > > > > > > - Mitko
> >> > > > > > > > >
> >> > > > > > > > > ---------- Forwarded message ---------
> >> > > > > > > > > From: Mitko Haralanov <
> >> > > > > > > > > [hidden email]
> >> > > > > > > > > >
> >> > > > > > > > > Date: Tue, Dec 18, 2018 at 9:37 AM
> >> > > > > > > > > Subject: Re: Emitting signals from threads
> >> > > > > > > > > To: Luca Bacci <
> >> > > > > > > > > [hidden email]
> >> > > > > > > > > >
> >> > > > > > > > >
> >> > > > > > > > >
> >> > > > > > > > > I found something that is different between the two cases -
> >> > > > > > > > > button click
> >> > > > > > > > > with signals and without.
> >> > > > > > > > >
> >> > > > > > > > > Using the code from the link that Luca posted, I decided to
> >> > > > > > > > > print the
> >> > > > > > > > > size of each column when a button press is received. As it
> >> > > > > > > > > turns out, the
> >> > > > > > > > > width of the columns is different in the two cases:
> >> > > > > > > > >
> >> > > > > > > > > Without thread signals:
> >> > > > > > > > > column[0](193) = 0 -> 193
> >> > > > > > > > > cell[0] = min->109, natural->109
> >> > > > > > > > > column[1](66) = 193 -> 259
> >> > > > > > > > > cell[0] = min->20, natural->20
> >> > > > > > > > > cell[1] = min->16, natural->16
> >> > > > > > > > > cell[2] = min->35, natural->35
> >> > > > > > > > > column[2](36) = 259 -> 295
> >> > > > > > > > > cell[0] = min->16, natural->16
> >> > > > > > > > > x = 105.872116, y = 259.547516
> >> > > > > > > > >
> >> > > > > > > > > (x and y are the coordinates of the button press event)
> >> > > > > > > > >
> >> > > > > > > > > With thread signals:
> >> > > > > > > > > column[0](0) = 0 -> 0
> >> > > > > > > > > cell[0] = min->135, natural->135
> >> > > > > > > > > column[1](66) = 0 -> 66
> >> > > > > > > > > cell[0] = min->20, natural->20
> >> > > > > > > > > cell[1] = min->16, natural->16
> >> > > > > > > > > cell[2] = min->35, natural->35
> >> > > > > > > > > column[2](36) = 66 -> 102
> >> > > > > > > > > cell[0] = min->16, natural->16
> >> > > > > > > > > x = 113.528488, y = 158.563782
> >> > > > > > > > >
> >> > > > > > > > > As you can see, the width of the first column is 0 when the
> >> > > > > > > > > signals are
> >> > > > > > > > > being emitted. As expected, if I were to click very close to
> >> > > > > > > > > the left
> >> > > > > > > > > border of the widget, the edit dialog does not get triggered as
> >> > > > > > > > > the x
> >> > > > > > > > > coordinate falls within column 1:
> >> > > > > > > > >
> >> > > > > > > > > column[0](0) = 0 -> 0
> >> > > > > > > > > cell[0] = min->135, natural->135
> >> > > > > > > > > column[1](66) = 0 -> 66
> >> > > > > > > > > cell[0] = min->20, natural->20
> >> > > > > > > > > cell[1] = min->16, natural->16
> >> > > > > > > > > cell[2] = min->35, natural->35
> >> > > > > > > > > column[2](36) = 66 -> 102
> >> > > > > > > > > cell[0] = min->16, natural->16
> >> > > > > > > > > x = 21.247330, y = 181.310333
> >> > > > > > > > >
> >> > > > > > > > > I could use the cell renderer width if the column width is 0
> >> > > > > > > > > but that
> >> > > > > > > > > seems unreliable since the cell renderer width is not the same
> >> > > > > > > > > as the
> >> > > > > > > > > column and it's also not static.
> >> > > > > > > > >
> >> > > > > > > > > On Tue, Dec 18, 2018 at 8:23 AM Mitko Haralanov <
> >> > > > > > > > > [hidden email]
> >> > > > > > > > > >
> >> > > > > > > > > wrote:
> >> > > > > > > > >
> >> > > > > > > > > > I am not posting the complete function because there is a lot
> >> > > > > > > > > > of
> >> > > > > > > > > > irrelevant code. I am also not interested in the specific
> >> > > > > > > > > > cell renderer but
> >> > > > > > > > > > rather the row on which the click occurred.
> >> > > > > > > > > >
> >> > > > > > > > > > tatic gboolean on_button_press_event(GtkWidget *widget,
> >> > > > > > > > > >       GdkEvent *event,
> >> > > > > > > > > >       gpointer data)
> >> > > > > > > > > > {
> >> > > > > > > > > > GtkTreeView *treeview = GTK_TREE_VIEW(widget);
> >> > > > > > > > > > GdkEventButton *button = (GdkEventButton *)event;
> >> > > > > > > > > > GtkTreeModel *model;
> >> > > > > > > > > > GtkTreePath *path;
> >> > > > > > > > > > GtkTreeIter iter;
> >> > > > > > > > > > GtkTreeViewColumn *column;
> >> > > > > > > > > > GtkScopeProjectEditDialog *dialog;
> >> > > > > > > > > > GtkScopeProjectEditData *pdata, fill;
> >> > > > > > > > > > GtkScopeProject *project;
> >> > > > > > > > > > guint response, index;
> >> > > > > > > > > > gboolean ret = FALSE;
> >> > > > > > > > > >
> >> > > > > > > > > > if (button->type != GDK_BUTTON_PRESS ||
> >> > > > > > > > > >     !gtk_tree_view_get_path_at_pos(treeview, button->x,
> >> > > > > > > > > > button->y,
> >> > > > > > > > > >    &path, &column, NULL, NULL))
> >> > > > > > > > > > return FALSE;
> >> > > > > > > > > >
> >> > > > > > > > > > index = GPOINTER_TO_UINT(g_object_get_data(G_OBJECT(column),
> >> > > > > > > > > > "index"));
> >> > > > > > > > > > if (index != TREEVIEW_COLUMN_EDIT)
> >> > > > > > > > > > goto done;
> >> > > > > > > > > > model = gtk_tree_view_get_model(treeview);
> >> > > > > > > > > > if (!gtk_tree_model_get_iter(model, &iter, path))
> >> > > > > > > > > > goto done;
> >> > > > > > > > > > gtk_tree_model_get(model, &iter, PROJECT_COLUMN_OBJ,
> >> > > > > > > > > > &project, -1);
> >> > > > > > > > > >         ...
> >> > > > > > > > > >
> >> > > > > > > > > > The issue is that the column which is returned by
> >> > > > > > > > > > gtk_tree_view_get_path_at_pos() is different depending on
> >> > > > > > > > > > whether thread
> >> > > > > > > > > > signals are being emitted vs not. I have verified that the
> >> > > > > > > > > > button press
> >> > > > > > > > > > coordinates are the same (button->x and button->y have the
> >> > > > > > > > > > same values in
> >> > > > > > > > > > both cases).
> >> > > > > > > > > >
> >> > > > > > > > > >
> >> > > > > > > > > > On Tue, Dec 18, 2018 at 5:24 AM Luca Bacci <
> >> > > > > > > > > > [hidden email]
> >> > > > > > > > > > >
> >> > > > > > > > > > wrote:
> >> > > > > > > > > >
> >> > > > > > > > > > > Hi Mitko! Can you post here the code for the button-press
> >> > > > > > > > > > > event
> >> > > > > > > > > > > handler?
> >> > > > > > > > > > > It should more or less follow the code here:
> >> > > > > > > > > > > http://scentric.net/tutorial/sec-misc-get-renderer-from-click.html
> >> > > > > > > > > > >
> >> > > > > > > > > > >
> >> > > > > > > > > > > Luca
> >> > > > > > > > > > >
> >> > > > > > > > > > > Il giorno lun 17 dic 2018 alle ore 20:28 Mitko Haralanov
> >> > > > > > > > > > > via gtk-list <
> >> > > > > > > > > > > [hidden email]
> >> > > > > > > > > > > > ha scritto:
> >> > > > > > > > > > >
> >> > > > > > > > > > > > Hi,
> >> > > > > > > > > > > >
> >> > > > > > > > > > > > In my application, I want to be able to update a treeview
> >> > > > > > > > > > > > from a
> >> > > > > > > > > > > > separate thread. Each treeview row was a column that is a
> >> > > > > > > > > > > > progress bar. The
> >> > > > > > > > > > > > progress to be displayed is generated by a separate
> >> > > > > > > > > > > > thread as to not block
> >> > > > > > > > > > > > the UI.
> >> > > > > > > > > > > >
> >> > > > > > > > > > > > Since GTK is not thread-safe, the way the application is
> >> > > > > > > > > > > > written is
> >> > > > > > > > > > > > that the thread, when it needs to emit a signal, will
> >> > > > > > > > > > > > prepare the signal
> >> > > > > > > > > > > > data and then call g_main_context_invoke_full(NULL, cb,
> >> > > > > > > > > > > > data, ...) in order
> >> > > > > > > > > > > > to be able to call g_singal_emit() in the global default
> >> > > > > > > > > > > > context thread.
> >> > > > > > > > > > > > The signal handler updates the tree model, which in turn
> >> > > > > > > > > > > > updates the tree
> >> > > > > > > > > > > > view.
> >> > > > > > > > > > > >
> >> > > > > > > > > > > > For the most part this works with one big, ugly exception
> >> > > > > > > > > > > > - the same
> >> > > > > > > > > > > > treeview has a column, which is supposed to open the
> >> > > > > > > > > > > > item's Edit dialog
> >> > > > > > > > > > > > when clicked. So, naturally, I have a button-press
> >> > > > > > > > > > > > handler connected to the
> >> > > > > > > > > > > > treeview, which launches the Edit dialog when the button
> >> > > > > > > > > > > > press occurs in
> >> > > > > > > > > > > > the correct column.
> >> > > > > > > > > > > >
> >> > > > > > > > > > > > However, when an update is running and the thread is
> >> > > > > > > > > > > > continuously
> >> > > > > > > > > > > > emitting signals, clicking on *any* column of *any* of
> >> > > > > > > > > > > > the other items
> >> > > > > > > > > > > > opens the Edit dialog. The treeview behaves as if the
> >> > > > > > > > > > > > items in it have only
> >> > > > > > > > > > > > one column.
> >> > > > > > > > > > > >
> >> > > > > > > > > > > > Every example or document that I have seen in relation to
> >> > > > > > > > > > > > signals
> >> > > > > > > > > > > > from threads says to emit the signal from a g_idle_add()
> >> > > > > > > > > > > > handler. However,
> >> > > > > > > > > > > > g_main_context_invoke_full(NULL, ...) should be the same
> >> > > > > > > > > > > > as calling
> >> > > > > > > > > > > > g_idle_add().
> >> > > > > > > > > > > >
> >> > > > > > > > > > > > Can someone shed some light into what might be happening?
> >> > > > > > > > > > > >
> >> > > > > > > > > > > > Thank you.
> >> > > > > > > > > > > >
> >> > > > > > > > > > > >
> >> > > > > > > > > > > > _______________________________________________
> >> > > > > > > > > > > > gtk-list mailing list
> >> > > > > > > > > > > > [hidden email]
> >> > > > > > > > > > > >
> >> > > > > > > > > > > > https://mail.gnome.org/mailman/listinfo/gtk-list
> >> > > > > > > > > > > >
> >> > > > > > > > > > > >
> >> > > > > > > > > > >
> >> > > > > > > > > > > _______________________________________________
> >> > > > > > > > >
> >> > > > > > > > > gtk-list mailing list
> >> > > > > > > > > [hidden email]
> >> > > > > > > > >
> >> > > > > > > > > https://mail.gnome.org/mailman/listinfo/gtk-list
> >> > > > > > > > >
> >> > > > > > > > >
> >> > > > > > > >
> >> > > > > > > > _______________________________________________
> >> > > > > > > > gtk-list mailing list
> >> > > > > > > > [hidden email]
> >> > > > > > > >
> >> > > > > > > > https://mail.gnome.org/mailman/listinfo/gtk-list
> >> > > > > > > >
> >> > > > > > > >
> >> > > > > >
> >> > > > > > _______________________________________________
> >> > > > > > gtk-list mailing list
> >> > > > > > [hidden email]
> >> > > > > >
> >> > > > > > https://mail.gnome.org/mailman/listinfo/gtk-list
> >> > > > > >
> >> > > > >
> >> > > > >
> >> > > > >
> >> > > > _______________________________________________
> >> > > > gtk-list mailing list
> >> > > > [hidden email]
> >> > > > https://mail.gnome.org/mailman/listinfo/gtk-list
_______________________________________________
gtk-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtk-list
Reply | Threaded
Open this post in threaded view
|

Re: Emitting signals from threads

Gtk+ - General mailing list
Hi Mitko,
last time I tried creating a simple C application for testing but I did get always correct values. (Btw I used g_idle_add)
Can you try to write a minimal test application that still exhibits the problem? That would be very helpful!

Il giorno mer 9 gen 2019, 18:32 Mitko Haralanov via gtk-list <[hidden email]> ha scritto:
After some offline discussion, I decided to experiment with
g_idle_add_full() since that function seems to work for other people.

Unfortunately, it doesn't in my case. The width of the first column is
still 0 and bad behavior is reproducible:

column[0](0) = 0 -> 0
    cell[0] = min->102, natural->102, text->98
column[1](66) = 98 -> 164
    cell[0] = min->20, natural->20
    cell[1] = min->16, natural->16
    cell[2] = min->35, natural->35
column[2](36) = 164 -> 200
    cell[0] = min->16, natural->16
x = 138.000000, y = 274.000000

Looking at the code for g_main_context_invoke_full() and
g_idle_add_full(), as expected, the portion of
g_main_context_invoke_full() that deals with the idle source is
virtually identical to g_idle_add_full(). So, the issue is somewhere
deeper.

Are there any GLib or Gtk+ developers on this list that can offer any help?

On Tue, Jan 8, 2019 at 4:35 PM Lex Trotman <[hidden email]> wrote:
>
> "calling gtk functions from a thread would be possible only through
> g_idle_add()." thats my understanding from
> https://developer.gnome.org/gdk3/stable/gdk3-Threads.html and thats
> what our app does.  It never seems to be a  performance problem, the
> main thread continuously chews its way through the idle queue.
>
> Cheers
> Lex
>
> On Wed, 9 Jan 2019 at 10:17, Mitko Haralanov <[hidden email]> wrote:
> >
> > I havent looked at the actual code but I am willing to bet that the "idle source" is just using g_idle_add(). If so, g_main_context_invoke_full() is essentially the same.
> >
> > If not the case, calling gtk functions from a thread would be possible only through g_idle_add(). I would think that if that were the case, it would have been mentioned in the docs.
> >
> > Thank you,
> > Mitko
> >
> > On Tue, Jan 8, 2019, 16:11 Lex Trotman <[hidden email] wrote:
> >>
> >> Hi Mitko,
> >>
> >> Same problem, from g_main_context_invoke() "In any other case, an idle
> >> source is created to call function and that source is attached to
> >> context (presumably to be run in another thread)."
> >>
> >> Cheers
> >> Lex
> >>
> >> On Wed, 9 Jan 2019 at 09:55, Mitko Haralanov <[hidden email]> wrote:
> >> >
> >> > Hi Lex,
> >> >
> >> > That is for the "notify" callback, which only deals with free/release
> >> > of the "data" pointer. The "function" callback is different and should
> >> > be called from the context default thread (as the documentation
> >> > describes.)
> >> >
> >> > Thank you,
> >> > Mitko
> >> >
> >> > On Tue, Jan 8, 2019 at 3:44 PM Lex Trotman <[hidden email]> wrote:
> >> > >
> >> > > Mito,
> >> > >
> >> > > It seems to me that since the g_main_context_invoke_full() docs say
> >> > > "notify should not assume that it is called from any particular
> >> > > thread" that notify cannot call GTK functions since GTK is not thread
> >> > > safe.
> >> > >
> >> > > Cheers
> >> > > Lex
> >> > >
> >> > > PS I'm not on gtk-list and am not gonna join for one line, feel free to forward
> >> > >
> >> > > On Wed, 9 Jan 2019 at 04:03, Mitko Haralanov via gtk-list
> >> > > <[hidden email]> wrote:
> >> > > >
> >> > > > Thanks for the reply.
> >> > > >
> >> > > > When calling g_main_context_invoke_full(), I am using NULL as the
> >> > > > context pointer. According to the documentation of
> >> > > > g_main_context_invoke():
> >> > > >
> >> > > >         "If context is NULL then the global default main context — as
> >> > > > returned by g_main_context_default() — is used."
> >> > > >
> >> > > > So, the code should be using the correct context.
> >> > > >
> >> > > > One of the main reasons why I am not using g_idle_add() is the timing
> >> > > > of the callback. I don't want to defer the processing of the callback
> >> > > > to the "idle" time since this is signal handling related. Another
> >> > > > advantage of g_main_context_invoke[_full]() is that it will check the
> >> > > > "context" of the caller and, if possible, will call the callback
> >> > > > directly:
> >> > > >
> >> > > >        "If context is owned by the current thread, function is called
> >> > > > directly. Otherwise, if context is the thread-default main context of
> >> > > > the current thread and g_main_context_acquire()
> >> > > >        succeeds, then function is called and g_main_context_release()
> >> > > > is called afterwards.
> >> > > >        In any other case, an idle source is created to call function
> >> > > > and that source is attached to context (presumably to be run in
> >> > > > another thread). The idle source is attached with
> >> > > >        G_PRIORITY_DEFAULT priority. If you want a different priority,
> >> > > > use g_main_context_invoke_full()."
> >> > > >
> >> > > > Your suggested implementation is basically the GLib's async queues.
> >> > > > Or, may be, a custom event source. However, it seems that
> >> > > > g_main_context_invoke_full() should be doing exactly that. With all
> >> > > > due respect, I also don't see how it would solve the issue. If the
> >> > > > current implementation has an problem with locking/race conditions,
> >> > > > would your suggested implementation suffer from the same issue since
> >> > > > it's using the same or similar mechanism for calling the callback?
> >> > > >
> >> > > > Thank you,
> >> > > >
> >> > > > Mitko
> >> > > >
> >> > > >
> >> > > > On Mon, Jan 7, 2019 at 3:54 PM ente <[hidden email]> wrote:
> >> > > > >
> >> > > > > Hi,
> >> > > > >
> >> > > > >
> >> > > > > I am not sure with my answer. Treat it as unreliable.
> >> > > > >
> >> > > > > There seems to be a difference between g_idle_add
> >> > > > > and g_main_context_invoke_full. While the documentation of idle_add
> >> > > > > says:
> >> > > > > "Adds a function to be called [...] to the default main loop." (i.e.
> >> > > > > main thread / the only gtk-thread) g_main_context_invoke_full does not
> >> > > > > mention the main loop - although it mentions a "context" which I have
> >> > > > > no experience with and which may be related to the main loop. So maybe
> >> > > > > you must retrieve the correct context using g_main_context_default or
> >> > > > > g_main_context_acquire. Keep in mind: glib is thread safe, gtk is not.
> >> > > > > g_main_context_invoke_full may support glib multi threading while
> >> > > > > g_idle_add clearly sends your function call to the gtk thread.
> >> > > > >
> >> > > > > The effect you are describing makes sense to me. The effects you
> >> > > > > observe sound very much like race conditions in the treeview event
> >> > > > > handler.
> >> > > > >
> >> > > > > Why aren't you using g_idle_add in the first place? In my experience
> >> > > > > this works like a charm. Be careful with one thing tho: The main loop
> >> > > > > has a "todo-list". Each time you call "g_idle_add" it adds an item to
> >> > > > > that todo-list and schedules a call to your function. If your function
> >> > > > > doesn't return false, it won't even be taken down from the todo-list.
> >> > > > > Each click event ends on that todo-list. Each column resize adds
> >> > > > > multiple items to that todo-list (depending on your column resize
> >> > > > > policy and the number of rows). As soon as you add more items to that
> >> > > > > list, your UI becomes unresponsive. It seems advisable to build your
> >> > > > > own shadow todo-list for the update process, i.e.:
> >> > > > > * setup a function "update_progress"
> >> > > > > * on the first threaded update event, call idle_add for the function
> >> > > > > and put the new progress and the row number in your own data structure
> >> > > > > * while the function is still "planned in for idle_add", just add new
> >> > > > > events to your own data structure
> >> > > > > * process 1 to 10 (maybe some more) events on each of the calls
> >> > > > > * the function returns true as long as there is still some events in
> >> > > > > your own list; it returns false otherwise
> >> > > > > * apply mutex checks on your data structure (not sure if i should
> >> > > > > mention, I am sure you had this in your mind already)
> >> > > > >
> >> > > > > Each time you update a progress bar in your treeview, several (at least
> >> > > > > one) events are added to the gtk-todo list (repaint!, re-order? and
> >> > > > > maybe some more). Doing multiple progress events at once may lower the
> >> > > > > amount of events, gtk has to process (a re-order affects all rows -
> >> > > > > doing an update on multiple rows does not change anything here).
> >> > > > >
> >> > > > > That's my 5 cents. I hope it helped a bit.
> >> > > > >
> >> > > > >
> >> > > > > regards,
> >> > > > >
> >> > > > >
> >> > > > > ente
> >> > > > >
> >> > > > >
> >> > > > > On Mon, 2019-01-07 at 08:28 -0800, Mitko Haralanov via gtk-list wrote:
> >> > > > > > Anyone have any ideas? I still can't figure out why the column sizes
> >> > > > > > go to
> >> > > > > > 0.
> >> > > > > >
> >> > > > > > Thank you.
> >> > > > > >
> >> > > > > > On Tue, Dec 18, 2018, 13:40 Mitko Haralanov <
> >> > > > > > [hidden email]
> >> > > > > >  wrote:
> >> > > > > >
> >> > > > > > > This is Gtk3:
> >> > > > > > > gtk3-3.22.26-2.fc27.x86_64
> >> > > > > > >
> >> > > > > > > On Tue, Dec 18, 2018 at 1:14 PM Luca Bacci via gtk-list <
> >> > > > > > > [hidden email]
> >> > > > > > > > wrote:
> >> > > > > > >
> >> > > > > > > > Is it Gtk2 or Gtk3, which version exactly?
> >> > > > > > > >
> >> > > > > > > >
> >> > > > > > > > Il giorno mar 18 dic 2018 alle ore 18:47 Mitko Haralanov via gtk-
> >> > > > > > > > list <
> >> > > > > > > > [hidden email]
> >> > > > > > > > > ha scritto:
> >> > > > > > > >
> >> > > > > > > > > I mistakenly replied only to Luca!! Forwarding to the list.
> >> > > > > > > > >
> >> > > > > > > > > (Sorry, Luca, my bad)
> >> > > > > > > > > - Mitko
> >> > > > > > > > >
> >> > > > > > > > > ---------- Forwarded message ---------
> >> > > > > > > > > From: Mitko Haralanov <
> >> > > > > > > > > [hidden email]
> >> > > > > > > > > >
> >> > > > > > > > > Date: Tue, Dec 18, 2018 at 9:37 AM
> >> > > > > > > > > Subject: Re: Emitting signals from threads
> >> > > > > > > > > To: Luca Bacci <
> >> > > > > > > > > [hidden email]
> >> > > > > > > > > >
> >> > > > > > > > >
> >> > > > > > > > >
> >> > > > > > > > > I found something that is different between the two cases -
> >> > > > > > > > > button click
> >> > > > > > > > > with signals and without.
> >> > > > > > > > >
> >> > > > > > > > > Using the code from the link that Luca posted, I decided to
> >> > > > > > > > > print the
> >> > > > > > > > > size of each column when a button press is received. As it
> >> > > > > > > > > turns out, the
> >> > > > > > > > > width of the columns is different in the two cases:
> >> > > > > > > > >
> >> > > > > > > > > Without thread signals:
> >> > > > > > > > > column[0](193) = 0 -> 193
> >> > > > > > > > > cell[0] = min->109, natural->109
> >> > > > > > > > > column[1](66) = 193 -> 259
> >> > > > > > > > > cell[0] = min->20, natural->20
> >> > > > > > > > > cell[1] = min->16, natural->16
> >> > > > > > > > > cell[2] = min->35, natural->35
> >> > > > > > > > > column[2](36) = 259 -> 295
> >> > > > > > > > > cell[0] = min->16, natural->16
> >> > > > > > > > > x = 105.872116, y = 259.547516
> >> > > > > > > > >
> >> > > > > > > > > (x and y are the coordinates of the button press event)
> >> > > > > > > > >
> >> > > > > > > > > With thread signals:
> >> > > > > > > > > column[0](0) = 0 -> 0
> >> > > > > > > > > cell[0] = min->135, natural->135
> >> > > > > > > > > column[1](66) = 0 -> 66
> >> > > > > > > > > cell[0] = min->20, natural->20
> >> > > > > > > > > cell[1] = min->16, natural->16
> >> > > > > > > > > cell[2] = min->35, natural->35
> >> > > > > > > > > column[2](36) = 66 -> 102
> >> > > > > > > > > cell[0] = min->16, natural->16
> >> > > > > > > > > x = 113.528488, y = 158.563782
> >> > > > > > > > >
> >> > > > > > > > > As you can see, the width of the first column is 0 when the
> >> > > > > > > > > signals are
> >> > > > > > > > > being emitted. As expected, if I were to click very close to
> >> > > > > > > > > the left
> >> > > > > > > > > border of the widget, the edit dialog does not get triggered as
> >> > > > > > > > > the x
> >> > > > > > > > > coordinate falls within column 1:
> >> > > > > > > > >
> >> > > > > > > > > column[0](0) = 0 -> 0
> >> > > > > > > > > cell[0] = min->135, natural->135
> >> > > > > > > > > column[1](66) = 0 -> 66
> >> > > > > > > > > cell[0] = min->20, natural->20
> >> > > > > > > > > cell[1] = min->16, natural->16
> >> > > > > > > > > cell[2] = min->35, natural->35
> >> > > > > > > > > column[2](36) = 66 -> 102
> >> > > > > > > > > cell[0] = min->16, natural->16
> >> > > > > > > > > x = 21.247330, y = 181.310333
> >> > > > > > > > >
> >> > > > > > > > > I could use the cell renderer width if the column width is 0
> >> > > > > > > > > but that
> >> > > > > > > > > seems unreliable since the cell renderer width is not the same
> >> > > > > > > > > as the
> >> > > > > > > > > column and it's also not static.
> >> > > > > > > > >
> >> > > > > > > > > On Tue, Dec 18, 2018 at 8:23 AM Mitko Haralanov <
> >> > > > > > > > > [hidden email]
> >> > > > > > > > > >
> >> > > > > > > > > wrote:
> >> > > > > > > > >
> >> > > > > > > > > > I am not posting the complete function because there is a lot
> >> > > > > > > > > > of
> >> > > > > > > > > > irrelevant code. I am also not interested in the specific
> >> > > > > > > > > > cell renderer but
> >> > > > > > > > > > rather the row on which the click occurred.
> >> > > > > > > > > >
> >> > > > > > > > > > tatic gboolean on_button_press_event(GtkWidget *widget,
> >> > > > > > > > > >       GdkEvent *event,
> >> > > > > > > > > >       gpointer data)
> >> > > > > > > > > > {
> >> > > > > > > > > > GtkTreeView *treeview = GTK_TREE_VIEW(widget);
> >> > > > > > > > > > GdkEventButton *button = (GdkEventButton *)event;
> >> > > > > > > > > > GtkTreeModel *model;
> >> > > > > > > > > > GtkTreePath *path;
> >> > > > > > > > > > GtkTreeIter iter;
> >> > > > > > > > > > GtkTreeViewColumn *column;
> >> > > > > > > > > > GtkScopeProjectEditDialog *dialog;
> >> > > > > > > > > > GtkScopeProjectEditData *pdata, fill;
> >> > > > > > > > > > GtkScopeProject *project;
> >> > > > > > > > > > guint response, index;
> >> > > > > > > > > > gboolean ret = FALSE;
> >> > > > > > > > > >
> >> > > > > > > > > > if (button->type != GDK_BUTTON_PRESS ||
> >> > > > > > > > > >     !gtk_tree_view_get_path_at_pos(treeview, button->x,
> >> > > > > > > > > > button->y,
> >> > > > > > > > > >    &path, &column, NULL, NULL))
> >> > > > > > > > > > return FALSE;
> >> > > > > > > > > >
> >> > > > > > > > > > index = GPOINTER_TO_UINT(g_object_get_data(G_OBJECT(column),
> >> > > > > > > > > > "index"));
> >> > > > > > > > > > if (index != TREEVIEW_COLUMN_EDIT)
> >> > > > > > > > > > goto done;
> >> > > > > > > > > > model = gtk_tree_view_get_model(treeview);
> >> > > > > > > > > > if (!gtk_tree_model_get_iter(model, &iter, path))
> >> > > > > > > > > > goto done;
> >> > > > > > > > > > gtk_tree_model_get(model, &iter, PROJECT_COLUMN_OBJ,
> >> > > > > > > > > > &project, -1);
> >> > > > > > > > > >         ...
> >> > > > > > > > > >
> >> > > > > > > > > > The issue is that the column which is returned by
> >> > > > > > > > > > gtk_tree_view_get_path_at_pos() is different depending on
> >> > > > > > > > > > whether thread
> >> > > > > > > > > > signals are being emitted vs not. I have verified that the
> >> > > > > > > > > > button press
> >> > > > > > > > > > coordinates are the same (button->x and button->y have the
> >> > > > > > > > > > same values in
> >> > > > > > > > > > both cases).
> >> > > > > > > > > >
> >> > > > > > > > > >
> >> > > > > > > > > > On Tue, Dec 18, 2018 at 5:24 AM Luca Bacci <
> >> > > > > > > > > > [hidden email]
> >> > > > > > > > > > >
> >> > > > > > > > > > wrote:
> >> > > > > > > > > >
> >> > > > > > > > > > > Hi Mitko! Can you post here the code for the button-press
> >> > > > > > > > > > > event
> >> > > > > > > > > > > handler?
> >> > > > > > > > > > > It should more or less follow the code here:
> >> > > > > > > > > > > http://scentric.net/tutorial/sec-misc-get-renderer-from-click.html
> >> > > > > > > > > > >
> >> > > > > > > > > > >
> >> > > > > > > > > > > Luca
> >> > > > > > > > > > >
> >> > > > > > > > > > > Il giorno lun 17 dic 2018 alle ore 20:28 Mitko Haralanov
> >> > > > > > > > > > > via gtk-list <
> >> > > > > > > > > > > [hidden email]
> >> > > > > > > > > > > > ha scritto:
> >> > > > > > > > > > >
> >> > > > > > > > > > > > Hi,
> >> > > > > > > > > > > >
> >> > > > > > > > > > > > In my application, I want to be able to update a treeview
> >> > > > > > > > > > > > from a
> >> > > > > > > > > > > > separate thread. Each treeview row was a column that is a
> >> > > > > > > > > > > > progress bar. The
> >> > > > > > > > > > > > progress to be displayed is generated by a separate
> >> > > > > > > > > > > > thread as to not block
> >> > > > > > > > > > > > the UI.
> >> > > > > > > > > > > >
> >> > > > > > > > > > > > Since GTK is not thread-safe, the way the application is
> >> > > > > > > > > > > > written is
> >> > > > > > > > > > > > that the thread, when it needs to emit a signal, will
> >> > > > > > > > > > > > prepare the signal
> >> > > > > > > > > > > > data and then call g_main_context_invoke_full(NULL, cb,
> >> > > > > > > > > > > > data, ...) in order
> >> > > > > > > > > > > > to be able to call g_singal_emit() in the global default
> >> > > > > > > > > > > > context thread.
> >> > > > > > > > > > > > The signal handler updates the tree model, which in turn
> >> > > > > > > > > > > > updates the tree
> >> > > > > > > > > > > > view.
> >> > > > > > > > > > > >
> >> > > > > > > > > > > > For the most part this works with one big, ugly exception
> >> > > > > > > > > > > > - the same
> >> > > > > > > > > > > > treeview has a column, which is supposed to open the
> >> > > > > > > > > > > > item's Edit dialog
> >> > > > > > > > > > > > when clicked. So, naturally, I have a button-press
> >> > > > > > > > > > > > handler connected to the
> >> > > > > > > > > > > > treeview, which launches the Edit dialog when the button
> >> > > > > > > > > > > > press occurs in
> >> > > > > > > > > > > > the correct column.
> >> > > > > > > > > > > >
> >> > > > > > > > > > > > However, when an update is running and the thread is
> >> > > > > > > > > > > > continuously
> >> > > > > > > > > > > > emitting signals, clicking on *any* column of *any* of
> >> > > > > > > > > > > > the other items
> >> > > > > > > > > > > > opens the Edit dialog. The treeview behaves as if the
> >> > > > > > > > > > > > items in it have only
> >> > > > > > > > > > > > one column.
> >> > > > > > > > > > > >
> >> > > > > > > > > > > > Every example or document that I have seen in relation to
> >> > > > > > > > > > > > signals
> >> > > > > > > > > > > > from threads says to emit the signal from a g_idle_add()
> >> > > > > > > > > > > > handler. However,
> >> > > > > > > > > > > > g_main_context_invoke_full(NULL, ...) should be the same
> >> > > > > > > > > > > > as calling
> >> > > > > > > > > > > > g_idle_add().
> >> > > > > > > > > > > >
> >> > > > > > > > > > > > Can someone shed some light into what might be happening?
> >> > > > > > > > > > > >
> >> > > > > > > > > > > > Thank you.
> >> > > > > > > > > > > >
> >> > > > > > > > > > > >
> >> > > > > > > > > > > > _______________________________________________
> >> > > > > > > > > > > > gtk-list mailing list
> >> > > > > > > > > > > > [hidden email]
> >> > > > > > > > > > > >
> >> > > > > > > > > > > > https://mail.gnome.org/mailman/listinfo/gtk-list
> >> > > > > > > > > > > >
> >> > > > > > > > > > > >
> >> > > > > > > > > > >
> >> > > > > > > > > > > _______________________________________________
> >> > > > > > > > >
> >> > > > > > > > > gtk-list mailing list
> >> > > > > > > > > [hidden email]
> >> > > > > > > > >
> >> > > > > > > > > https://mail.gnome.org/mailman/listinfo/gtk-list
> >> > > > > > > > >
> >> > > > > > > > >
> >> > > > > > > >
> >> > > > > > > > _______________________________________________
> >> > > > > > > > gtk-list mailing list
> >> > > > > > > > [hidden email]
> >> > > > > > > >
> >> > > > > > > > https://mail.gnome.org/mailman/listinfo/gtk-list
> >> > > > > > > >
> >> > > > > > > >
> >> > > > > >
> >> > > > > > _______________________________________________
> >> > > > > > gtk-list mailing list
> >> > > > > > [hidden email]
> >> > > > > >
> >> > > > > > https://mail.gnome.org/mailman/listinfo/gtk-list
> >> > > > > >
> >> > > > >
> >> > > > >
> >> > > > >
> >> > > > _______________________________________________
> >> > > > gtk-list mailing list
> >> > > > [hidden email]
> >> > > > https://mail.gnome.org/mailman/listinfo/gtk-list
_______________________________________________
gtk-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtk-list

_______________________________________________
gtk-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtk-list
Reply | Threaded
Open this post in threaded view
|

Re: Emitting signals from threads

Gtk+ - General mailing list
In reply to this post by Gtk+ - General mailing list
Hi Mitko,
last time I tried creating a simple C application for testing but I did get always correct values. (Btw I used g_idle_add)
Can you try to write a minimal test application that still exhibits the problem? That would be very helpful!

_______________________________________________
gtk-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtk-list
Reply | Threaded
Open this post in threaded view
|

Re: Emitting signals from threads

Gtk+ - General mailing list
In reply to this post by Gtk+ - General mailing list
I never said it worked with g_idle_add() (or if I did, I made a typing
mistake). Actually, what I said is that it *doesn't* work with
g_idle_add().

I am not entirely sure what bug "in my code" I could have found since
my code is not responsible for managing and/or painting the columns.
This should be handled entirely in the library. The only thing that
the threaded signal callback is doing is changing the *model*, which
should be allowed. The button click callback is obviously executing
the same code

On Wed, Jan 9, 2019 at 9:37 AM Chris Vine via gtk-list
<[hidden email]> wrote:

>
> On Tue, 8 Jan 2019 10:02:58 -0800
> Mitko Haralanov via gtk-list <[hidden email]> wrote:
> > Thanks for the reply.
> >
> > When calling g_main_context_invoke_full(), I am using NULL as the
> > context pointer. According to the documentation of
> > g_main_context_invoke():
> >
> >         "If context is NULL then the global default main context — as
> > returned by g_main_context_default() — is used."
> >
> > So, the code should be using the correct context.
> >
> > One of the main reasons why I am not using g_idle_add() is the timing
> > of the callback. I don't want to defer the processing of the callback
> > to the "idle" time since this is signal handling related. Another
> > advantage of g_main_context_invoke[_full]() is that it will check the
> > "context" of the caller and, if possible, will call the callback
> > directly:
> >
> >        "If context is owned by the current thread, function is called
> > directly. Otherwise, if context is the thread-default main context of
> > the current thread and g_main_context_acquire()
> >        succeeds, then function is called and g_main_context_release()
> > is called afterwards.
> >        In any other case, an idle source is created to call function
> > and that source is attached to context (presumably to be run in
> > another thread). The idle source is attached with
> >        G_PRIORITY_DEFAULT priority. If you want a different priority,
> > use g_main_context_invoke_full()."
> >
> > Your suggested implementation is basically the GLib's async queues.
> > Or, may be, a custom event source. However, it seems that
> > g_main_context_invoke_full() should be doing exactly that. With all
> > due respect, I also don't see how it would solve the issue. If the
> > current implementation has an problem with locking/race conditions,
> > would your suggested implementation suffer from the same issue since
> > it's using the same or similar mechanism for calling the callback?
>
> "With all due respect" this is fine, but I am not sure what more your
> interlocutor can say.  If your code works with g_idle_add() but not
> with g_main_context_invoke_full() then you have a timing issue in your
> code caused by the fact that the callbacks for the default main loop via
> g_main_context_invoke_full() may be executed before the callbacks for
> earlier invocations of g_idle_add().
>
> If it doesn't work with either of them then you have some other issue.
> It is possible you have found a bug in glib but more likely you have
> found a bug in your code.
> _______________________________________________
> gtk-list mailing list
> [hidden email]
> https://mail.gnome.org/mailman/listinfo/gtk-list
_______________________________________________
gtk-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtk-list
Reply | Threaded
Open this post in threaded view
|

Re: Emitting signals from threads

Gtk+ - General mailing list
In reply to this post by Gtk+ - General mailing list
Sure, let me try to come up with something and if successful, I'll post it.

Thank you.

On Wed, Jan 9, 2019 at 10:33 AM Luca Bacci <[hidden email]> wrote:
>
> Hi Mitko,
> last time I tried creating a simple C application for testing but I did get always correct values. (Btw I used g_idle_add)
> Can you try to write a minimal test application that still exhibits the problem? That would be very helpful!
_______________________________________________
gtk-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtk-list
Reply | Threaded
Open this post in threaded view
|

Re: Emitting signals from threads

Gtk+ - General mailing list
I haven't had much time to work on this but I did figure out the following:

The reason that the "Edit" dialog is being opened is that when the
click is processed by the button-press-event handler, the width of the
first column in the TreeView is 0. As a result, the calculation of
where the click occurred always ends up determining that the "Edit"
cell was clicked.

After much digging, I found out that the code which changes the width
of the first column cell to 0 is
"_gtk_tree_view_column_cell_set_dirty()" when called by
"gtk_tree_row_changed()":

Thread 1 "gtkscope" hit Hardware watchpoint 12: ((GtkTreeViewColumn
*)0xa009a0)->priv->width

Old value = 193
New value = 0
_gtk_tree_view_column_cell_set_dirty (tree_column=<optimized out>,
install_handler=1)
    at gtktreeviewcolumn.c:3006
3006   g_signal_handler_block (priv->cell_area_context,
(gdb) bt
#0  0x00007ffff739663f in _gtk_tree_view_column_cell_set_dirty
(tree_column=<optimized out>, install_handler=1) at
gtktreeviewcolumn.c:3006
#1  0x00007ffff737e8b5 in gtk_tree_view_row_changed (model=<optimized
out>, path=0x2c7b690, iter=<optimized out>, data=0x954400) at
gtktreeview.c:9020
#5  0x00007ffff599765f in <emit signal ??? on instance 0x93ef00
[GtkTreeStore]> (instance=instance@entry=0x93ef00,
signal_id=<optimized out>, detail=detail@entry=0) at gsignal.c:3447
    #2  0x00007ffff597b73d in g_closure_invoke (closure=0xa01640,
return_value=0x0, n_param_values=3, param_values=0x7fffffffad10,
invocation_hint=0x7fffffffac90) at gclosure.c:804
    #3  0x00007ffff598e4ce in signal_emit_unlocked_R
(node=node@entry=0x7fffcc009fa0, detail=detail@entry=0,
instance=instance@entry=0x93ef00,
emission_return=emission_return@entry=0x0,
instance_and_params=instance_and_params@entry=0x7fffffffad10) at
gsignal.c:3635
    #4  0x00007ffff5996cf5 in g_signal_emit_valist (instance=0x93ef00,
signal_id=<optimized out>, detail=0,
var_args=var_args@entry=0x7fffffffaf10) at gsignal.c:3391
#6  0x00007ffff7365950 in gtk_tree_model_row_changed
(tree_model=tree_model@entry=0x93ef00, path=path@entry=0x2c7b690,
iter=iter@entry=0x7fffffffb130) at gtktreemodel.c:1835
#7  0x00007ffff737643b in gtk_tree_store_set_valist
(tree_store=0x93ef00 [GtkTreeStore], iter=0x7fffffffb130,
var_args=var_args@entry=0x7fffffffb030) at gtktreestore.c:1161
#8  0x00007ffff73764e4 in gtk_tree_store_set (tree_store=<optimized
out>, iter=<optimized out>)
    at gtktreestore.c:1190
...

The column is set to be with AUTOMATIC size so that code path in
gtk_tree_row_changed() gets triggered.

However, as I understand it, if my signal is running in the main
context, the signal handler should not be running at the same time as
Gtk is recalculating/repainting the TreeView. It seems as if the
threaded signal handler is not running in the main context. The above
behavior is replicated even if I switched to use g_idle_add() instead
of g_main_context_invoke_full().

On Wed, Jan 9, 2019 at 11:08 AM Mitko Haralanov <[hidden email]> wrote:

>
> Sure, let me try to come up with something and if successful, I'll post it.
>
> Thank you.
>
> On Wed, Jan 9, 2019 at 10:33 AM Luca Bacci <[hidden email]> wrote:
> >
> > Hi Mitko,
> > last time I tried creating a simple C application for testing but I did get always correct values. (Btw I used g_idle_add)
> > Can you try to write a minimal test application that still exhibits the problem? That would be very helpful!
_______________________________________________
gtk-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtk-list
Reply | Threaded
Open this post in threaded view
|

Re: Emitting signals from threads

Gtk+ - General mailing list
On Wed, 27 Feb 2019 09:49:43 -0800
Mitko Haralanov via gtk-list <[hidden email]> wrote:
[snip]
> However, as I understand it, if my signal is running in the main
> context, the signal handler should not be running at the same time as
> Gtk is recalculating/repainting the TreeView. It seems as if the
> threaded signal handler is not running in the main context. The above
> behavior is replicated even if I switched to use g_idle_add() instead
> of g_main_context_invoke_full().

I am not going to try to penetrate your code, and you may already know
this but a GObject signal handler executes in the thread which emits on
the signal.  If this is a GDK/GTK+ signal, this would/should be, in
almost all cases, the thread in which GTK+ runs, namely the thread
of the default main context.

g_idle_add() does not of itself emit a signal.  It executes a callback
in the main loop of the default main context.

Chris
_______________________________________________
gtk-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtk-list
Reply | Threaded
Open this post in threaded view
|

Re: Emitting signals from threads

Gtk+ - General mailing list
Hi Chris,

I am not expecting g_idle_add() to emit the signal. I am calling a
separate function scheduled by g_idle_add() or
g_main_context_invoke_full(), which does the signal emission. I use
g_idle_add()/g_main_context_invoke_full() to ensure that this callback
is, in fact, running in the main context thread.

However, despite the signal emission occurring in the main context
thread, the signal handler seems to be running at the same time as GTK
internal functions are updating the state of the TreeView columns. As
I understand GTK, this should not be possible.

- Mitko

On Wed, Feb 27, 2019 at 1:10 PM Chris Vine via gtk-list
<[hidden email]> wrote:

>
> On Wed, 27 Feb 2019 09:49:43 -0800
> Mitko Haralanov via gtk-list <[hidden email]> wrote:
> [snip]
> > However, as I understand it, if my signal is running in the main
> > context, the signal handler should not be running at the same time as
> > Gtk is recalculating/repainting the TreeView. It seems as if the
> > threaded signal handler is not running in the main context. The above
> > behavior is replicated even if I switched to use g_idle_add() instead
> > of g_main_context_invoke_full().
>
> I am not going to try to penetrate your code, and you may already know
> this but a GObject signal handler executes in the thread which emits on
> the signal.  If this is a GDK/GTK+ signal, this would/should be, in
> almost all cases, the thread in which GTK+ runs, namely the thread
> of the default main context.
>
> g_idle_add() does not of itself emit a signal.  It executes a callback
> in the main loop of the default main context.
>
> Chris
> _______________________________________________
> gtk-list mailing list
> [hidden email]
> https://mail.gnome.org/mailman/listinfo/gtk-list
_______________________________________________
gtk-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtk-list
Reply | Threaded
Open this post in threaded view
|

Re: Emitting signals from threads

Nicola Fontana-3
In reply to this post by Gtk+ - General mailing list
Il giorno mar, 08/01/2019 alle 10.02 -0800, Mitko Haralanov via gtk-list ha
scritto:
> Thanks for the reply.
> ...

Hi,

I find this mail thread really confusing and with a lot of misleading
guesses. As already stated elsewhere, a minimal working example would
likely be a *much* quicker way to solve your problem. I'd also suggest
to start a new clean mail thread.

> One of the main reasons why I am not using g_idle_add() is the timing
> of the callback. I don't want to defer the processing of the callback
> to the "idle" time since this is signal handling related.

g_main_context_invoke is just a wrapper around an idle GSource:

https://gitlab.gnome.org/GNOME/glib/blob/master/glib/gmain.c#L5854

There no magic speed gain in using it instead of g_idle_add: it just
happens to be more convenient.

> Another advantage of g_main_context_invoke[_full]() is that it will
> check the "context" of the caller and, if possible, will call the
> callback directly:

Here rings an alarm bell: you are in a worker thread and you want to
execute some code in the GTK thread; how can you expect that code to be
called directly?

In another email you said:

> The only thing that the threaded signal callback is doing is changing
> the *model*, which should be allowed.

I don't know what a "threaded signal callback" is, but if with that you
meant code executed in the worker thread, can you please point me where
you got the idea that the model could be changed from outside the GTK
thread? I always thought this was *not* allowed.

Apart from that I still did not understand if you have problems with
threads, with timing, with user interface not updating properly or
other.

Ciao.
--
Nicola


_______________________________________________
gtk-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtk-list
Reply | Threaded
Open this post in threaded view
|

Re: Emitting signals from threads

Gtk+ - General mailing list
In reply to this post by Gtk+ - General mailing list
On Wed, 27 Feb 2019 14:08:34 -0800
Mitko Haralanov <[hidden email]> wrote:

> On Wed, Feb 27, 2019 at 1:10 PM Chris Vine via gtk-list
> <[hidden email]> wrote:
> >
> > On Wed, 27 Feb 2019 09:49:43 -0800
> > Mitko Haralanov via gtk-list <[hidden email]> wrote:
> > [snip]
> > > However, as I understand it, if my signal is running in the main
> > > context, the signal handler should not be running at the same time as
> > > Gtk is recalculating/repainting the TreeView. It seems as if the
> > > threaded signal handler is not running in the main context. The above
> > > behavior is replicated even if I switched to use g_idle_add() instead
> > > of g_main_context_invoke_full().
> >
> > I am not going to try to penetrate your code, and you may already know
> > this but a GObject signal handler executes in the thread which emits on
> > the signal.  If this is a GDK/GTK+ signal, this would/should be, in
> > almost all cases, the thread in which GTK+ runs, namely the thread
> > of the default main context.
> >
> > g_idle_add() does not of itself emit a signal.  It executes a callback
> > in the main loop of the default main context.
>
> Hi Chris,
>
> I am not expecting g_idle_add() to emit the signal. I am calling a
> separate function scheduled by g_idle_add() or
> g_main_context_invoke_full(), which does the signal emission. I use
> g_idle_add()/g_main_context_invoke_full() to ensure that this callback
> is, in fact, running in the main context thread.
>
> However, despite the signal emission occurring in the main context
> thread, the signal handler seems to be running at the same time as GTK
> internal functions are updating the state of the TreeView columns. As
> I understand GTK, this should not be possible.

It depends on what you mean by "at the same time".  They ought not to be
running concurrently in different threads assuming you are not trying
set that up yourself with the deprecated gdk_threads_enter()/leave() and
so forth.  But if the signal handler surrenders control to the main loop
by posting its continuations to the main loop using g_idle_add_full()/
g_main_context_invoke_full() or their cognates, and the "GTK internal
functions ... updating the state of the TreeView columns" to which you
refer do the same, then the continuations may interleave.  Plenty of
GDK drawing works that way, as I understand it.

I am not saying that is what is happening here (I haven't looked at
the code), but it might be.

Chris
_______________________________________________
gtk-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtk-list
Reply | Threaded
Open this post in threaded view
|

Re: Emitting signals from threads

Gtk+ - General mailing list
In reply to this post by Nicola Fontana-3
I could start a new thread but will be confusing for anyone who may be
reading this thread a year from now researching a similar problem.

So, with that said, let me try to clarify:

The application has a GtkTreeView being populated by a GtkTreeModel.
The TreeView has 3 columns, the last one having a GtkCellRenderPixbuf
displaying a "gtk-edit" icon. The TreeView also has a
button-presse-event callback connected, which checks where in the
TreeView the mouse button has clicked and if it happens to be on the
last column/renderer, opens an "Edit" dialog box. One of the other
columns of the TreeView has a GtkCellRendererSpinner attached to it.
This cell render has a cell data function that will "spin" the spinner
when the model gets updated. The GtkTreeModel backing the TreeView
contains a column that is of type guint64. This is the value that
causes the GtkCellRendererSpinner to "spin" when it gets updated.

The actual event which causes the model to get updated is the
application finding a file on the filesystem matching a certain
pattern. This discovery process is happening in a worker thread as to
not block the main UI. In that worker thread, the filesystem is
scanned recursively looking at all files in a directory tree. When a
file matching the pattern is found, a function is scheduled using
g_idle_add()/g_main_context_invoke_full(). This callback is what
actually emits a signal whose handler updates the model.

So, the worker thread is not doing the *real* signal emission. It's
just scheduling a function to run in the main context thread, which
does the *real* signal emission.

As I mentioned in a previous email, I haven't had a lot of time to
create a separate application to show this. I can try to do that if
things are still not clear but I was hoping that the additional
information, which I posted earlier might be useful.

Thank you,
- Mitko

On Wed, Feb 27, 2019 at 2:18 PM Fontana Nicola <[hidden email]> wrote:

>
> Il giorno mar, 08/01/2019 alle 10.02 -0800, Mitko Haralanov via gtk-list ha
> scritto:
> > Thanks for the reply.
> > ...
>
> Hi,
>
> I find this mail thread really confusing and with a lot of misleading
> guesses. As already stated elsewhere, a minimal working example would
> likely be a *much* quicker way to solve your problem. I'd also suggest
> to start a new clean mail thread.
>
> > One of the main reasons why I am not using g_idle_add() is the timing
> > of the callback. I don't want to defer the processing of the callback
> > to the "idle" time since this is signal handling related.
>
> g_main_context_invoke is just a wrapper around an idle GSource:
>
> https://gitlab.gnome.org/GNOME/glib/blob/master/glib/gmain.c#L5854
>
> There no magic speed gain in using it instead of g_idle_add: it just
> happens to be more convenient.
>
> > Another advantage of g_main_context_invoke[_full]() is that it will
> > check the "context" of the caller and, if possible, will call the
> > callback directly:
>
> Here rings an alarm bell: you are in a worker thread and you want to
> execute some code in the GTK thread; how can you expect that code to be
> called directly?
>
> In another email you said:
>
> > The only thing that the threaded signal callback is doing is changing
> > the *model*, which should be allowed.
>
> I don't know what a "threaded signal callback" is, but if with that you
> meant code executed in the worker thread, can you please point me where
> you got the idea that the model could be changed from outside the GTK
> thread? I always thought this was *not* allowed.
>
> Apart from that I still did not understand if you have problems with
> threads, with timing, with user interface not updating properly or
> other.
>
> Ciao.
> --
> Nicola
>
>
_______________________________________________
gtk-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtk-list
12