michael@0: /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: /* RCThread.h */ michael@0: michael@0: #if defined(_RCTHREAD_H) michael@0: #else michael@0: #define _RCTHREAD_H michael@0: michael@0: #include "rcbase.h" michael@0: michael@0: #include michael@0: michael@0: class RCInterval; michael@0: michael@0: class PR_IMPLEMENT(RCThreadPrivateData) michael@0: { michael@0: public: michael@0: RCThreadPrivateData(); michael@0: RCThreadPrivateData(const RCThreadPrivateData&); michael@0: michael@0: virtual ~RCThreadPrivateData(); michael@0: michael@0: virtual void Release() = 0; michael@0: michael@0: }; /* RCThreadPrivateData */ michael@0: michael@0: class PR_IMPLEMENT(RCThread): public RCBase michael@0: { michael@0: public: michael@0: michael@0: typedef enum michael@0: { michael@0: local = PR_LOCAL_THREAD, global = PR_GLOBAL_THREAD michael@0: } Scope; michael@0: michael@0: typedef enum michael@0: { michael@0: joinable = PR_JOINABLE_THREAD, unjoinable = PR_UNJOINABLE_THREAD michael@0: } State; michael@0: michael@0: typedef enum michael@0: { michael@0: first = PR_PRIORITY_FIRST, michael@0: low = PR_PRIORITY_LOW, michael@0: normal = PR_PRIORITY_NORMAL, michael@0: high = PR_PRIORITY_HIGH, michael@0: urgent = PR_PRIORITY_URGENT, michael@0: last = PR_PRIORITY_LAST michael@0: } Priority; michael@0: michael@0: /* michael@0: * Create a new thread, providing scope and joinability state. michael@0: */ michael@0: RCThread(Scope scope, State state, PRUint32 stackSize=0); michael@0: michael@0: /* michael@0: * New threads are created in a suspended state. It must be 'started" michael@0: * before it begins execution in the class' defined 'RootFunction()'. michael@0: */ michael@0: virtual PRStatus Start(); michael@0: michael@0: /* michael@0: * If a thread is created joinable, then the thread's object exists michael@0: * until join is called. The thread that calls join will block until michael@0: * the target thread returns from it's root function. michael@0: */ michael@0: virtual PRStatus Join(); michael@0: michael@0: /* michael@0: * The priority of a newly created thread is the same as the creator. michael@0: * The priority may be changed either by the new thread itself, by michael@0: * the creator or any other arbitrary thread. michael@0: */ michael@0: virtual void SetPriority(Priority newPriority); michael@0: michael@0: michael@0: /* michael@0: * Interrupt another thread, causing it to stop what it michael@0: * is doing and return with a well known error code. michael@0: */ michael@0: virtual PRStatus Interrupt(); michael@0: michael@0: /* michael@0: * And in case a thread was interrupted and didn't get a chance michael@0: * to have the notification delivered, a way to cancel the pending michael@0: * status. michael@0: */ michael@0: static void ClearInterrupt(); michael@0: michael@0: /* michael@0: * Methods to discover the attributes of an existing thread. michael@0: */ michael@0: static PRThread *Self(); michael@0: Scope GetScope() const; michael@0: State GetState() const; michael@0: Priority GetPriority() const; michael@0: michael@0: /* michael@0: * Thread private data michael@0: */ michael@0: static PRStatus NewPrivateIndex(PRUintn* index); michael@0: michael@0: /* michael@0: * Getting it - if you want to modify, make a copy michael@0: */ michael@0: static RCThreadPrivateData* GetPrivateData(PRUintn index); michael@0: michael@0: /* michael@0: * Setting it to - deletes existing data michael@0: */ michael@0: static PRStatus SetPrivateData(PRUintn index); michael@0: michael@0: /* michael@0: * Setting it - runtime will make a copy, freeing old iff necessary michael@0: */ michael@0: static PRStatus SetPrivateData(PRUintn index, RCThreadPrivateData* data); michael@0: michael@0: /* michael@0: * Scheduling control michael@0: */ michael@0: static PRStatus Sleep(const RCInterval& ticks); michael@0: michael@0: friend void nas_Root(void*); michael@0: friend class RCPrimordialThread; michael@0: protected: michael@0: michael@0: /* michael@0: * The instantiator of a class must not call the destructor. The base michael@0: * implementation of Join will, and if the thread is created unjoinable, michael@0: * then the code that called the RootFunction will call the desctructor. michael@0: */ michael@0: virtual ~RCThread(); michael@0: michael@0: private: michael@0: michael@0: /* michael@0: * This is where a newly created thread begins execution. Returning michael@0: * from this function is equivalent to terminating the thread. michael@0: */ michael@0: virtual void RootFunction() = 0; michael@0: michael@0: PRThread *identity; michael@0: michael@0: /* Threads are unstarted until started - pretty startling */ michael@0: enum {ex_unstarted, ex_started} execution; michael@0: michael@0: /* There is no public default constructor or copy constructor */ michael@0: RCThread(); michael@0: RCThread(const RCThread&); michael@0: michael@0: /* And there is no assignment operator */ michael@0: void operator=(const RCThread&); michael@0: michael@0: public: michael@0: static RCPrimordialThread *WrapPrimordialThread(); michael@0: michael@0: }; michael@0: michael@0: /* michael@0: ** class RCPrimordialThread michael@0: */ michael@0: class PR_IMPLEMENT(RCPrimordialThread): public RCThread michael@0: { michael@0: public: michael@0: /* michael@0: ** The primordial thread can (optionally) wait for all created michael@0: ** threads to terminate before allowing the process to exit. michael@0: ** Not calling Cleanup() before returning from main() will cause michael@0: ** the immediate termination of the entire process, including michael@0: ** any running threads. michael@0: */ michael@0: static PRStatus Cleanup(); michael@0: michael@0: /* michael@0: ** Only the primordial thread is allowed to adjust the number of michael@0: ** virtual processors of the runtime. It's a lame security thing. michael@0: */ michael@0: static PRStatus SetVirtualProcessors(PRIntn count=10); michael@0: michael@0: friend class RCThread; michael@0: private: michael@0: /* michael@0: ** None other than the runtime can create of destruct michael@0: ** a primordial thread. It is fabricated by the runtime michael@0: ** to wrap the thread that initiated the application. michael@0: */ michael@0: RCPrimordialThread(); michael@0: ~RCPrimordialThread(); michael@0: void RootFunction(); michael@0: }; /* RCPrimordialThread */ michael@0: michael@0: #endif /* defined(_RCTHREAD_H) */