zoneminder/src/zm_thread.h

278 lines
5.2 KiB
C
Raw Normal View History

//
// ZoneMinder Thread Class Interface, $Date$, $Revision$
// Copyright (C) 2001-2008 Philip Coombes
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//
#ifndef ZM_THREAD_H
#define ZM_THREAD_H
#include <unistd.h>
#include <pthread.h>
2013-04-30 01:44:21 +08:00
#include <unistd.h>
2013-09-25 12:11:59 +08:00
#ifdef HAVE_SYS_SYSCALL_H
#include <sys/syscall.h>
#endif // HAVE_SYS_SYSCALL_H
#include "zm_exception.h"
#include "zm_utils.h"
2015-02-24 22:22:08 +08:00
#ifdef __FreeBSD__
#include <sys/thr.h>
#endif
class ThreadException : public Exception
{
2015-02-24 22:22:08 +08:00
private:
#ifndef SOLARIS
pid_t pid() {
pid_t tid;
2015-02-24 22:22:08 +08:00
#ifdef __FreeBSD__
long lwpid;
thr_self(&lwpid);
tid = lwpid;
2015-02-24 22:22:08 +08:00
#else
#ifdef __FreeBSD_kernel__
if ( (syscall(SYS_thr_self, &tid)) < 0 ) // Thread/Process id
# else
tid=syscall(SYS_gettid);
#endif
2015-02-24 22:22:08 +08:00
#endif
return tid;
}
#else
pthread_t pid() { return( pthread_self() ); }
#endif
public:
ThreadException( const std::string &message ) : Exception( stringtf( "(%d) "+message, (long int)pid() ) ) {
}
};
class Mutex
{
friend class Condition;
private:
pthread_mutex_t mMutex;
public:
Mutex();
~Mutex();
private:
pthread_mutex_t *getMutex()
{
return( &mMutex );
}
public:
void lock();
void lock( int secs );
void lock( double secs );
void unlock();
bool locked();
};
class ScopedMutex
{
private:
Mutex &mMutex;
public:
ScopedMutex( Mutex &mutex ) : mMutex( mutex )
{
mMutex.lock();
}
~ScopedMutex()
{
mMutex.unlock();
}
private:
ScopedMutex( const ScopedMutex & );
};
class Condition
{
private:
Mutex &mMutex;
pthread_cond_t mCondition;
public:
Condition( Mutex &mutex );
~Condition();
void wait();
bool wait( int secs );
bool wait( double secs );
void signal();
void broadcast();
};
class Semaphore : public Condition
{
private:
Mutex mMutex;
public:
Semaphore() : Condition( mMutex )
{
}
void wait()
{
mMutex.lock();
Condition::wait();
mMutex.unlock();
}
bool wait( int secs )
{
mMutex.lock();
bool result = Condition::wait( secs );
mMutex.unlock();
return( result );
}
bool wait( double secs )
{
mMutex.lock();
bool result = Condition::wait( secs );
mMutex.unlock();
return( result );
}
void signal()
{
mMutex.lock();
Condition::signal();
mMutex.unlock();
}
void broadcast()
{
mMutex.lock();
Condition::broadcast();
mMutex.unlock();
}
};
template <class T> class ThreadData
{
private:
T mValue;
mutable bool mChanged;
mutable Mutex mMutex;
mutable Condition mCondition;
public:
__attribute__((used)) ThreadData() : mCondition( mMutex )
{
}
__attribute__((used)) ThreadData( T value ) : mValue( value ), mCondition( mMutex )
{
}
//~ThreadData() {}
__attribute__((used)) operator T() const
{
return( getValue() );
}
__attribute__((used)) const T operator=( const T value )
{
return( setValue( value ) );
}
__attribute__((used)) const T getValueImmediate() const
{
return( mValue );
}
__attribute__((used)) T setValueImmediate( const T value )
{
return( mValue = value );
}
__attribute__((used)) const T getValue() const;
__attribute__((used)) T setValue( const T value );
__attribute__((used)) const T getUpdatedValue() const;
__attribute__((used)) const T getUpdatedValue( double secs ) const;
__attribute__((used)) const T getUpdatedValue( int secs ) const;
__attribute__((used)) void updateValueSignal( const T value );
__attribute__((used)) void updateValueBroadcast( const T value );
};
class Thread
{
public:
typedef void *(*ThreadFunc)( void * );
protected:
pthread_t mThread;
Mutex mThreadMutex;
Condition mThreadCondition;
#ifndef SOLARIS
pid_t mPid;
#else
pthread_t mPid;
#endif
bool mStarted;
bool mRunning;
protected:
Thread();
virtual ~Thread();
#ifndef SOLARIS
pid_t id() const
{
pid_t tid;
2015-02-24 22:22:08 +08:00
#ifdef __FreeBSD__
long lwpid;
thr_self(&lwpid);
tid = lwpid;
2015-02-24 22:22:08 +08:00
#else
#ifdef __FreeBSD_kernel__
if ( (syscall(SYS_thr_self, &tid)) < 0 ) // Thread/Process id
#else
tid=syscall(SYS_gettid);
#endif
2015-02-24 22:22:08 +08:00
#endif
return tid;
}
#else
pthread_t id() const
{
return( pthread_self() );
}
#endif
void exit( int status = 0 )
{
//INFO( "Exiting" );
pthread_exit( (void *)&status );
}
static void *mThreadFunc( void *arg );
public:
virtual int run() = 0;
void start();
void join();
void kill( int signal );
bool isThread()
{
return( mPid > -1 && pthread_equal( pthread_self(), mThread ) );
}
bool isStarted() const { return( mStarted ); }
bool isRunning() const { return( mRunning ); }
};
#endif // ZM_THREAD_H