C言語でオブジェクト指向ってこうゆうこと?


 なんか世の中には、C言語オブジェクト指向的な書き方を説明した本が有るとのこと。
ん〜、こんな感じかな?c11のthreads.hを試したメモ - 会者定離で以降のときに作った残念Stackを、オブジェクト指向っぽく書き直したの。


 ちなみにStackサイズ固定なのは、可変実装がむずかしそうだったのと固定でないとFullにならないから*1><

enum{S_SIZE = 10};
typedef struct Stack{
	int v_[S_SIZE];
	/* int vsize_; */
	int vused_;
	mtx_t mtx_;
	cnd_t cnd_push_;
	cnd_t cnd_pop_;
} Stack10;

int stack10_Constructor(Stack10 *s){
	int ret;
	
	ret = mtx_init(&s->mtx_, mtx_plain);
	if(ret != thrd_success){
		return ret;
	}
	
	ret = cnd_init(&s->cnd_push_);
	if(ret != thrd_success){
		return ret;
	}

	ret = cnd_init(&s->cnd_pop_);
	if(ret != thrd_success){
		return ret;
	}

	return 0;
}

void stack10_Destructor(Stack10 *s){
	mtx_destroy(&s->mtx_);
	cnd_destroy(&s->cnd_push_);
	cnd_destroy(&s->cnd_pop_);
}


int stack10_push(Stack10 *s, int x){
	mtx_lock(&s->mtx_);
	
	while(s->vused_ >= S_SIZE){
		cnd_wait(&s->cnd_push_, &s->mtx_);
	}
	s->v_[s->vused_++] = x;

	cnd_signal(&s->cnd_pop_);
	mtx_unlock(&s->mtx_);
	return 0;
}

int stack10_pop(Stack10 *s, int *x){
	mtx_lock(&s->mtx_);
	
	while(s->vused_ == 0){
		cnd_wait(&s->cnd_pop_, &s->mtx_);
	}
	*x = s->v_[--s->vused_];
	
	cnd_signal(&s->cnd_push_);
	mtx_unlock(&s->mtx_);
	return 0;
}


 使うときは、こんな感じ。個人的にmalloc/freeしなくて済むならそっちのほうが好きなので、「stack10_Constructor()で、Stack10構造体をmallocして〜」って実装にはしなかった。


 ほい、まあC言語っぽくてやっつけにしては良さげである^^
まあ素直に、C++使っとけって感じである。

int func(void *arg)
{
	int i;
	Stack10 *s =(Stack10*)arg;
	printf("thrd_current()vim is %ld\n", (unsigned long int)thrd_current());
	for(i = 0; i<3; ++i){
		stack10_push(s, i);
	}
	return 0;
}

int main()
{
	int i, n;
	Stack10 s = {{0},0};
	
	enum {SIZE = 4};
	thrd_t thr_s[SIZE];

	/*
	 * init
	 */
	stack10_Constructor(&s);

	/*
	 * run
	 */
	for(i=0; i<SIZE; i++) {
		thrd_create(&thr_s[i], func, (void*)(Stack10*)&s);
	}

	for(i=0; i<(SIZE*3); i++){
		stack10_pop(&s, &n);
		printf("%d : %d\n",i,n);
	}

	for(i=0; i<SIZE; i++) {
		thrd_join(thr_s[i], 0);
	}


	/*
	 * destroy
	 */
	stack10_Destructor(&s);
	
	return 0;
}

P.S. 2015Apr25


なんの本で読んで知ったか思い出した。


読書会で読んだC++のためのAPIデザインの「5.1.3. ANSI CによるAPIの記述」で、こんなStackのC言語オブジェクト指向でのAPI設計を読んだ読んだ><


まあ結構スタンダードな実装方法だとは思うので、コメントで教えて貰ったように、なんかのドライバでも似たような実装を見たもする。


C++のためのAPIデザイン
マーティン・レディ Martin Reddy
ソフトバンククリエイティブ
売り上げランキング: 28,989

*1:threadのwaitさせたかったので、固定長でpop待ちさせるためです