2017-11-30 29 views
0

この関数を使用して、特定のGMainContextにタイムアウトコールバック(繰り返し)を追加しています。GLib:g_source_remove()デフォルト以外のGMainContextでタイムアウトコールバックを停止しない

guint GstThreadHelper::timeoutAdd(guint delay, GSourceFunc function, gpointer data) { 
    // See https://developer.gnome.org/programming-guidelines/stable/main-contexts.html.en#implicit-use-of-the-global-default-main-context 
    // It is important that all thread functions we invoke don't implicitly decide a maincontext. 
    // We must manually provide one. 
    GSource *source = NULL; 
    guint id; 

    source = g_timeout_source_new(delay); 
    g_source_set_callback (source, function, data, NULL); 
    id = g_source_attach (source, priv->mainContext); 
    g_source_unref (source); 

    return id; 
} 

その後、返されたidを使用してコールバックをキャンセルします。

void GstThreadHelper::timeoutRemove(guint id) { 
    g_source_remove(id); 
} 

ただし、コールバックはまだ呼び出されます。ここに私のコールバックです。

static gboolean position_update (gpointer user_data) 
{ 
    Player::PrivateData* priv = (Player::PrivateData*)user_data; 
    gint64 pos = 0; 

    if (gst_element_query_position (priv->playbin, GST_FORMAT_TIME, &pos)) { 
     pos = pos/1000000; 
     priv->callback->PositionChanged(pos); 
    } 

    // Call me again 
    return TRUE; 
} 

私はTRUEを返しています理解しますが、私の理解では、それはまだ停止しなければならないということです。 FALSEを返すことでコールバックをキャンセルすると、私はg_source_removeコールで気にしません。

なぜg_source_removeは私のコールバックが発生しないようにしますか?

EDIT私はこれで私のtimeoutAdd方法を交換する場合

...

guint GstThreadHelper::timeoutAdd(guint delay, GSourceFunc function, gpointer data) { 
    return g_timeout_add(delay, function, data); 
} 

は...それが動作します。ただし、これは使用できません。デフォルトのグローバルGMainContextではなく、特定のGMainContextでコールバックをトリガーしないためです。

EDIT2

私は私の関数にg_timeout_add_seconds_fullのデフォルトのソースをコピーし、それが働きました。

ただし、g_source_attachにプライベートGMainContextを使用するように変更した瞬間、それは失敗しました。

問題は、デフォルト以外のGMainContextで追加されたタイムアウトについてg_source_removeを呼び出すことと関係がある。

答えて

0

g_source_removeはグローバル/デフォルトGMainContextを使用していることを前提として動作していますが、この場合は私はそうではありません。

これはドキュメントでは読めません。

とにかく、ここに解決策があります。

void GstThreadHelper::timeoutRemove(guint id) { 
    GSource* source = g_main_context_find_source_by_id(priv->mainContext, id); 
    if (source) 
     g_source_destroy (source); 
} 

これはg_source_removeが何をしているのか、本質的であるが、代わりに私たちのプライベートGMainContextを使用。

+1

あなたはそれを持っています。これは 'g_source_remove()'のドキュメントで言及されています: "与えられたIDを持つソースをデフォルトのメインコンテキストから削除します"しかし、これを明確にするためにGLibに変更をプッシュします。 'g_source_destroy()'を使って(そして、 'guint'タグを渡すのではなく、' GSource * 'ポインタをあちこちに渡し、参照を保持して)、正しいです。 –

関連する問題