My favorites | Sign in
Project Home Downloads Wiki Issues Source
READ-ONLY: This project has been archived. For more information see this post.
Search
for
ArchitecturalOverview  
Overview of the code architecture
Updated Jun 24, 2008 by keyvan.e...@gmail.com

Introduction

The goal of the underlying System code is to make the lives of the application developers easy. Since the project is going to include multiple threads in the first implementation, and should be expandable to use more than one camera and infrared transceiver (or other command dispatchers), the overall system should have the ability to expand and contract with little to no effort.

Since the operating environment is Linux, use of the POSIX threads (pthreads) library is necessary to achieve parallel processing. The level of abstraction in pthreads is low and there are many things it can do that are completely irrelevant for our uses. In an effort to achieve easy and rapid development, the Thread class was created.

Thread class

The Thread class can be used by developers to easily create new threads in the system and abstract all of the necessary atomic and blocking operations of thread synchronization.

The class declaration is as follows:

class Thread
{
  public:
        Thread();
        virtual ~Thread();

        virtual void Thread_main() = 0;
        virtual unsigned Get_startup_priority() const = 0;

        void Delay( unsigned milliseconds );

        unsigned Get_id() const;
        void Set_id( unsigned const & id );

  private:
        unsigned                m_thread_id;
};

To create a thread, an application developer must inherit the Thread class and implement Thread_main and Get_startup_priority, and then simply create an instance of the class to run it. For example, the following code will create a thread and continually print "Hello World!" to the console every two seconds:

#include "thread.hpp"

#include <stdio.h>

class Hello_world : public System::Thread
{
  public:
    void Thread_main()
    {
        while( true ) {
            fprintf( stdout, "Hello World!\n" );
            Delay( 2000 );
        }
    }

    unsigned Get_startup_priority()
    {
        return 0;
    }
  private:
    static Hello_world g_instance;
};

Hello_world Hello_world::g_instance;

Public APIs

It is desirable to only publish useful and public APIs for each module in the project. These public APIs shall be placed in header files (.hpp) in the root include directory with the same name as the module folder. The APIs will typically be procedural and use their own namespace.

Each module may include private data which is hidden from other modules in its module folder. Typically, there will be an internal.hpp file in each module folder which will contain the thread classes and any internal data structures and functions. This separation of information allows for maximum flexability when implementing different modules.

For example, suppose a thread is desired whose purpose is to print "Hello World!" to the console on command. The following file layout should be used:


include/helloworld.hpp

#ifndef _HELLOWORLD_HPP_INCLUDED_
#define _HELLOWORLD_HPP_INCLUDED_

#include "types.hpp"

namespace Hello_world {

Status Print_hello_world_now();

} // namespace Hello_world

#endif // _HELLOWORLD_HPP_INCLUDED_

helloworld/internal.hpp

#ifndef _INTERNAL_HPP_INCLUDED_
#define _INTERNAL_HPP_INCLUDED_

#include "thread.hpp"

namespace Hello_world {

class Hello_world_thread : public System::Thread
{
  public:
    enum {
        MSG_HELLO_WORLD_PRINT_NOW      = 0,
    };

    void Thread_main();

    unsigned Get_startup_priority()
    {
        return 0;
    }

    static Hello_world_thread * Get_instance()
    {
        return &g_instance;
    }
  private:
    static Hello_world_thread g_instance;
};

} // namespace Hello_world

#endif // _INTERNAL_HPP_INCLUDED_

helloworld/helloworld.cpp

#include "helloworld.hpp"
#include "internal.hpp"
#include "system.hpp"

using namespace System;

namespace Hello_world {

// static
Hello_world_thread Hello_world_thread::g_instance;

Status Print_hello_world_now()
{
    Status status = STATUS_OK;

    Send_message( Hello_world_thread::Get_instance()->Get_id(),
                  Hello_world_thread::MSG_HELLO_WORLD_PRINT_NOW,
                  &status );

    return status;
}

} // namespace Hello_world

helloworld/helloworldthread.cpp

#include "internal.hpp"
#include "types.hpp"
#include "system.hpp"

#include <stdio.h>

using namespace System;

void Hello_world_thread::Thread_main()
{
    Status   status = STATUS_OK;
    Message  msg;
    unsigned sender;
    void *   data;

    while( true ) {
        status = Recv_message( sender, msg, data );

        if( status == STATUS_OK && msg == MSG_HELLO_WORLD_PRINT_NOW ) {
            Status * ret_status = reinterpret_cast< Status * >( data );
            
            fprintf( stdout, "Hello World!\n" );
            
            *ret_status = STATUS_OK;
        }
        Reply( sender );
    }
}

MORE TO COME

References

  1. POSIX threads tutorial http://www.yolinux.com/TUTORIALS/LinuxTutorialPosixThreads.html
Powered by Google Project Hosting