⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 omnithread.h

📁 teamviewer source code vc++
💻 H
📖 第 1 页 / 共 2 页
字号:
public:
    omni_semaphore(unsigned int initial = 1);
    ~omni_semaphore(void);

    void wait(void);
	// if semaphore value is > 0 then decrement it and carry on. If it's
	// already 0 then block.

    int trywait(void);
	// if semaphore value is > 0 then decrement it and return 1 (true).
	// If it's already 0 then return 0 (false).

    void post(void);
	// if any threads are blocked in wait(), wake one of them up. Otherwise
	// increment the value of the semaphore.

private:
    // dummy copy constructor and operator= to prevent copying
    omni_semaphore(const omni_semaphore&);
    omni_semaphore& operator=(const omni_semaphore&);

OMNI_THREAD_EXPOSE:
    OMNI_SEMAPHORE_IMPLEMENTATION
};

//
// A helper class for semaphores, similar to omni_mutex_lock above.
//

class _OMNITHREAD_NTDLL_ omni_semaphore_lock {
    omni_semaphore& sem;
public:
    omni_semaphore_lock(omni_semaphore& s) : sem(s) { sem.wait(); }
    ~omni_semaphore_lock(void) { sem.post(); }
private:
    // dummy copy constructor and operator= to prevent copying
    omni_semaphore_lock(const omni_semaphore_lock&);
    omni_semaphore_lock& operator=(const omni_semaphore_lock&);
};


///////////////////////////////////////////////////////////////////////////
//
// Thread
//
///////////////////////////////////////////////////////////////////////////

class _OMNITHREAD_NTDLL_ omni_thread {

public:

    enum priority_t {
	PRIORITY_LOW,
	PRIORITY_NORMAL,
	PRIORITY_HIGH
    };

    enum state_t {
	STATE_NEW,		// thread object exists but thread hasn't
				// started yet.
	STATE_RUNNING,		// thread is running.
	STATE_TERMINATED	// thread has terminated but storage has not
				// been reclaimed (i.e. waiting to be joined).
    };

    //
    // Constructors set up the thread object but the thread won't start until
    // start() is called. The create method can be used to construct and start
    // a thread in a single call.
    //

    omni_thread(void (*fn)(void*), void* arg = NULL,
		priority_t pri = PRIORITY_NORMAL);
    omni_thread(void* (*fn)(void*), void* arg = NULL,
		priority_t pri = PRIORITY_NORMAL);
	// these constructors create a thread which will run the given function
	// when start() is called.  The thread will be detached if given a
	// function with void return type, undetached if given a function
	// returning void*. If a thread is detached, storage for the thread is
	// reclaimed automatically on termination. Only an undetached thread
	// can be joined.

    void start(void);
	// start() causes a thread created with one of the constructors to
	// start executing the appropriate function.

protected:

    omni_thread(void* arg = NULL, priority_t pri = PRIORITY_NORMAL);
	// this constructor is used in a derived class.  The thread will
	// execute the run() or run_undetached() member functions depending on
	// whether start() or start_undetached() is called respectively.

    void start_undetached(void);
	// can be used with the above constructor in a derived class to cause
	// the thread to be undetached.  In this case the thread executes the
	// run_undetached member function.

    virtual ~omni_thread(void);
	// destructor cannot be called by user (except via a derived class).
	// Use exit() or cancel() instead. This also means a thread object must
	// be allocated with new - it cannot be statically or automatically
	// allocated. The destructor of a class that inherits from omni_thread
	// shouldn't be public either (otherwise the thread object can be
	// destroyed while the underlying thread is still running).

public:

    void join(void**);
	// join causes the calling thread to wait for another's completion,
	// putting the return value in the variable of type void* whose address
	// is given (unless passed a null pointer). Only undetached threads
	// may be joined. Storage for the thread will be reclaimed.

    void set_priority(priority_t);
	// set the priority of the thread.

    static omni_thread* create(void (*fn)(void*), void* arg = NULL,
			       priority_t pri = PRIORITY_NORMAL);
    static omni_thread* create(void* (*fn)(void*), void* arg = NULL,
			       priority_t pri = PRIORITY_NORMAL);
	// create spawns a new thread executing the given function with the
	// given argument at the given priority. Returns a pointer to the
	// thread object. It simply constructs a new thread object then calls
	// start.

    static void exit(void* return_value = NULL);
	// causes the calling thread to terminate.

    static omni_thread* self(void);
	// returns the calling thread's omni_thread object.  If the
	// calling thread is not the main thread and is not created
	// using this library, returns 0. (But see create_dummy()
	// below.)

    static void yield(void);
	// allows another thread to run.

    static void sleep(unsigned long secs, unsigned long nanosecs = 0);
	// sleeps for the given time.

    static void get_time(unsigned long* abs_sec, unsigned long* abs_nsec,
			 unsigned long rel_sec = 0, unsigned long rel_nsec=0);
	// calculates an absolute time in seconds and nanoseconds, suitable for
	// use in timed_waits on condition variables, which is the current time
	// plus the given relative offset.


    static void stacksize(unsigned long sz);
    static unsigned long stacksize();
        // Use this value as the stack size when spawning a new thread.
        // The default value (0) means that the thread library default is
        // to be used.


    // Per-thread data
    //
    // These functions allow you to attach additional data to an
    // omni_thread. First allocate a key for yourself with
    // allocate_key(). Then you can store any object whose class is
    // derived from value_t. Any values still stored in the
    // omni_thread when the thread exits are deleted.
    //
    // These functions are NOT thread safe, so you should be very
    // careful about setting/getting data in a different thread to the
    // current thread.

    typedef unsigned int key_t;
    static key_t allocate_key();

    class value_t {
    public:
      virtual ~value_t() {}
    };

    value_t* set_value(key_t k, value_t* v);
        // Sets a value associated with the given key. The key must
        // have been allocated with allocate_key(). If a value has
        // already been set with the specified key, the old value_t
        // object is deleted and replaced. Returns the value which was
        // set, or zero if the key is invalid.

    value_t* get_value(key_t k);
        // Returns the value associated with the key. If the key is
        // invalid, or there is no value for the key, returns zero.

    value_t* remove_value(key_t k);
        // Removes the value associated with the key and returns it.
        // If the key is invalid, or there is no value for the key,
        // returns zero.


    // Dummy omni_thread
    //
    // Sometimes, an application finds itself with threads created
    // outside of omnithread which must interact with omnithread
    // features such as the per-thread data. In this situation,
    // omni_thread::self() would normally return 0. These functions
    // allow the application to create a suitable dummy omni_thread
    // object.

    static omni_thread* create_dummy(void);
        // creates a dummy omni_thread for the calling thread. Future
        // calls to self() will return the dummy omni_thread. Throws
        // omni_thread_invalid if this thread already has an
        // associated omni_thread (real or dummy).

    static void release_dummy();
        // release the dummy omni_thread for this thread. This
        // function MUST be called before the thread exits. Throws
        // omni_thread_invalid if the calling thread does not have a
        // dummy omni_thread.

    // class ensure_self should be created on the stack. If created in
    // a thread without an associated omni_thread, it creates a dummy
    // thread which is released when the ensure_self object is deleted.

    class ensure_self {
    public:
      inline ensure_self() : _dummy(0)
      {
	_self = omni_thread::self();
	if (!_self) {
	  _dummy = 1;
	  _self  = omni_thread::create_dummy();
	}
      }
      inline ~ensure_self()
      {
	if (_dummy)
	  omni_thread::release_dummy();
      }
      inline omni_thread* self() { return _self; }
    private:
      omni_thread* _self;
      int          _dummy;
    };


private:

    virtual void run(void* /*arg*/) {}
    virtual void* run_undetached(void* /*arg*/) { return NULL; }
	// can be overridden in a derived class.  When constructed using the
	// the constructor omni_thread(void*, priority_t), these functions are
	// called by start() and start_undetached() respectively.

    void common_constructor(void* arg, priority_t pri, int det);
	// implements the common parts of the constructors.

    omni_mutex mutex;
	// used to protect any members which can change after construction,
	// i.e. the following 2 members.

    state_t _state;
    priority_t _priority;

    static omni_mutex* next_id_mutex;
    static int next_id;
    int _id;

    void (*fn_void)(void*);
    void* (*fn_ret)(void*);
    void* thread_arg;
    int detached;
    int _dummy;
    value_t**     _values;
    unsigned long _value_alloc;

    omni_thread(const omni_thread&);
    omni_thread& operator=(const omni_thread&);
    // Not implemented

public:

    priority_t priority(void) {

	// return this thread's priority.

	omni_mutex_lock l(mutex);
	return _priority;
    }

    state_t state(void) {

	// return thread state (invalid, new, running or terminated).

	omni_mutex_lock l(mutex);
	return _state;
    }

    int id(void) { return _id; }
	// return unique thread id within the current process.


    // This class plus the instance of it declared below allows us to execute
    // some initialisation code before main() is called.

    class _OMNITHREAD_NTDLL_ init_t {
    public:
	init_t(void);
        ~init_t(void);
    };

    friend class init_t;
    friend class omni_thread_dummy;

OMNI_THREAD_EXPOSE:
    OMNI_THREAD_IMPLEMENTATION
};

#ifndef __rtems__
static omni_thread::init_t omni_thread_init;
#else
// RTEMS calls global Ctor/Dtor in a context that is not
// a posix thread. Calls to functions to pthread_self() in
// that context returns NULL. 
// So, for RTEMS we will make the thread initialization at the
// beginning of the Init task that has a posix context.
#endif

#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -