Как проверить, вызывает ли функция обратный вызов - PullRequest
0 голосов
/ 15 декабря 2018

Допустим, у нас есть функция C funA в библиотеке, внутри funA она будет вызывать некоторые другие функции funB, funC, .etc.Вполне возможно, что funB и funC могут перезвонить funA.Итак, вопрос: возможно ли обнаружить эту ситуацию только внутри funA, что-то вроде:

void funA(void) {
    if (...) {
         // Calling back to funA
    }

}

Заключение

  • В среде с одним потоком,статическая / глобальная переменная будет работать.
  • В многопоточной среде придется зависеть от поддержки TLS.
  • У меня нет ответа, который мог бы достичь этого только на уровне языка (C)трюки

Ответы [ 4 ]

0 голосов
/ 15 декабря 2018

может быть, другой подход, который вы можете идентифицировать звонящего:

void func_a(void *ptr);
void func_b(void);
void func_c(void);

void func_a(void *caller)
{
    if(caller == func_a)
    {
        printf("called from func_a\n");
        return;
    }
    if(caller == func_b)
    {
        printf("called from func_b\n");
        return;
    }    
    if(caller == func_c)
    {
        printf("called from func_c\n");
        return;
    }    
    if(caller == NULL)
    {
        printf("called from somewhere elese - going to call myself\n");
        func_a(func_a);
    }
}

void func_b()
{
    func_a(func_b);
}

void func_c()
{
    func_a(func_c);
}

int main()
{
    func_b();
    func_c();
    func_a(NULL);

    return 0;
}
0 голосов
/ 15 декабря 2018

Это можно сделать с помощью статического флага.

Когда функция вызывается, если флаг не установлен, установите его и продолжайте, иначе вернитесь сразу же.Затем в конце функции вы снимаете флажок, чтобы вы могли ввести его снова.

void funcA(void) 
{
    static int callback = 0;

    if (callback) return;
    callback = 1;
    ...
    callback = 0;
}

Если вам нужно работать в нескольких потоках отдельно, вы можете объявить переменную как _Thread_local вместо static.

0 голосов
/ 15 декабря 2018

С уровнем косвенности вы можете даже посчитать, сколько раз ваша функция была вызвана:

void func( int count )
{
    printf( "Count is %d\n", count );
    if ( ... ) // no longer want to recurse...
    {
        return;
    }
    func( count + 1 );
}

// wrap the actual recursive call to hide the parameter
void funA()
{
    func( 0 );
}

Таким образом, она полностью поточнобезопасна.Если вам не нужна функция-оболочка или передаваемый параметр, вы можете использовать хранилище, специфичное для потока .

0 голосов
/ 15 декабря 2018

Если это только один вызов, вы можете установить глобальный / статический флаг после вызова этой функции и проверить его в начале.Или, чтобы снять ограничение на одиночный вызов, вы можете сбросить этот флаг перед возвратом функции.Примерно так:

void funA(void) {
    static bool used = false;
    if (used)
    {
        printf("It is used!\n");
    }
    used = true;

    // .... Do stuff here, including possible recursion

    used = false;
}

Примечание - это не будет работать с многопоточностью - эта функция не реентерабельна ..

...