速度(コスト)を意識すること(前編)

 せっかくだからプログラムのことでも書こうか。
 でも、C言語
 もうC言語なんて忘れている! という気もするのだけれど、まぁ、書いてみる。

 こういう関数を見たことがある。
 リソースに対し何かしらハンドルを割り当てて管理したい、ってことだ。
 わりとありがち。

#include <stdio.h>

#define TRUE (!FALSE)
#define FALSE (0)

#define BOOL int

#define HANDLE int
#define HANDLE_MAX (128)

#define RESOURCE_NAME_LENGTH (32)

typedef struct tagResource {
	char name[RESOURCE_NAME_LENGTH];
	int value;
} Resource;

Resource* resource[HANDLE_MAX];

// ハンドルからリソースを得る
Resource* getResource(HANDLE handle)
{
    if( handle >= 0 && handle <= HANDLE_MAX ) {
       return resource[handle];
    }
    return NULL;
}

// リソースを確保して制御用のハンドルを得る
HANDLE allocateResource(void)
{
    int i;
    for( i = 0; i < HANDLE_MAX; i++ ) {
        if( resource[i] == NULL ) {
            resource[i] = (Resource*)malloc( sizeof(Resource) );
            return i;
        }
    }
    return -1;
}

// ハンドルに関連づけられたリソースを解放する
BOOL freeResource(HANDLE handle)
{
    if( handle >= 0 && handle <= HANDLE_MAX ) {
        if( resource[handle] != NULL ) {
            free( resource[handle] );
            resource[handle] = NULL;
            return TRUE;
        }
    }
    return FALSE;
}

// 言わずとしれたメイン関数
int main(int argc, char* argv[] )
{
    int i;
    for( i = 0; i < 150; i++ ) {
        HANDLE handle = allocateResource();
        Resource* resource = getResource(handle);
        printf( "[%d]\n", resource->value );
    }
    return 0;
}

 これって、ある種致命的な欠陥を持っている。
 取得速度が一定じゃないってこと。
 例えば、最初にハンドルを取得した場合の速度を「1」とすると、
 127までハンドルが使われていた場合に取得する速度は「128」となる。
 なんと128倍。
 もし1024まで使えるハンドルならそれは1024倍になる。
 極論ではあるし、(戻り値以外の問題で)バグるかといえばそうでもないが、
 ちょっとこういう関数だと使い道が難しい。
 加えて、戻り値が-1だとかなり拙い。バグっても分からないかもしれない。

 じゃあ、どうしたら良いかを考えていかなければならないってことだ。

 gccで実行してみたが、楽勝でエラーになる。
 え、150確保しているからね。