summaryrefslogtreecommitdiffstats
path: root/nsprpub/pr/src/cplus/rcthread.h
blob: b7716d4b993e1bd5d4539b342c9d5180519378a4 (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
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

/* RCThread.h */

#if defined(_RCTHREAD_H)
#else
#define _RCTHREAD_H

#include "rcbase.h"

#include <prthread.h>

class RCInterval;

class PR_IMPLEMENT(RCThreadPrivateData)
{
public:
    RCThreadPrivateData();
    RCThreadPrivateData(const RCThreadPrivateData&);

    virtual ~RCThreadPrivateData();

    virtual void Release() = 0;

};  /* RCThreadPrivateData */

class PR_IMPLEMENT(RCThread): public RCBase
{
public:

    typedef enum
    {
        local = PR_LOCAL_THREAD, global = PR_GLOBAL_THREAD
    } Scope;

    typedef enum
    {
        joinable = PR_JOINABLE_THREAD, unjoinable = PR_UNJOINABLE_THREAD
    } State;

    typedef enum
    {
        first = PR_PRIORITY_FIRST,
        low = PR_PRIORITY_LOW,
        normal = PR_PRIORITY_NORMAL,
        high = PR_PRIORITY_HIGH,
        urgent = PR_PRIORITY_URGENT,
        last = PR_PRIORITY_LAST
    } Priority;

    /*
     * Create a new thread, providing scope and joinability state.
     */
    RCThread(Scope scope, State state, PRUint32 stackSize=0);

    /*
     * New threads are created in a suspended state. It must be 'started"
     * before it begins execution in the class' defined 'RootFunction()'.
     */
    virtual PRStatus Start();

    /*
     * If a thread is created joinable, then the thread's object exists
     * until join is called. The thread that calls join will block until
     * the target thread returns from it's root function.
     */
    virtual PRStatus Join();

    /*
     * The priority of a newly created thread is the same as the creator.
     * The priority may be changed either by the new thread itself, by
     * the creator or any other arbitrary thread.
     */
    virtual void SetPriority(Priority newPriority);


    /*
     * Interrupt another thread, causing it to stop what it
     * is doing and return with a well known error code.
     */
    virtual PRStatus Interrupt();

    /*
     * And in case a thread was interrupted and didn't get a chance
     * to have the notification delivered, a way to cancel the pending
     * status.
     */
    static void ClearInterrupt();

    /*
     * Methods to discover the attributes of an existing thread.
     */
    static PRThread *Self();
    Scope GetScope() const;
    State GetState() const;
    Priority GetPriority() const;

    /*
     * Thread private data
     */
    static PRStatus NewPrivateIndex(PRUintn* index);

    /*
     * Getting it - if you want to modify, make a copy
     */
    static RCThreadPrivateData* GetPrivateData(PRUintn index);

    /*
     * Setting it to <empty> - deletes existing data
     */
    static PRStatus SetPrivateData(PRUintn index);

    /*
     * Setting it - runtime will make a copy, freeing old iff necessary
     */
    static PRStatus SetPrivateData(PRUintn index, RCThreadPrivateData* data);

    /*
     * Scheduling control
     */
    static PRStatus Sleep(const RCInterval& ticks);

    friend void nas_Root(void*);
    friend class RCPrimordialThread;
protected:

    /*
     * The instantiator of a class must not call the destructor. The base
     * implementation of Join will, and if the thread is created unjoinable,
     * then the code that called the RootFunction will call the desctructor.
     */
    virtual ~RCThread();

private:

    /*
     * This is where a newly created thread begins execution. Returning
     * from this function is equivalent to terminating the thread.
     */
    virtual void RootFunction() = 0;

    PRThread *identity;

    /* Threads are unstarted until started - pretty startling */
    enum {ex_unstarted, ex_started} execution;

    /* There is no public default constructor or copy constructor */
    RCThread();
    RCThread(const RCThread&);

    /* And there is no assignment operator */
    void operator=(const RCThread&);

public:
    static RCPrimordialThread *WrapPrimordialThread();

};

/*
** class RCPrimordialThread
*/
class PR_IMPLEMENT(RCPrimordialThread): public RCThread
{
public:
    /*
    ** The primordial thread can (optionally) wait for all created
    ** threads to terminate before allowing the process to exit.
    ** Not calling Cleanup() before returning from main() will cause
    ** the immediate termination of the entire process, including
    ** any running threads.
    */
    static PRStatus Cleanup();

    /*
    ** Only the primordial thread is allowed to adjust the number of
    ** virtual processors of the runtime. It's a lame security thing.
    */
    static PRStatus SetVirtualProcessors(PRIntn count=10);

    friend class RCThread;
private:
    /*
    ** None other than the runtime can create of destruct
    ** a primordial thread. It is fabricated by the runtime
    ** to wrap the thread that initiated the application.
    */
    RCPrimordialThread();
    ~RCPrimordialThread();
    void RootFunction();
};  /* RCPrimordialThread */

#endif /* defined(_RCTHREAD_H) */