2017-11-30 14 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은 콜백이 중지되지 않는 이유는 무엇입니까?

편집 나는이 내 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 *'포인터를 주변에 놓고 참조를 유지하십시오.) 올바른 것입니다. –