/* 

                          Firewall Builder

                 Copyright (C) 2001 NetCitadel, LLC

  Author:  Vadim Zaliva lord@crocodile.org

  $Id: ThreadTools.hh,v 1.6 2002/08/29 00:34:09 vkurland Exp $


  This program is free software which we release under the GNU General Public
  License. You may redistribute and/or modify this program under the terms
  of that 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.
 
  To get a copy of the GNU General Public License, write to the Free Software
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

*/

#ifndef __THREAD_TOOLS_H_FLAG__
#define __THREAD_TOOLS_H_FLAG__

#include <fwbuilder/libfwbuilder-config.h>

#include <time.h> //for time_t definition
#include <glib.h>

#include <string>
#include <queue>

#include <fwbuilder/FWException.hh>

namespace libfwbuilder
{

/**
 * POSIX Mutex wrapper class.
 */
class Mutex
{
    friend class Cond;

    protected:

    GMutex *mutex;

    public:

    Mutex();
    virtual ~Mutex();

    void lock() const;
    void unlock() const;

};

/**
 * POSIX Mutex wrapper class.
 */
class Cond
{
    protected:

    GCond *cond;

    public:

    Cond();
    virtual ~Cond();

    /*
     * Waits until this thread is woken up on this conditional variable, but not longer than 
     * gived timeout. The Mutex is unlocked before falling asleep and locked again 
     * before resuming.
     *
     * @param mutex Mutex to be locked
     * @param timeout_ms timeout in milliseconds. -1 means wait forewer.
     * @returns TRUE, if the thread is woken up in time.
     */
    bool wait(const Mutex &mutex, long timeout_ms=-1) const;
    void signal   () const;
    void broadcast() const;

};

/**
 * This class represents boolean value, access to which
 * is guarded by mutex.
 */
class SyncFlag: public Mutex
{
    private:

    bool value;

    public:

    SyncFlag(bool v=false);

    /**
     * Checks value without locking.
     * Use with lock/unlock()
     */
    bool peek() const;

    /**
     * Changes value without locking.
     * Use with lock/unlock()
     */
    void modify(bool v);

    bool get() const;
    void set(bool v);
    
    operator bool() const;
    SyncFlag& operator=(const SyncFlag &o);
    SyncFlag& operator=(bool v);
};

/**
 * Timeout counter
 */
class TimeoutCounter
{
    private:

    unsigned int timeout ; 
    std::string name     ;
    time_t finish        ;

    public:
    
    /**
     * Creates counter with start time now
     * and end time now+timeout. String is counter
     * name which will be used in thrown exception
     * in check() method.
     * NB: timeout is in whole seconds.
     */
    TimeoutCounter(unsigned int timeout, const std::string &name);

    /** 
     * Starts counter with start time 'now'
     * and end time now+timeout.
     * Could be called several times to restart it.
     */
    void start();
    
    /**
     * retunrs time left before
     * timeout expiration (in seconds)
     */
    unsigned int timeLeft() const;

    /**
     * Returns 'true' if timeout is expired.
     */
    bool isExpired() const;

    /**
     * Throw exception if timeout is expired
     */
    void check() const throw(FWException) ;

    /**
     * Reads from socket/file.
     * Throws FWException if timeout occured.
     */
    ssize_t read(int fd, void *buf, size_t n) const throw(FWException);
    
};

}

#endif //__THREAD_TOOLS_H_FLAG__


