matz / zetabits.com (Yukihiro Matsumoto) wrote:
> Hi,
> 
> In message "[ruby-talk:6392] Re: lots of Threads"
>     on 00/11/16, hipster <hipster / xs4all.nl> writes:
> 
> |(META: would a pthread impl. of Ruby be a Good Thing[tm]?)
> 
> I really want two things for pthread:
> 
>   * scheme to get list of existing threads
>   * scheme to get stack region addresses for arbitrary thread
> 
> I can make pthread Ruby (especially GC) if I get these.
> 
> 							matz.

You can do something like this.  It will let you always have whatever
info you need...

static VALUE pthreads = Qnil;
/* protect from modification during startup, whatever */
pthread_mutex_t pthread_junk_mutex = PTHREAD_MUTEX_INITIALIZER;

void
rb_pthread_init(void) {

	pthreads = rb_ary_new();
}

void
rb_thread_cleanup(void *me) {
	pthread_mutex_lock(&pthread_junk_mutex);
	pthreads.delete_if {|x|
		*(void **)&x->data[0 * sizeof(void *)] == me
	}
	pthread_mutex_unlock(&pthread_junk_mutex);
	
}


void
rb_pthread_start(struct pthread_startinfo *startinfo) {
	unsigned char threadinfo[2 * sizeof(void *)];
	*(void **)&threadinfo[0 * sizeof(void *)] = pthread_self();
	*(void **)&threadinfo[1 * sizeof(void *)] =
	    pthread_attr_getstackaddr(attr);
	pthread_attr_destroy(startinfo->attr);
	pthread_cleanup_push(rb_thread_cleanup, pthread_self());
	rb_ary_push(pthreads, startinfo.to_struct_etc);
	pthread_mutex_unlock(&pthread_junk_mutex);
	rb_pthread_run(startinfo->block);
	rb_pthread_cleanup(pthread_self());
	pthread_exit(NULL);

VALUE
rb_pthread_new(VALUE self, VALUE block) {
	pthread_attr_t attr;
	/* should specify your own stack policy */
	void *newstack = malloc(STKSIZE);
	newthread = Thread.new();
	pthread_attr_init(&attr);
	pthread_attr_setstacksize(&attr, newstack);
	/* lock here (for thread info), release next when child runs */
	pthread_mutex_lock(&pthread_junk_mutex);
	rb_pthread_start([attr, block, etc.]);
	newthread.do_whatever();
	return (newthread);
}

/* stuff like kill, Thread.list, etc. would need this */
void
rb_pthread_anything_involving_current_state_of_other_threads(...) {
	pthread_mutex_lock(&pthread_junk_mutex);
	do stuff;
	pthread_mutex_unlock(&pthread_junk_mutex);
}