リスト処理をマクロで書いてみた

C言語でリスト処理を作るときに、普通の関数で作ると引数の型に柔軟性を持たせにくくなって、セルになる構造体のデータ毎に関数をつくらざるをえないようなことになったりもする。


C++であればtemplateなんかでもよいのだろうけど、C言語だけで書くには困ってしまう。


そこで、マクロでリストの処理を書いてみた。
リスト処理はしょっちゅう必要になるので(何に?)ここにまとめておくとよいかなーと思った。

Macでeditすると¥が?に置き換わる。。



#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>

#define init_cell(cell) { ?
  (cell)->prev = (cell)->next = NULL; ?
}

#define init_list(list) { ?
  (list)->head = (list)->tail = NULL; ?
  pthread_mutex_init(&((list)->mutex), NULL); ?
}
  
#define push_list(list, cell) { ?
  (cell)->next = NULL; ?
  pthread_mutex_lock(&((list)->mutex)); ?
  if((list)->head != NULL) { ?
    (cell)->prev = (list)->tail; ?
    (list)->tail->next = cell; ?
    (list)->tail = cell; ?
  } else { ?
    (cell)->prev = NULL; ?
    (list)->head = (list)->tail = cell; ?
  } ?
  pthread_mutex_unlock(&((list)->mutex)); ?
}

#define pop_list(list, cell) ?
{ ?
  pthread_mutex_lock(&((list)->mutex)); ?
  *(cell) = (list)->head; ?
  if((list)->head != NULL) { ?
    (list)->head = (list)->head->next; ?
    if((list)->head != NULL) { ?
      (list)->head->prev = NULL; ?
    } ?
    (*(cell))->next = NULL; ?
  } ?
  pthread_mutex_unlock(&((list)->mutex)); ?
}

ここより下は上記マクロの動作確認用。同じファイルにくっつけるなり、上のコードをヘッダに書いておいてincludeするなりしてください。

struct sample_cell_a {
  struct sample_cell_a *prev;
  struct sample_cell_a *next;
  int data;
};


struct sample_list_a {
  struct sample_cell_a *head;
  struct sample_cell_a *tail;
  pthread_mutex_t mutex;
};

#define CELLNUM (5)

void show_list(const char *str, struct sample_list_a *list)  { 
  struct sample_cell_a *tmp = list->head;
  printf("-- %s --?n", str);
  while(tmp != NULL) {
    printf("prev=%016p cell=%016p next=%016p data=%d?n",
         tmp->prev, tmp, tmp->next, tmp->data);
    tmp = tmp->next;
  }
}

int main(int argc, char **argv) {
  struct sample_cell_a *tmp;
  struct sample_cell_a cell[CELLNUM];
  struct sample_list_a list;
  int i;
  for(i=0;i<CELLNUM;i++ ) {
    init_cell(&cell[i]);
    cell[i].data = i;
  }
  init_list(&list);

  for(i=0;i<CELLNUM;i++ ) {
    push_list(&list, &cell[i]);
    show_list("pushed", &list);
  }

  while(1) {
    pop_list(&list, &tmp);
    if(tmp == NULL) {
      break;
    }
    show_list("popped", &list);
  }
  return 0;
}

listをロックするように修正しました。
次はqueueかな。そのあとhashでそのあとTimerかなぁ。