winix/core/basethread.h

159 lines
4.3 KiB
C++

/*
* This file is a part of Winix
* and is distributed under the 2-Clause BSD licence.
* Author: Tomasz Sowa <t.sowa@ttmath.org>
*/
/*
* Copyright (c) 2010-2014, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef headerfile_winix_core_basethread
#define headerfile_winix_core_basethread
#include <pthread.h>
#include "synchro.h"
namespace Winix
{
class BaseThread
{
public:
BaseThread();
// synchro object (must be set)
void SetSynchro(Synchro * psynchro);
// work mode
// we have two modes:
// 0 - there is a loop with SignalReceived() and Do()
// if SignalReceived() returns true then Do() is called
// 1 - only Work() method is called
// the thread exits after Work() has finished
// default: 0
void Mode(int mode);
// starting the second thread
bool StartThread();
// virtual methods which should/can be inherited by your class
// the methods will be called from the other thread
// wake up the second thread
// (if it waits for the signal)
// you should use it with: synchro->Lock() and Unlock()
// if the thread doesn't wait on a signal then nothing is done
virtual void WakeUpThread();
// waiting until the thread exits
// you should call WakeUpThread() before
virtual void WaitForThread();
// initialize the thread
// (global objects are locked)
// if it returns false then the thread immediately exits
// default: true
virtual bool Init() { return true; }
// uninitialize the thread
// this is called before the thread is prepare to detach
// (global objects are locked)
// it's called only if Init() returned true
virtual void Uninit() {}
// returns the thread id
// this identifier is set by StartThread() metdhod
pthread_t ThreadId();
protected:
// signal came (work mode = 0 - default)
// signal comes when an other thread calls WakeUpThread() method
// check specific job and return true to call Do() next
// (global objects are locked -- copy some global objects to local variables)
virtual bool SignalReceived() { return false; };
// if SignalReceived() returned true then this method is called
// global objects are *not* locked -- use only your local variables
// if you have to do something on global objects use synchro->Lock() and synchro->Unlock()
virtual void Do() {}
// this method is called after Init() when Mode(1) is used
// this is for long-time job
// this method is called only once
// global objects are *not* locked
virtual void Work() {}
protected:
Synchro * synchro;
pthread_t thread_id; // thread id - set by StartThread()
pthread_cond_t thread_signal;
int work_mode;
bool wake_up_was_called;
void SignalLoop();
static void * StartRoutine(void *);
bool BaseInit();
void BaseUninit();
bool BaseSignalReceived();
void BaseDo();
bool WaitForSignal();
bool WaitForSignalSleep(time_t second);
bool Lock();
void Unlock();
// if the work done by Do() is long time consuming you should periodically check
// wheter there was a signal for exiting, and if it was just simply return from Do()
// (it's checking with locking and unlocking)
bool IsExitSignal();
};
} // namespace Winix
#endif