import pycsp

Channel = pycsp.Channel

def chan(*n):
	'''Create a channel. If an argument is given, it specifies
	the buffer size (default 0, unbuffered)'''
	if len(n) == 0:
		n = 0
	else:
		n = n[0]
	if n > 0:
		c = pycsp.BufferedAny2OneChannel(buffer = pycsp.FifoBuffer(n))
	else:
		c = pycsp.Any2OneChannel();
	return c;

def alt(*cs):
	'''alt(chan....)
	Alt waits until one of the channels becomes ready for reading,
	then returns its read member - it is up to the caller
	to do the read'''
	return pycsp.Alternative(*map(lambda c: c.read, cs)).select();

def altf(*cs):
	'''altf(chan..., fn, chan..., fn, ...)
	Altf waits until one of the channels is ready for reading,
	then reads from it, calls its associated function,
	and returns the result of that call.'''

	as = []
	fs = []
	i = 0
	while i < len(cs):
		j = i
		while isinstance(cs[j], Channel):
			j = j + 1
		if i == j:
			raise 'expected channel(s)'
		f = cs[j]
		k = i
		while k < j:
			as.append(cs[k].read)
			fs.append(f)
			k = k + 1
		i = j + 1
	a = pycsp.Alternative(*as)
	s = a.select()
	i = 0
	while i < len(as):
		if s == as[i]:
			return fs[i](s())
		i = i + 1

def spawn(f, *args, **kwargs):
	pycsp.Process(f, *args, **kwargs).start();
