# BasicPthread reference

Building a new Triead is a serious business, containing many moving part. Doing it every time from scratch would be hugely annoying and error prone. The class BasicPthread, defined in

    app/BasicPthread.h

, takes care of wrapping all that complicated logic.

It originated as a subclass of pw::pwthread, and even though it ended up easier to copy and modify the code (okay, maybe this means that pwthread can be made more flexible), the usage is still very similar to it. You define a new subclass of BasicPthread, and define the virtual function

    execute()

in it. Then you instantiate the object and call the method

    start()

with the App argument.

For a very simple example:

    class MainLoopPthread : public BasicPthread
    {
    public:
    	MainLoopPthread(const string &name):
    		BasicPthread(name)
    	{ }

    	// overrides BasicPthread::execute
    	virtual void execute(TrieadOwner *to)
    	{
    		to->readyReady();
    		to->mainLoop();
    	}
    };

    ...

    Autoref pt3 = new MainLoopPthread("t3");
    pt3->start(myapp);

It will properly create the Triead, TrieadOwner, register the thread joiner and start the execution. The TrieadOwner will pass through to the

    execute()

method, and its field

    fi_

will contain the reference to the FileInterrupt object. After

    execute()

returns, it will take care of marking the thread as dead.

It also wraps the call of

    execute()

into a try/catch block, so any Exceptions thrown will be caught and cause the App to abort. In short, it's very similar to the Triead management in Perl.

You don't need to keep the reference to the thread object afterwards, you can even do the construction and start in one go:

    (new MainLoopPthread("t3"))->start(myapp);

The internals of BasicPthread will make sure that the object will be dereferenced (and thus, in the absence of other references, destroyed) after the thread gets joined by the harvester.

Of course, if you need to pass more arguments to the thread, you can define them as fields in your subclass, set them in the constructor (or by other means between constructing the object and calling

    start()

), and then

    execute()

can access them. Remember,

    execute()

is a method, so it receives not only the TrieadObject as an argument but also the BasicPthread object as

    this

.

BasicPthread is implemented as a subclass of TrieadJoin, and thus is an Mtarget. It provides the concrete implementation of the joiner's virtual methods,

    join()

and

    interrupt()

.

    Interrupt()

calls the method of the base class, then sends the signal

    SIGUSR2

to the target thread.

And finally the actual reference:

    BasicPthread(const string &name);

Constructor. The name of the thread is passed through to

    App::makeTriead()

. The Triead will be constructed in

    start()

, the BasicPthread constructor just collects together the arguments.

    void start(Autoref app);

Construct the Triead, create the POSIX thread, and start the execution there.

    void start(Autoref to);

Similar to the other version of

    start()

but uses a pre-constructed TrieadOwner object. This version is useful mostly for the tests, and should not be used much in the real life.

    virtual void execute(TrieadOwner *to);

Method that must be redefined by the subclass, containing the threads's logic.

    virtual void join();
    virtual void interrupt();

Methods inherited from TrieadJoin, providing the proper implementations for the POSIX threads.

BasicPthread