// included by ocbbs.cpp

void BBSImpl::subworld_worker_execute() {
	// execute the same thing that execute_worker is executing. This
	// is done for all the nrnmpi_myid_bbs == -1 workers associated with
	// the specific nrnmpi_myid == 0 with nrnmpi_myid_bbs >= 0.
	// All the nrnmpi/mpispike.c functions can be used since the
	// proper communicators for a subworld are used by those functions.
	// The broadcast functions are particularly useful and those are
	// how execute_worker passes messages into here.

//printf("%d enter subworld_worker_execute\n", nrnmpi_myid_world);
	int info[2];
	// wait for something to do
	nrnmpi_int_broadcast(info, 2, 0);
	// info[0] = -1 means it was from a pc.context. Also -2 means
	// DONE.
//printf("%d subworld_worker_execute info %d %d\n", nrnmpi_myid_world, info[0], info[1]);
	int id = info[0];
	if (id == -2) { // DONE, so quit.
		done();
	}
	hoc_ac_ = double(id);
	int style = info[1];
	if (style == 0) { // hoc statement form
		int size;
		nrnmpi_int_broadcast(&size, 1, 0); // includes terminator
		char *s = new char[size];
		nrnmpi_char_broadcast(s, size, 0);
		hoc_obj_run(s, nil);
		delete [] s;
//printf("%d leave subworld_worker_execute\n", nrnmpi_myid_world);
		return;
	}
	int i, j;
	int npickle;
	char* s;
	Symbol* fname = 0;
	Object* ob = nil;
	char* sarg[20]; // up to 20 arguments may be strings
	int ns = 0; // number of args that are strings
	int narg = 0; // total number of args

	if (style == 3) { // python callable
		nrnmpi_int_broadcast(&npickle, 1, 0);
		s = new char[npickle];
		nrnmpi_char_broadcast(s, npickle, 0);
	}else if (style == 1) { // hoc function
		int size;
		nrnmpi_int_broadcast(&size, 1, 0); // includes terminator
//printf("%d subworld hoc function string size = %d\n", nrnmpi_myid_world, size);
		s = new char(size);
		nrnmpi_char_broadcast(s, size, 0);
		fname = hoc_lookup(s);
		if (!fname) { return; } // error raised by sender
	}else{
		return; // no others implemented, error raised by sender
	}

	// now get the args
	int argtypes;
	nrnmpi_int_broadcast(&argtypes, 1, 0);
//printf("%d subworld argtypes = %d\n", nrnmpi_myid_world, argtypes);
	for (j = argtypes; (i = j%5) != 0; j /= 5) {
		++narg;
		if (i == 1) { // double
			double x;
			nrnmpi_dbl_broadcast(&x, 1, 0);
//printf("%d subworld scalar = %g\n", nrnmpi_myid_world, x);
			hoc_pushx(x);
		}else if (i == 2) { // string
			int size;
			nrnmpi_int_broadcast(&size, 1, 0);
			sarg[ns] = new char(size);
			nrnmpi_char_broadcast(sarg[ns], size, 0);
			hoc_pushstr(sarg+ns);
			ns++;
		}else if (i == 3) { // Vector
			int n;
			nrnmpi_int_broadcast(&n, 1, 0);
			Vect* vec = new Vect(n);
			nrnmpi_dbl_broadcast(vec->vec(), n, 0);
			hoc_pushobj(vec->temp_objvar());
		}else{ // PythonObject
			int n;
			nrnmpi_int_broadcast(&n, 1, 0);
			char* s;
			s = new char[n];
			nrnmpi_char_broadcast(s, n, 0);
			Object* po = nrnpy_pickle2po(s, size_t(n));
			delete [] s;
			hoc_pushobj(hoc_temp_objptr(po));
		}
	}

	if (style == 3) {
		size_t size;
		char* rs = (*nrnpy_callpicklef)(s, size_t(npickle), narg, &size);
		assert(rs);
		delete [] rs;
	}else{
//printf("%d subworld hoc call %s narg=%d\n", nrnmpi_myid_world, fname->name, narg);
		hoc_call_objfunc(fname, narg, ob);
//printf("%d subworld return from hoc call %s\n", nrnmpi_myid_world, fname->name);
	}
	delete [] s;
	for (i=0; i < ns; ++i) {
		delete [] sarg[i];
	}
}


