|
|
| Посл.отвђт | Сообщенiе |
|
|
Дата: Авг 28, 2003 23:57:36 · Поправил: Безпощадный даос Итак, господа. Новая проблемка для алгоритмизаторов. Заранее спасибо за помощь! Имеем функцию: hugefunction(char *func_name); которая принимает на вход имя функции, которую она должна выполнить и зовет функцию с этим именем. Где-то так:
hugefunction(char *func_name)
{
...
if(!strcmp(func_name, "do_this"))
do_this();
else if(!strmp(func_name, "do_that"))
do_that();
else if ... еще хренова туча сравнений
... и вызовов функций при необходимости...
}
Очевидно, функция далека от идеала. Если, скажем, имя "do_it_at_last" стоит в самом конце, то можно подсчитать, сколько времени потратится на то, чтобы добраться до нее! Далее в этом же файле стоит непосредственно исходный код функций do_this, do_that, do_it_at_last и т.п. Как это дело можно улучшить? Ну, первое, что приходит на ум, это взять и подсчитать хеши функций и вписать их в файл вместо имен и сравнивать не строки, а хеши, т.е. unsigned long или что-то еще. Уже быстрее. Тогда нужна хорошая хеш-функция без коллизий. А теперь вопросы к спецам 1) Какая такая есть хорошая функция, чтобы на выходе unsigned long получить? 2) Вероятно, можно еще более улучшить производительность, скажем, создав какой-нибудь массив, отсортировать его и находить там элемент бинарным поиском, а что потом - я пока не дотумкал? Ну что, кто меня будет пинать :) |
|
|
Дата: Авг 29, 2003 00:16:57 2) looks very nice.
typedef int (*FUNCTYPE) (int, char*);
typedef struct
{
char* pstrFuncName;
FUNCTYPE pfnCallThisCode;
}
FUNCMAPSLOT;
// Prototypes:
int foo1 (int, char*);
int foo2 (int, char*);
int foo3 (int, char*);
// Map itself:
FUNCMAPSLOT mapAll [] = {
{ "foo1", foo1 }, // Can be optimized with ## operators
{ "foo2", foo2 },
{ "foo3", foo3 },
};
// Bodies:
int foo1 (int, char*)
{
return 0;
}
int foo2 (int, char*)
{
return 0;
}
int foo3 (int, char*)
{
return 0;
}
// Sort the 'mapAll' by 'pstrFuncName':
// TODO: ...
// And then with binary search call the entry's
// member 'pfnCallThisCode'.
It works with the 'foo_xxx()' where parameters are the same, but with diff. parameters you need to 'trick' compiler... |
|
|
Дата: Авг 29, 2003 00:25:53 AsmGuru62 1) Меня не слишком вдохновляет, что имена в mapAll символьные, а не хеши - это медленно. 2) ПРИНЦИПИАЛЬНОЕ ограничение на параметры функции - лучше бы как-то хранить массив и поинтеров на функции, который создавать динамически и заполнять его по мере надобности (только я не знаю как %() |
|
|
Дата: Авг 29, 2003 00:50:34 Да, статья по основам хеширования лежит на RSDN.ru. И еще - язык - именно С. Алгоритм можно проиллюстрировать и на С++, но STL мне предлагать использовать не надо. Еще раз спасибо. |
|
|
Дата: Авг 29, 2003 00:55:03 А что если подставить в эту же структуру CRC32 от имени функции? Перед сортировкой пройтись по именам функций и сделать для них CRC32.
typedef struct
{
char* pstrFuncName;
FUNCTYPE pfnCallThisCode;
UINT crc32FuncName; // Sort and binary scan for this!
}
FUNCMAPSLOT;
|
|
|
Дата: Авг 29, 2003 00:56:33 volodya А как часто надо динамически строить такие массивы? |
|
|
Дата: Авг 29, 2003 00:59:28 Очень хорошо. CRC32 вот:
unsigned hashCrc(char *string)
/* Returns a CRC value on string. */
{
unsigned char *us = (unsigned char *)string;
unsigned char c;
unsigned shiftAcc = 0;
unsigned addAcc = 0;
while ((c = *us++) != 0)
{
shiftAcc <<= 2;
shiftAcc += c;
addAcc += c;
}
return shiftAcc + addAcc;
}
Т.о. мы решили проблему с CRC32. Далее, ты предлагаешь заводить структуры... Т.е. массив из структур. Как часто его надо создавать? Это CGI приложение. Следовательно, на каждый http-запрос надо его запускать и создавать такой массив. Только я не понимаю ту его часть, что с pstrFuncName и pfnCallThisCode - она не будет работать %( |
|
|
Дата: Авг 29, 2003 02:52:04 Вообще я не понимаю пока особо эти указатели на функции. Скорее всего, на стадии компиляции, теоретически, это нереализуемо. Значит, скорее всего, от массива с void * придется отказаться. Вероятно, это будет что-то со switch/case. Или я не прав? |
|
|
Дата: Авг 29, 2003 02:56:31 AsmGuru62 А зачем пихать в структуру и "имя ф-ции" и CRC32? Достаточно хранить только CRC32 (+ адрес ф-ции, ессно). volodya А hugefunction(char *func_name) нельзя переделать в hugefunction(UINT crc)? Пусть клиентская часть приложения считает CRC вместо серверной части. Обычно принято перекладывать максимум работы на клиента. |
|
|
Дата: Авг 29, 2003 03:20:51 Quantum это хорошо и идея классная, но, пардон, вынужден хранить обратную совместимость с уже написанным (не мной) мусором, который изначально безграмотно проектировался. Только я не представляю как можно запихнуть в структуру адрес функции. :( |
|
|
Дата: Авг 29, 2003 04:04:19 · Поправил: Quantum volodya Только я не представляю как можно запихнуть в структуру адрес функции. typedef int (CALLBACK *FARPROC)();
struct myStruct{
FARPROC address;
UINT crc32;
}; |
|
|
Дата: Авг 29, 2003 04:34:02 · Поправил: volodya Да нет, не совсем то. Во-первых, почему после typedef идет int. Во-вторых, как туда положить РЕАЛЬНЫЙ адрес? В третьих - функция может вернуть вовсе не int, а, скажем, char *, а то и вообще указатель на сложную структуру... По-моему, тут решения нет. :(((( |
|
|
Дата: Авг 29, 2003 04:38:56 volodya почему после typedef идет int Потому что адрес 32-битный. как туда положить РЕАЛЬНЫЙ адрес? myStruct test;
test.address = (FARPROC)myFunction;
// . . .
void myFunction(void){}
... или я опять не совсем понял? |
|
|
Дата: Авг 29, 2003 06:05:12 · Поправил: volodya test.address = (FARPROC)myFunction; т.е. заполнение динамическое! Т.е., если массив содержит, скажем, 300 функций, мне что, звать все 300 функций? Может уже я не очень понимаю? Логика программы:
/*подготовка массива, что включает в себя, ну...
скажем так, я бы просто хранил все подсчитанные суммы
внутри файла как хеш, т.е. массив из структур выглядел бы так:
array[0] -> 123456, void*
array[1] -> 789012, void* и т.п.
Т.е. часть массива готовится уже на стадии компиляции, а для добавления новой функции написать малюсенькую программу, которая пересчитает имя в хеш, а хеш добавлять в .c-файл.*/
hugefunction(char *func_name)
{
hash = hashCrc(char *func_name); //вычисляем, к сожалению, на стороне сервера
qsort(наш родимый массив из структур);
bsearch(в массиве из структур ищем hash);
//далее каким-то магическим образом берем поинтер на эту функцию
ну а далее просто вызывается нужная функция;
//так я себе это мыслю...
}
|
|
|
Дата: Авг 29, 2003 06:08:41 Quantum Главное требование к этому коду, как и ко всему коду, что я пишу - это то, что он должен успешно компилироваться и работать под 3 осями минимум - Windows/Linux/Solaris - под Солярисом у нас стоят спарки, а это значит, что Я НЕ МОГУ РАССЧИТЫВАТЬ НА ТО, ЧТО АДРЕС БУДЕТ 32-битным. |
|
Powered by miniBB 1.6 © 2001-2002
Время загрузки страницы (сек.): 0.093 |