Chief Delphi

Chief Delphi (http://www.chiefdelphi.com/forums/index.php)
-   C/C++ (http://www.chiefdelphi.com/forums/forumdisplay.php?f=183)
-   -   Threading (http://www.chiefdelphi.com/forums/showthread.php?t=72371)

nickmagus 18-01-2009 19:04

Threading
 
While I am familiar with threading and have used it many times I have never done so in C++. Can anyone refer me to a good threading tutorial?

Jared Russell 18-01-2009 19:10

Re: Threading
 
For what environment? Threads are a system-dependent feature and can be implemented at various levels of the system.

POSIX is a pretty commonly used threading library on Linux-based systems; you basically call a "create thread" function and pass it a function pointer for whatever code it is that you want to run asynchronously. Primitives like mutexes and semaphores are included.

This is a good overview of POSIX threading.

nickmagus 18-01-2009 19:38

Re: Threading
 
for the cRio.

dpeterson3 18-01-2009 19:39

Re: Threading
 
Here is another old thread dedicated to it. http://www.chiefdelphi.com/forums/sh...ad.php?t=71138
On the CRIO, they are called tasks. I am not sure how to use them yet myself. That part of the WPI manual is blanked out. Look at the tasks.h file in the WPILib folder. It helps a little. Also look at the camera examples in WindRiver. I believe they are using seperate tasks for image aquisition.

hope this helps a little

nickmagus 19-01-2009 00:32

Re: Threading
 
Does anybody have any sample code of a thread (task) that they have got working. At the moment it appears that the task is being deleted.

Shinigami2057 19-01-2009 08:15

Re: Threading
 
Hi nickmagus,

I'd recommend you use the WPILib Task class, which is a simple wrapper over the VxWorks task/thread API. Here's some sample code to get you started:

To define a task, you have to give it a name. The task will show up in debugging as FRC_task_name, where task_name is the value passed to the Task constructor. The second argument to the constructor is a FUNCPTR, which is your threading function.
Code:

MyRobot::RobotInit()
{
    Task myTask("image_process", imageProcessThread);

    myTask.Start();
}

The thread function must return an int and take a variable number of arguments (up to 10), which is denoted in C/C++ by "..." as the last function argument.

Your task will run from start to finish once, after Start is called. If you don't want it to be deleted, then put a loop in it so it doesn't return until you're done:
Code:

int imageProcessThread(...)
{
  va_arg argptr;
  // do stuff...
}

To get access to any of your 10 arguments, you must use the va_arg macros, which are explained here:
http://www.cppreference.com/wiki/c/other/va_arg

If you are using shared data between threads, you must be sure to enforce synchronization between the threads. WPILib has an interesting abstraction for synchronization with semaphores - examples are in the C++ Programming Guide - but it's really more confusing in my opinion. PM me if you need help with synchronization.

nickmagus 19-01-2009 14:18

Re: Threading
 
Thanks for your help Shinigami. Here's what I have found. If you start a task in an init function it is deleted when the init function ends. It appears the task thinks its a local object but when I try to put the definition as a global I get an error "error: expected `,' or `...' before string constant". Does anybody know how to make it global (I will experiment and post the answer if I figure it out.)

Chief Pride 01-02-2009 15:47

Re: Threading
 
I'm having difficulty getting the small code sample to compile, Shinigami. Hopefully, you or someone else could lend a hand?

Here is what I currently have:
Code:

#include "WPILib.h"

/** TODO: Change this message.
 * This is a demo program showing the use of the RobotBase class.
 * The SimpleRobot class is the base of a robot application that will automatically call your
 * Autonomous and OperatorControl methods at the right time as controlled by the switches on
 * the driver station or the field controls.
 */
class Robot : public SimpleRobot
{
        RobotDrive myRobot;        // robot drive system
        Task CameraThread;
       

public:
        Robot(void):                // these must be initialized in the same order
                myRobot(1, 2),        // as they are declared above.
                CameraThread("camera_thread", imageProcessThread())
        {
                GetWatchdog().SetExpiration(0.1);
        }

        /**
        * Drive left & right motors for 2 seconds then stop
        */
        void Autonomous(void)
        {
                GetWatchdog().SetEnabled(false);
                myRobot.Drive(0.5, 0.0);        // drive forwards half speed
                Wait(2.0);                                        // for 2 seconds
                myRobot.Drive(0.0, 0.0);        // stop robot
        }

        void OperatorControl(void)
        {
                GetWatchdog().SetEnabled(true);
                while (IsOperatorControl())
                {
                        GetWatchdog().Feed();        //woof.
                }
        }
       
        int imageProcessThread(...)
        {
          // do stuff...
                return 1;
        }
};

START_ROBOT_CLASS(SimpleRobot);

Thanks.

Shinigami2057 01-02-2009 17:58

Re: Threading
 
Chief Pride,

I can see two small problems with your code, both of which are very easy to fix. The first:

Quote:

Originally Posted by Chief Pride (Post 812310)
Code:

                CameraThread("camera_thread", imageProcessThread())

When you pass a function as an argument, you don't use parenthesis after the thread - parenthesis indicate a function call, not the function itself. So it should be just
Code:

CameraThread("camera_thread", imageProcessThread)
Secondly, your task function (imageProcessThread) must be declared outside any class definition. So move it after the class ends and before START_ROBOT_CLASS.
You may also have to put a "prototype" of your function before your class definition to make the compiler happy, like so:

Code:

int imageProcessThread(...); /* prototype */

class Robot : public SimpleRobot {
  // ...
};

int imageProcessThread(...)
{
  return 1;
}

START_ROBOT_CLASS(SimpleRobot);

Good luck and let me know if you have any more trouble. :)

Chief Pride 01-02-2009 21:32

Re: Threading
 
Thank you very much, Shinigami. :)

Although, if you have a minute, would you mind letting me know why the prototype makes the compiler happy?

Thanks.

intellec7 02-02-2009 18:04

Re: Threading
 
The compiler compiles the source code from top to bottom, so if you have a source file like :

Code:

test_function();

void test_function(void)
{ //do stuff
}

it is best to prototype "test_function" before you call it. This lets the compiler know that there is a definition of the function. Some compilers might not compile the source code without the prototypes, others might throw a "implicit reference" warning.

Tom Bottiglieri 02-02-2009 19:23

Re: Threading
 
There is a good example of how to utilize tasks in WPILib source. Check out StartCameraTask in the AxisCam.cpp file.

byteit101 05-02-2009 14:41

Re: Threading
 
here is a brief overview:
Code:

#include...
Task tsk("myTask",MyTask);//creates task "tsk" identified by the name "myTask" on the cRIO, calling function MyTask
//put variables to be accesed by the task and norm. code here
RobotDrive myRobot(1,2);
class ...
...
void Auto()
{
    while (!tsk.IsReady())
    { }
    tsk.Start(1);//start MyFunction on another thread w/ args (1);
    while (IsAuto())
    {
    }
    tsk.Stop();
}
...
...
};//end of class
void MyFunction (int arg1)
{
//code using arg1
}

You can have up to 10 int args, and the function must be global


All times are GMT -5. The time now is 02:38.

Powered by vBulletin® Version 3.6.4
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.
Copyright © Chief Delphi