Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

taskSpawn() problem

291 views
Skip to first unread message

Morné Hartman

unread,
Oct 21, 1999, 3:00:00 AM10/21/99
to
Hi all,

I am using Tornado2 and I am experiencing problems when trying to
spawn a task. I have a method in a class that spawns a task. The task
is a method of another class. The task sits in a forever loop waiting
to read data from a TCP socket. The task is part of my server class,
because the rest of the class takes care of creation, binding,
connection, transmitting and closure of the socket.

my code looks like this:
TMyServer * MyServer = new TMyServer();
gnServerReceiveID = taskSpawn("tSerRec", 10, 0, 10000,
(FUNCPTR)MyServer->ReceiveData, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0);

After that I tried using a standard function in the taskspawn command
and then from that function call the method. That code looks like
this:


gnServerReceiveID = taskSpawn("tSerRec", 10, 0, 10000,
(FUNCPTR)RxData, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0);

STATUS RxData()
{
TMyServer * MyServer = new TMyServer();
MyServer->ReceiveData();
}

both these efforts did not work. I greatly appreciate any help that
anyone can provide.

Yours Sincerely
Morné Hartman
mhar...@grintek.com


Ron Dempster

unread,
Oct 21, 1999, 3:00:00 AM10/21/99
to
The first one definitely will not work. You can however pass a static method as the task
function. How does the second code fail? I have done the following:

class TMyServer
{
public:
TMyServer();
static int TaskProc(int);
}

TMyServer *MyServer = new TMyServer();
gnServerReceiveID=taskSpawn("tSerRec",10,0,10000,(FUNCPTR)TMyServer::TaskProc,(int)MyServer,
0,0,0,0,0,0,0,0,0);

static int TaskProc(int myserver)
{
TMyServer* MyServer = (TMyServer*)myserver;
MyServer->ReceiveData();
}


Hope this helps,
Ron

Morné Hartman

unread,
Oct 21, 1999, 3:00:00 AM10/21/99
to
Hi, there Ron Dempster.

Thanks for your mail. In the interm, I came up with a solution that is
very similar to yours. I place the taskspawn() function in the
constructor of a class, TaskClass. The actual task is a method of this
class. I define TaskClass to be static and a friend to MyServer class.
The task is then spawned whenever an object of TaskClass is
initialised.

Thanks for your help.

Have you got any ideas on priority and events. The aforemensioned task
is a receiveData function for a TCP application. At the moment I have
it in a FOREVER loop, polling the socket to a response from the remote
system. I would prefer to have an asynchronous event notify me of Data
that is being received. Any further help would be greatly appreciated.

Yours Sincerely
Morné Hartman

Ron Dempster <NO-SP...@NO-SPAM-home.com> wrote in message
news:380f0c1d.601863604@news...

engineer_scotty

unread,
Oct 21, 1999, 3:00:00 AM10/21/99
to
Morné Hartman wrote:
>
> Hi all,
>
> I am using Tornado2 and I am experiencing problems when trying to
> spawn a task. I have a method in a class that spawns a task. The task
> is a method of another class. The task sits in a forever loop waiting
> to read data from a TCP socket. The task is part of my server class,
> because the rest of the class takes care of creation, binding,
> connection, transmitting and closure of the socket.
>
> my code looks like this:
> TMyServer * MyServer = new TMyServer();
> gnServerReceiveID = taskSpawn("tSerRec", 10, 0, 10000,
> (FUNCPTR)MyServer->ReceiveData, 0, 0,
> 0, 0, 0, 0, 0, 0, 0, 0);

I'm assuming that MyServer->ReceiveData is a nonstatic member
function (ie has a this pointer); in which case the above won't
work. At all.


>
> After that I tried using a standard function in the taskspawn command
> and then from that function call the method. That code looks like
> this:
>
> gnServerReceiveID = taskSpawn("tSerRec", 10, 0, 10000,
> (FUNCPTR)RxData, 0, 0,
> 0, 0, 0, 0, 0, 0, 0, 0);
>
> STATUS RxData()
> {
> TMyServer * MyServer = new TMyServer();
> MyServer->ReceiveData();
> }

Not sure why this doesn't work, other than the calling task doesn't have
a pointer to MyServer around...which might be the problem. Also, the
call to operator new() occurs in the created task's context--which might
be a problem.

Try this:

static void myServerThreadFunc (TMyServer *myServer);

TMyServer * MyServer = new TMyServer();
gnServerReceiveID = taskSpawn("tSerRec", 10, 0, 10000,

(FUNCPTR)myServerThreadFunc, myServer, 0,


0, 0, 0, 0, 0, 0, 0, 0);

static voic myServerThreadFunc (TMyServer *myServer) {
myServer->ReceiveData();
};


In other words, pass a pointer to the object as an argument of the
task; and have a static function (no this pointer) to invoke the
correct member function.



> both these efforts did not work. I greatly appreciate any help that
> anyone can provide.
>
> Yours Sincerely
> Morné Hartman
> mhar...@grintek.com

--
------------------------------------------------------------------------
engineer_scotty (no, not that one) -- consumer of fine ales and lagers
some days you're the fire hydrant, some days you're the dog | go blazers
no small furry creatures were harmed in the creation of this .signature
------------------------------------------------------------------------

engineer_scotty

unread,
Oct 21, 1999, 3:00:00 AM10/21/99
to
Morné Hartman wrote:
>
> Hi, there Ron Dempster.
>
> Thanks for your mail. In the interm, I came up with a solution that is
> very similar to yours. I place the taskspawn() function in the
> constructor of a class, TaskClass. The actual task is a method of this
> class. I define TaskClass to be static and a friend to MyServer class.
> The task is then spawned whenever an object of TaskClass is
> initialised.

Unless you know FOR SURE that the class will NEVER be derived from, do
NOT
spawn tasks in a class's constructor. Otherwise, the following will
happen:

1) Someone derives from your class, and overrides a method called from
your thread function.

2) An object of the class is instantiated.

3) The thread is spawned in the base class constructor.

4) The thread tries to invoke a member function in the class...and
the program crashes. If you are lucky.

What is happening?

When an object is constructed, the base class constructor(s) runs before
the derived class constructor(s)--in other words, the object is not
completely constructed before the task is spawned. Depending on how
vxWorks (or any OS; this is not a vxWorks problem) schedules things,
the task you have spawned may be operating on junk. If you are lucky,
it will do something that causes an immediate crash; if you are not
lucky you will have a wild pointer that does strange and unpredictable
things to your code, resulting in random crashes elsewhere.

The proper thing to do is declare a virtual run() function that spawns
the task; and run this after the constructor returns. You have to
explicitly do this; there is no safe way to automatically execute a
method and ensure that it does not happen until all derived constructors
have run.

> Thanks for your help.
>
> Have you got any ideas on priority and events. The aforemensioned task
> is a receiveData function for a TCP application. At the moment I have
> it in a FOREVER loop, polling the socket to a response from the remote
> system. I would prefer to have an asynchronous event notify me of Data
> that is being received. Any further help would be greatly appreciated.

Reading from a socket, in most cases, should block if there is no data
(did you for some reason open the socket with O_NONBLOCK or O_NDELAY
set???). If you want a timeout, you can use select().


> Yours Sincerely
> Morné Hartman
>
> Ron Dempster <NO-SP...@NO-SPAM-home.com> wrote in message
> news:380f0c1d.601863604@news...
> > The first one definitely will not work. You can however pass a
> static method as the task
> > function. How does the second code fail? I have done the
> following:
> >
> > class TMyServer
> > {
> > public:
> > TMyServer();
> > static int TaskProc(int);
> > }
> >
> > TMyServer *MyServer = new TMyServer();
> >
> gnServerReceiveID=taskSpawn("tSerRec",10,0,10000,(FUNCPTR)TMyServer::T
> askProc,(int)MyServer,
> > 0,0,0,0,0,0,0,0,0);
> >
> > static int TaskProc(int myserver)
> > {
> > TMyServer* MyServer = (TMyServer*)myserver;
> > MyServer->ReceiveData();
> > }
> >
> >
> > Hope this helps,
> > Ron
> >
> > On Thu, 21 Oct 1999 10:54:06 +0200, =?iso-8859-1?Q?Morn=E9_Hartman?=

> <mhar...@grintek.com> wrote:
> >
> > >Hi all,
> > >
> > >I am using Tornado2 and I am experiencing problems when trying to
> > >spawn a task. I have a method in a class that spawns a task. The
> task
> > >is a method of another class. The task sits in a forever loop
> waiting
> > >to read data from a TCP socket. The task is part of my server
> class,
> > >because the rest of the class takes care of creation, binding,
> > >connection, transmitting and closure of the socket.
> > >
> > >my code looks like this:
> > >TMyServer * MyServer = new TMyServer();
> > > gnServerReceiveID = taskSpawn("tSerRec", 10, 0, 10000,
> > > (FUNCPTR)MyServer->ReceiveData, 0, 0,
> > > 0, 0, 0, 0, 0, 0, 0, 0);
> > >

> > >After that I tried using a standard function in the taskspawn
> command
> > >and then from that function call the method. That code looks like
> > >this:
> > >
> > >
> > >gnServerReceiveID = taskSpawn("tSerRec", 10, 0, 10000,
> > > (FUNCPTR)RxData, 0, 0,
> > > 0, 0, 0, 0, 0, 0, 0, 0);
> > >
> > >STATUS RxData()
> > >{
> > > TMyServer * MyServer = new TMyServer();
> > > MyServer->ReceiveData();
> > >}
> > >

0 new messages