-
Notifications
You must be signed in to change notification settings - Fork 0
Tutorial
#Motivation This tutorial will walk you through some of the basics of building an application using libSPRITE.
libSPRITE provides for scheduling and deterministic data routing for multi-tasking applications on POSIX compliant operating systems. It also allows you to configure and control applications using the Lua scripting language.
libSPRITE hides some of the complexity of building multi-threaded applications and attempts to reduce the errors and indeterminism associated with concurrent programming. Especially when running on multi-core machines.
#Prereqisites
- A C++ compiler
- CMake
- Lua development tools
- Download and install libSPRITE.
#Hello World!
A good first step is to build a simple, straight forward application that prints "Hello World!"
Create a file called sprite_main.cpp
. For this first step, we are not going to use the SCALE Lua interface. We will stick with straight C/C++.
Start by creating a directory called task
. This is where we will put source code for SRTX tasks. The write the following two source files.
Hello.hpp
#ifndef task_Hello_hpp
#define task_Hello_hpp
#include "SRTX/Task.h"
namespace task {
class Hello : public SRTX::Task {
public:
/**
* Constructor.
* @param name Task name.
*/
Hello(const char *const name);
/**
* Initialization routine.
* @return true on success or false on failure.
*/
bool init();
/**
* This the the function that gets executed on a periodic basis
* each time this task is scheduler to run.
* @return Return true to continue execution or false to terminate
* the task.
*/
bool execute();
/**
* Terminate routine.
*/
void terminate();
};
} // namespace
#endif // task_Hello_hpp
and Hello.cpp
#include "task/Hello.hpp"
#include "base/XPRINTF.h"
namespace task {
Hello::Hello(const char *const name)
: SRTX::Task(name)
{
}
bool Hello::init()
{
return true;
}
bool Hello::execute()
{
IPRINTF("Hello World\n");
return true;
}
void Hello::terminate()
{
}
} // namespace
In the top level directory, create the file sprite_main.cpp
#include <SRTX/Scheduler.h>
#include <base/XPRINTF.h>
#include <signal.h>
#include "task/Hello.hpp"
static volatile bool done(false);
static void kill_me_now(int)
{
done = true;
}
static units::Nanoseconds HZ_to_period(unsigned int hz)
{
return units::Nanoseconds(1*units::SEC / hz);
}
int main(void)
{
/* Set up the signal handler for control-C.
*/
signal(SIGINT, kill_me_now);
/* Declare the task properties.
*/
SRTX::Task_properties tp;
SRTX::priority_t priority = SRTX::MAX_PRIO;
/* Create the scheduler
*/
tp.prio = priority;
tp.period = HZ_to_period(1);
SRTX::Scheduler &s = SRTX::Scheduler::get_instance();
s.set_properties(tp);
/* Create the "Hello World!" task
*/
--tp.prio;
task::Hello hello("Hello");
hello.set_properties(tp);
s.start();
hello.start();
while(!done)
{
;
}
hello.stop();
s.stop();
return 0;
}
Then add a CMakeLists.txt file at the top level to build the project.
cmake_minimum_required(VERSION 2.8)
# I like to have the warning level set high.
add_definitions("-Wall -Wextra -Wparentheses -Wuninitialized -Wcomment -Wformat -Weffc++")
# Add the source tree directory to the search path for include files.
# Add the path to the libSPRITE header files.
include_directories(${CMAKE_CURRENT_SOURCE_DIR} "/usr/local/include/SPRITE")
# Set libSPRITE in the libraries path.
link_directories(/usr/local/lib/SPRITE)
# Add the executable and it's source.
add_executable(sprite_main sprite_main.cpp
task/Hello.cpp)
# Specify libraries to link.
target_link_libraries(sprite_main SPRITE_SRTX pthread)
To build the executable, create a directory called build
and cd
into that directory. Execute cmake ..
to generate the Makefiles. Then enter make
to create an executable called sprite_main
.
You must have root privledges to run the executable. This is required because tasks are set to real-time priorities. If you are not root, you will get a warning to run using sudo
.
So what happens here. Well, we've created an executable that has one task called Hello
. There is also a scheduler task running in the system and the Hello
task is registered with the scheduler. Both the scheduler and the Hello
task are set to run at 1 Hz with the scheduler running at the highest priority in the system and the Hello
task running a the highest priority minus 1 --tp.prio
.
The scheduler and Hello
tasks are both started and continue to run until control-C
is entered, at which point the Hello
task and the scheduler are stopped and the program exits.
So what's up with the IPRINTF("Hello World!\n")
? The definition comes from the base/XPRINTF.h
file in libSPRITE/base. It is a macro that can be turned on and off. IPRINTF
stands for "information print". The base/XPRINTF.h
header also contains macros for DPRINTF
(debug), WPRINTF
(warning), and EPRINTF
(error).
By adding the line set_property(SOURCE task/Hello.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -DNO_PRINT_INFO")
to CMakeLists.txt
, you can turn off the print statement. This can be quite useful in controlling the level of verbosity on a file by file or system wide basis. Just use -DPRINT_DEBUG
, -DNO_PRINT_WARNING
, and -DNO_PRINT_ERROR
to change the default behavior of DPRINTF
, WPRINTF
, and EPRINTF
macros respectively. Note that the default behavior of DPRINTF
is to not print.