summaryrefslogtreecommitdiff
path: root/cpp/include/IceUtil/Thread.h
blob: 5dbc94365a053e7c343b2cdb4fd41104eb6f4a8d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
// **********************************************************************
//
// Copyright (c) 2003
// ZeroC, Inc.
// Billerica, MA, USA
//
// All Rights Reserved.
//
// Ice is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License version 2 as published by
// the Free Software Foundation.
//
// **********************************************************************

#ifndef ICE_UTIL_THREAD_H
#define ICE_UTIL_THREAD_H

#include <IceUtil/Shared.h>
#include <IceUtil/Handle.h>

namespace IceUtil
{

class Time;

#ifdef _WIN32
struct HandleWrapper : public Shared
{
    // Inline for performance reasons.
    HandleWrapper(HANDLE h) :
	handle(h)
    {
    }

    // Inline for performance reasons.
    virtual ~HandleWrapper()
    {
	if(handle)
	{
	    CloseHandle(handle);
	}
    }

    HANDLE handle;
};

typedef Handle<HandleWrapper> HandleWrapperPtr;
#endif

class ICE_UTIL_API ThreadControl
{
public:

    ThreadControl();

#ifdef _WIN32
    ThreadControl(const HandleWrapperPtr&, unsigned int);
#else
    ThreadControl(pthread_t);
#endif

    bool operator==(const ThreadControl&) const;
    bool operator!=(const ThreadControl&) const;
    bool operator<(const ThreadControl&) const;

    //
    // Wait until the controlled thread terminates. The call has POSIX
    // semantics.
    //
    // At most one thread can wait for the termination of a given
    // thread.C alling join on a thread on which another thread is
    // already waiting for termination results in undefined behaviour.
    // Joining with a thread after having joined with it previously,
    // or joining with a detached thread raises ThreadSyscallException.
    //
    void join();

    //
    // Detach a thread. Once a thread is detached, it cannot be detached
    // again, nor can it be joined with. Every thread must either be
    // joined with or detached exactly once. Detaching a thread a second
    // time, or detaching a thread that was previously joined with raises
    // ThreadSyscallException.
    //
    void detach();

    //
    // Check whether a thread is still alive. This is useful to implement
    // a non-blocking join().
    //
    bool isAlive() const;

    static void sleep(const Time&);
    static void yield();

private:

#ifdef _WIN32
    HandleWrapperPtr _handle;
    unsigned int _id;
#else
    pthread_t _id;
#endif

    bool _detached;
};

class ICE_UTIL_API Thread : virtual public IceUtil::Shared
{
public:
#ifdef _WIN32
    typedef unsigned int ThreadId;
#else
    typedef pthread_t ThreadId;
#endif

    Thread();
    virtual ~Thread();

    ThreadId id() const;

    virtual void run() = 0;

    ThreadControl start();

    ThreadControl getThreadControl() const;

    bool operator==(const Thread&) const;
    bool operator!=(const Thread&) const;
    bool operator<(const Thread&) const;

private:

    bool _started;
#ifdef _WIN32
    unsigned int _id;
    HandleWrapperPtr _handle;
#else
    pthread_t _id;
#endif
};

typedef Handle<Thread> ThreadPtr;
    
}

#endif