www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Starting threads inside class

reply Josh <moonburntm gmail.com> writes:
My goal with the code below is to eventually have my main 
communicate with Foo and Bar classes listening for packets on a 
different address/port, each in a separate thread. They would 
then communicate with Foobaz and Barbaz threads respectively to 
do other work. In trying to get just Foo working though, I'm 
getting this error:

Error: template std.concurrency.spawn cannot deduce function from 
argument types !()(void delegate(Tid ownerTid), Tid), candidates 
are:
D:\D\dmd2\windows\bin\..\..\src\phobos\std\concurrency.d(466):    
     std.concurrency.spawn(F, T...)(F fn, T args) if 
(isSpawnable!(F, T))

The code works fine if I call daemon as a normal function, but it 
holds up the main thread.

Is there anything I'm doing wrong here? I'm not accessing 
anything outside this class from inside, and the most I would be 
doing from outside is accessing the Tid in order to send packets 
from my main.

class Foo
{
	private string address = "127.0.0.1";
	private ushort port = 55555;
	private ubyte[256] buffer;
	private TcpSocket mysock;
	Tid listenerd;
	
	this()
	{
		listenerd = spawn(&daemon, thisTid);
	}
	
	void setup()
	{
		mysock = new TcpSocket();
		mysock.blocking = true;
		try
		{
			mysock.connect(new InternetAddress(address, port));
		}
		catch (SocketOSException e)
		{
		}
	}
	
	void initialise()
	{
		// send init packet
	}
	
	void closeConnection()
	{
		// send close packet
	}
	
	void packetHandler()
	{
		// do something with buffer
	}
	
	void daemon(Tid ownerTid)
	{
		setup();
		initialise();
		int rxSize = -1;
		while (true)
		{
			rxSize = mysock.receive(buffer);
			if (rxSize == 0)
			{
				break;
			}
			packetHandler();
		}
		closeConnection();
	}
}
Feb 23 2016
parent =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 02/23/2016 07:31 AM, Josh wrote:
 My goal with the code below is to eventually have my main communicate
 with Foo and Bar classes listening for packets on a different
 address/port, each in a separate thread.
The main issue is that in D all data is thread-local by-default. main() cannot create objects and then implicitly give access to those objects from other threads.
 the most I would be doing from outside is accessing the Tid in order
 to send packets from my main.
Even that's not needed because spawn() returns the Tid. And you don't need to pass ownerTid, it is already available to child threads. Options: a) spawn() a thread by passing necessary data for it to create a Foo. (Preferred.) b) In case main() needs to have access to the objects, construct objects as shared(Foo) and pass references to threads. Here is the code with option a: import std.socket; import std.concurrency; void daemon() { auto f = new Foo(); f.setup(); f.initialise(); long rxSize = -1; while (true) { rxSize = f.mysock.receive(f.buffer); if (rxSize == 0) { break; } f.packetHandler(); } f.closeConnection(); } class Foo { private string address = "127.0.0.1"; private ushort port = 55555; private ubyte[256] buffer; private TcpSocket mysock; Tid listenerd; void setup() { mysock = new TcpSocket(); mysock.blocking = true; try { mysock.connect(new InternetAddress(address, port)); } catch (SocketOSException e) { } } void initialise() { // send init packet } void closeConnection() { // send close packet } void packetHandler() { // do something with buffer } } void main() { auto listenerd = spawn(&daemon); } Ali
Feb 23 2016