スレッドの中で作った構造体と通信を行う方法

これまでC/C++言語で作ってきたスケーラブルなエージェントシミュレーションを、golangで作りかえようとしています。

これまでもメイン関数に縛られずに、スレッドを自由に動き回すシミュレータは作ってきたのですが、C/C++のスレッドは、いかんせんメモリサイズが大きく、万の単位のエージェントには耐えられないという問題があります。

そんな感じで、golangに乗り換えしているのですが、色々文法が面倒くさいです。

例えば、スレッドの中で作った構造体と通信を行う方法として、go func() で返り値(return)が欲しいと思っていたのだけど、考えてみれば、スレッド化したfunc()は、それが終了するまでreturn値を返す訳ないと気がつきました。

だから,

go func_xxxx()

は、

go i:= finc_xxxx()

もダメだし

i := go func_xxxx()

もダメということで ―― では、スレッドの中の情報にどうやってアクセスすればいいかが、分かりません。

とすれば、スレッド側で送受信機能を持たせることになるのかなぁ、と思って、以下のようなコードを書いてみました。

package main

import (
	"fmt"
	"sync"
)

type BUS struct {
	number int
}

func bus_func(i int, wg *sync.WaitGroup, ch chan int) {
	defer wg.Done()

	bus := BUS{}
	bus.number = i

	pointer_bus := &bus

	fmt.Println(pointer_bus)

	for {
		select {
		case v := <-ch:
			fmt.Println(i, v)
		}
	}

}

func main() {
	var wg sync.WaitGroup
	defer wg.Wait()

	c := make(chan int)

	// バスエージェントの生成 3台
	for i := 0; i < 3; i++ {
		wg.Add(1)

		go bus_func(i, &wg, c)
	}

	// バスエージェントにメッセージを送る

	c <- 50
	c <- 30
	c <- 10

	c <- 50
	c <- 30
	c <- 10

	c <- 50
	c <- 30
	c <- 10

}

ただ、この場合、cチャネルは適当に投げられるので、どのオブジェクトにメッセージに届くか分からないので、もう少し工夫をしてみます。

package main

import (
	"fmt"
	"sync"
)

type BUS struct {
	number int
}

func bus_func(i int, wg *sync.WaitGroup, ch chan int) {
	defer wg.Done()

	bus := BUS{}
	bus.number = i

	pointer_bus := &bus

	fmt.Println(pointer_bus)

	for {
		select {
		case v := <-ch:
			fmt.Println(i, v)
		}
	}

}

//var c = make([]chan int, 3) // 間違い

var c [3]chan int // チャネルをグローバル変数で置く方法の、現時点での正解

// var c []chan int  これは実行時にエラーとなる

func main() {
	var wg sync.WaitGroup
	defer wg.Wait()

	//c := make(chan int)

	// バスエージェントの生成 3台
	for i := 0; i < 3; i++ {
		wg.Add(1)

		c[i] = make(chan int)
		go bus_func(i, &wg, c[i])
	}

	// バスエージェントにメッセージを送る

	c[0] <- 50
	c[1] <- 30
	c[2] <- 10

	c[0] <- 50
	c[1] <- 30
	c[2] <- 10

	c[0] <- 50
	c[1] <- 30
	c[2] <- 10

}