LINUX.ORG.RU

Инициализация модуля с наименьшим оверхедом в си

 


0

2

Есть либа (A-Library), предоставляющая некоторые функции. Она коннектится к другой либе (B-Library) и получает некую структуру:

typedef struct
{
   int a;
   int b;
   ...
   char z[256];
} AAA;

# In A-Library
int SomeFunc()
{
  AAA * aaa = GetAAAFromB();

  /// Do stuff
}

int SomeMoreFunc()
{
  AAA * aaa = GetAAAFromB();

  /// Do more stuff
}

int SomeEvenMoreFunc()
{
  AAA * aaa = GetAAAFromB();

  /// Do even more stuff
}

Понятно, что може например вынести ее глобально (как вариант через static):

# In A-Library
AAA * aaa = NULL;

int SomeFunc()
{
  if (!aaa) aaa = GetAAAFromB();

  /// Do stuff
}

int SomeMoreFunc()
{
  if (!aaa) aaa = GetAAAFromB();

  /// Do more stuff
}

int SomeEvenMoreFunc()
{
  if (!aaa) aaa = GetAAAFromB();

  /// Do even more stuff
}

Вопрос - как с наименьшим оверхедом проинициализировать ее? Нужно:
1. Обойтись без LibraryAInit функции
2. Обойтись без компиляторого-зависимых решений (need c89)
3. Обойтись без костылей в виде проверки в каждой функции, функций много и выглядит костыльно.
4. Представить что GetAAAFromB выполняется долго.

Может как-то намутить с адресами на функцию? Типа сначала адрес на GetAAAFromB, а потом на func() { return aaa; } ? Какие еще есть идеи?

★★★★★

Последнее исправление: PPP328 (всего исправлений: 1)

Чем не устраивает?

AAA *GetAAAFromA(void)
{
  static AAA *a = NULL;
  if (!a)
    a = GetAAAFromB();
  return a;
}
anonymous
()

По-моему вариант с if (!aaa) aaa = GetAAAFromB(); самый нормальный, если сделать этот код отдельной функцией.

Можно и как ты хочешь намутить с адресами. Так динамическая линковка функций работает. Тогда используй указатель на функции и меняй его после инициализации

urquan
()
Последнее исправление: urquan (всего исправлений: 1)

Можно попробовать использовать конструктор библиотеки.

AAA *aaa = NULL;
void __attribute__ ((constructor)) AAAInit(void) {
   aaa = GetAAAFromB();
}

Moncruist
()
Ответ на: комментарий от Moncruist

Не можно. Потому что я не зря упомянул c89 и не-компилятор специфичные фичи. Потому что для чего-то кроме жсс ваш код должен выглядеть подобно этому:

    // Initializer/finalizer sample for MSVC and GCC/Clang.
    // 2010-2016 Joe Lowe. Released into the public domain.
#include <stdio.h>
#include <stdlib.h>

#ifdef __cplusplus
    #define INITIALIZER(f) \
        static void f(void); \
        struct f##_t_ { f##_t_(void) { f(); } }; static f##_t_ f##_; \
        static void f(void)
#elif defined(_MSC_VER)
    #pragma section(".CRT$XCU",read)
    #define INITIALIZER2_(f,p) \
        static void f(void); \
        __declspec(allocate(".CRT$XCU")) void (*f##_)(void) = f; \
        __pragma(comment(linker,"/include:" p #f "_")) \
        static void f(void)
    #ifdef _WIN64
        #define INITIALIZER(f) INITIALIZER2_(f,"")
    #else
        #define INITIALIZER(f) INITIALIZER2_(f,"_")
    #endif
#else
    #define INITIALIZER(f) \
        static void f(void) __attribute__((constructor)); \
        static void f(void)
#endif

static void finalize(void)
{
    printf( "finalize\n");
}

INITIALIZER( initialize)
{
    printf( "initialize\n");
    atexit( finalize);
}

int main( int argc, char** argv)
{
    printf( "main\n");
    return 0;
}

anonymous
()
Ответ на: комментарий от PPP328

Где?

В варианте с глобальной переменной.

Указатель на структуру AAA не поменяется

?? aaa - поменяется.

anonymous
()

Вопрос - как с наименьшим оверхедом

Вопрос - у тебя это реально узкое место во всей системе или просто преждевременная оптимизация?

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.